• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

wurstscript / WurstScript / 228

29 Nov 2023 05:00PM UTC coverage: 62.48% (-0.09%) from 62.574%
228

push

circleci

web-flow
Show dialog for choosing game path, cleanup (#1083)

* show dialog for choosing game path

* cleanup code

* remove logs and refactor

* remove confusing mpq error, make some mpq loads readonly

17295 of 27681 relevant lines covered (62.48%)

0.62 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

74.7
de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/translation/imtranslation/Flatten.java
1
package de.peeeq.wurstscript.translation.imtranslation;
2

3
import com.google.common.base.Preconditions;
4
import com.google.common.collect.ImmutableList;
5
import com.google.common.collect.Lists;
6
import de.peeeq.wurstscript.WurstOperator;
7
import de.peeeq.wurstscript.jassIm.ImAlloc;
8
import de.peeeq.wurstscript.jassIm.ImCast;
9
import de.peeeq.wurstscript.jassIm.ImCompiletimeExpr;
10
import de.peeeq.wurstscript.jassIm.ImDealloc;
11
import de.peeeq.wurstscript.jassIm.ImExitwhen;
12
import de.peeeq.wurstscript.jassIm.ImExprs;
13
import de.peeeq.wurstscript.jassIm.ImFunction;
14
import de.peeeq.wurstscript.jassIm.ImFunctionCall;
15
import de.peeeq.wurstscript.jassIm.ImGetStackTrace;
16
import de.peeeq.wurstscript.jassIm.ImIf;
17
import de.peeeq.wurstscript.jassIm.ImInstanceof;
18
import de.peeeq.wurstscript.jassIm.ImLoop;
19
import de.peeeq.wurstscript.jassIm.ImMemberAccess;
20
import de.peeeq.wurstscript.jassIm.ImMethodCall;
21
import de.peeeq.wurstscript.jassIm.ImOperatorCall;
22
import de.peeeq.wurstscript.jassIm.ImProg;
23
import de.peeeq.wurstscript.jassIm.ImReturn;
24
import de.peeeq.wurstscript.jassIm.ImSet;
25
import de.peeeq.wurstscript.jassIm.ImStatementExpr;
26
import de.peeeq.wurstscript.jassIm.ImStmts;
27
import de.peeeq.wurstscript.jassIm.ImTupleExpr;
28
import de.peeeq.wurstscript.jassIm.ImTupleSelection;
29
import de.peeeq.wurstscript.jassIm.ImTypeIdOfClass;
30
import de.peeeq.wurstscript.jassIm.ImTypeIdOfObj;
31
import de.peeeq.wurstscript.jassIm.ImTypeVarDispatch;
32
import de.peeeq.wurstscript.jassIm.ImVar;
33
import de.peeeq.wurstscript.jassIm.ImVarAccess;
34
import de.peeeq.wurstscript.jassIm.ImVarArrayAccess;
35
import de.peeeq.wurstscript.jassIm.ImVarargLoop;
36
import de.peeeq.wurstscript.jassIm.*;
37
import de.peeeq.wurstscript.translation.imtranslation.purity.Pure;
38
import de.peeeq.wurstscript.types.WurstTypeBool;
39

40
import java.util.ArrayList;
41
import java.util.Arrays;
42
import java.util.Collections;
43
import java.util.List;
44

45
import static de.peeeq.wurstscript.jassIm.JassIm.*;
46

47
/**
48
 * flattening expressions and statements
49
 * after flattening there will be no more StatementExprs
50
 * for expressions there might be a StatementExpr on the top level
51
 * <p>
52
 * TODO wait, its not that easy: you have to make sure that the execution order is not changed for functions and global variables
53
 * <p>
54
 * e.g. take
55
 * <p>
56
 * y = x + StatementExpr(setX(4), 2)
57
 * <p>
58
 * this should be translated to:
59
 * <p>
60
 * temp = x
61
 * setX(4)
62
 * y = temp + 2
63
 * <p>
64
 * <p>
65
 * alternative: relax language semantics
66
 */
67
public class Flatten {
×
68

69

70
    public static Result flatten(ImTypeVarDispatch imTypeVarDispatch, ImTranslator translator, ImFunction f) {
71
        throw new RuntimeException("called too early");
×
72
    }
73

74
    public static Result flatten(ImCast imCast, ImTranslator translator, ImFunction f) {
75
        Result res = imCast.getExpr().flatten(translator, f);
1✔
76
        return new Result(res.stmts, ImCast(res.expr, imCast.getToType()));
1✔
77
    }
78

79
    public static Result flatten(ImTypeIdOfObj e, ImTranslator translator, ImFunction f) {
80
        Result o = e.getObj().flatten(translator, f);
×
81
        return new Result(o.stmts, ImTypeIdOfObj(o.expr, e.getClazz()));
×
82
    }
83

84
    public static Result flatten(ImTypeIdOfClass e, ImTranslator translator, ImFunction f) {
85
        e.setParent(null);
×
86
        return new Result(e);
×
87
    }
88

89
    public static Result flatten(ImDealloc d, ImTranslator translator, ImFunction f) {
90
        Result o = d.getObj().flatten(translator, f);
1✔
91
        return new Result(o.stmts, ImDealloc(d.getTrace(), d.getClazz(), o.expr));
1✔
92
    }
93

94
    public static Result flatten(ImInstanceof e, ImTranslator translator, ImFunction f) {
95
        Result res = e.getObj().flatten(translator, f);
×
96
        return new Result(res.stmts, ImInstanceof(res.expr, e.getClazz()));
×
97
    }
98

99
    public static Result flatten(ImAlloc e, ImTranslator translator, ImFunction f) {
100
        e.setParent(null);
1✔
101
        return new Result(e);
1✔
102
    }
103

104

105
    public static class Result {
106

107
        List<ImStmt> stmts;
108
        final ImExpr expr;
109

110
        public Result(List<ImStmt> stmts, ImExpr expr) {
1✔
111
            Preconditions.checkArgument(expr.getParent() == null, "expression must not have a parent");
1✔
112
            Preconditions.checkArgument(stmts.stream().allMatch(s -> s.getParent() == null), "statement must not have a parent");
1✔
113
            this.stmts = stmts;
1✔
114
            this.expr = expr;
1✔
115
        }
1✔
116

117
        public Result(ImExpr expr) {
118
            this(Collections.emptyList(), expr);
1✔
119
        }
1✔
120

121
        public Result(List<ImStmt> stmts) {
122
            this(stmts, ImHelper.nullExpr());
1✔
123
        }
1✔
124

125
        public void intoStatements(List<ImStmt> result, ImTranslator t, ImFunction f) {
126
            result.addAll(stmts);
1✔
127
            exprToStatements(result, expr, t, f);
1✔
128
        }
1✔
129

130
        public List<ImStmt> getStmts() {
131
            return stmts;
×
132
        }
133

134
        public ImExpr getExpr() {
135
            return expr;
×
136
        }
137

138
        public ImStatementExpr toStatementExpr() {
139
            return JassIm.ImStatementExpr(JassIm.ImStmts(stmts), expr);
×
140
        }
141

142
        public void addStmts(List<ImStmt> stmts) {
143
            if (stmts.isEmpty()) {
1✔
144
                return;
1✔
145
            }
146
            this.stmts = new ArrayList<>(this.stmts);
1✔
147
            this.stmts.addAll(stmts);
1✔
148
        }
1✔
149
    }
150

151
    public static class ResultL extends Result {
152
        public ResultL(List<ImStmt> stmts, ImLExpr expr) {
153
            super(stmts, expr);
1✔
154
        }
1✔
155

156
        public ResultL(ImLExpr expr) {
157
            super(expr);
1✔
158
        }
1✔
159

160
        @Override
161
        public ImLExpr getExpr() {
162
            return (ImLExpr) super.getExpr();
×
163
        }
164
    }
165

166
    public static class MultiResult {
167

168
        final List<ImStmt> stmts;
169
        final List<ImExpr> exprs;
170

171
        public MultiResult(List<ImStmt> stmts, List<ImExpr> exprs) {
1✔
172
            this.stmts = stmts;
1✔
173
            this.exprs = exprs;
1✔
174
        }
1✔
175

176

177
        public ImExpr expr(int i) {
178
            return exprs.get(i);
×
179
        }
180

181
    }
182

183
    public static class MultiResultL extends MultiResult {
184

185
        public MultiResultL(List<ImStmt> stmts, List<ImLExpr> exprs) {
186
            super(stmts, ImmutableList.copyOf(exprs));
×
187
        }
×
188

189
        public ImLExpr expr(int i) {
190
            return (ImLExpr) super.expr(i);
×
191
        }
192

193
        public List<ImLExpr> getLExprs() {
194
            //noinspection unchecked,rawtypes
195
            return (List) exprs;
×
196
        }
197

198
    }
199

200
    private static void exprToStatements(List<ImStmt> result, Element e, ImTranslator t, ImFunction f) {
201
        if (e instanceof ImFunctionCall) {
1✔
202
            Result res = flatten((ImFunctionCall) e, t, f);
1✔
203
            result.addAll(res.stmts);
1✔
204
            result.add(res.expr);
1✔
205
        } else if (e instanceof ImDealloc) {
1✔
206
            Result res = flatten((ImDealloc) e, t, f);
1✔
207
            result.addAll(res.stmts);
1✔
208
            result.add(res.expr);
1✔
209
        } else if (e instanceof ImMethodCall) {
1✔
210
            Result res = flatten((ImMethodCall) e, t, f);
1✔
211
            result.addAll(res.stmts);
1✔
212
            result.add(res.expr);
1✔
213
        } else if (e instanceof ImStatementExpr) {
1✔
214
            ImStatementExpr e2 = (ImStatementExpr) e;
×
215
            flattenStatementsInto(result, e2.getStatements(), t, f);
×
216
            exprToStatements(result, e2, t, f);
×
217
        } else if (e instanceof ImOperatorCall &&
1✔
218
            (((ImOperatorCall) e).getOp() == WurstOperator.AND
1✔
219
                || ((ImOperatorCall) e).getOp() == WurstOperator.OR)) {
1✔
220
            // short circuiting operators have to be handled in a special way:
221
            // we translate them to if statements when necessary
222
            ImOperatorCall oc = (ImOperatorCall) e;
1✔
223
            ImStmts rightStmts = JassIm.ImStmts();
1✔
224
            ImExpr right = oc.getArguments().get(1);
1✔
225
            ImExpr left = oc.getArguments().get(0);
1✔
226
            exprToStatements(rightStmts, right, t, f);
1✔
227
            if (rightStmts.isEmpty()) {
1✔
228
                // if no statements for righthand side, then just use left hand side as result
229
                exprToStatements(result, left, t, f);
1✔
230
            } else {
231
                // if righthandside contains some statements, transform the whole thing to an if statement:
232
                if (oc.getOp() == WurstOperator.AND) {
1✔
233
                    result.add(JassIm.ImIf(e.attrTrace(), left.copy(), rightStmts, JassIm.ImStmts()));
1✔
234
                } else { // WurstOperator.OR
235
                    result.add(JassIm.ImIf(e.attrTrace(), left.copy(), JassIm.ImStmts(), rightStmts));
×
236
                }
237
            }
238
        } else {
1✔
239
            // visit children:
240
            for (int i = 0; i < e.size(); i++) {
1✔
241
                exprToStatements(result, e.get(i), t, f);
1✔
242
            }
243
        }
244
    }
1✔
245

246

247
    private static ImStmts flattenStatements(ImStmts statements, ImTranslator t, ImFunction f) {
248
        ImStmts result = ImStmts();
1✔
249
        flattenStatementsInto(result, statements, t, f);
1✔
250
        return result;
1✔
251
    }
252

253
    private static void flattenStatementsInto(List<ImStmt> result, ImStmts statements, ImTranslator t, ImFunction f) {
254
        for (ImStmt s : statements) {
1✔
255
            s.flatten(t, f).intoStatements(result, t, f);
1✔
256
        }
1✔
257
    }
1✔
258

259
    public static Result flatten(ImExitwhen s, ImTranslator t, ImFunction f) {
260
        Result cond = s.getCondition().flatten(t, f);
1✔
261
        List<ImStmt> stmts = Lists.newArrayList(cond.stmts);
1✔
262
        stmts.add(ImExitwhen(s.getTrace(), cond.expr));
1✔
263
        return new Result(stmts);
1✔
264
    }
265

266

267
    public static Result flatten(ImIf s, ImTranslator t, ImFunction f) {
268
        Result cond = s.getCondition().flatten(t, f);
1✔
269
        List<ImStmt> stmts = Lists.newArrayList(cond.stmts);
1✔
270
        stmts.add(
1✔
271
            JassIm.ImIf(s.getTrace(), cond.expr,
1✔
272
                flattenStatements(s.getThenBlock(), t, f),
1✔
273
                flattenStatements(s.getElseBlock(), t, f)));
1✔
274
        return new Result(stmts);
1✔
275
    }
276

277

278
    public static Result flatten(ImLoop s, ImTranslator t, ImFunction f) {
279
        return new Result(Collections.singletonList(
1✔
280
            JassIm.ImLoop(s.getTrace(), flattenStatements(s.getBody(), t, f))));
1✔
281
    }
282

283
    public static Result flatten(ImReturn s, ImTranslator t, ImFunction f) {
284
        if (s.getReturnValue() instanceof ImExpr) {
1✔
285
            ImExpr ret = (ImExpr) s.getReturnValue();
1✔
286
            Result result = ret.flatten(t, f);
1✔
287
            List<ImStmt> stmts = Lists.newArrayList(result.stmts);
1✔
288
            stmts.add(ImReturn(s.getTrace(), result.expr));
1✔
289
            return new Result(stmts);
1✔
290
        } else {
291
            s.setParent(null);
1✔
292
            return new Result(Collections.singletonList(s));
1✔
293
        }
294
    }
295

296

297
    public static Result flatten(ImSet s, ImTranslator t, ImFunction f) {
298
        Result l = s.getLeft().flatten(t, f);
1✔
299
        Result r = s.getRight().flatten(t, f);
1✔
300
        List<ImStmt> stmts = Lists.newArrayList(l.stmts);
1✔
301
        stmts.addAll(r.stmts);
1✔
302
        stmts.add(JassIm.ImSet(s.getTrace(), (ImLExpr) l.expr, r.expr));
1✔
303
        return new Result(stmts);
1✔
304
    }
305

306

307
    public static Result flatten(ImFunctionCall e, ImTranslator t, ImFunction f) {
308
        MultiResult r = flattenExprs(t, f, e.getArguments());
1✔
309
        return new Result(r.stmts, ImFunctionCall(e.getTrace(), e.getFunc(), e.getTypeArguments().copy(), ImExprs(r.exprs), e.getTuplesEliminated(), e.getCallType()));
1✔
310
    }
311

312
    public static Result flatten(ImMethodCall e, ImTranslator t, ImFunction f) {
313
        Result recR = e.getReceiver().flatten(t, f);
1✔
314
        MultiResult argsR = flattenExprs(t, f, e.getArguments());
1✔
315
        Result res = new Result(recR.stmts, ImMethodCall(e.getTrace(), e.getMethod(), e.getTypeArguments().copy(), recR.expr, ImExprs(argsR.exprs), e.getTuplesEliminated()));
1✔
316
        res.addStmts(argsR.stmts);
1✔
317
        return res;
1✔
318
    }
319

320
    public static Result flatten(ImOperatorCall e, ImTranslator t, ImFunction f) {
321
        // TODO special case and, or
322
        de.peeeq.wurstscript.ast.Element trace = e.attrTrace();
1✔
323
        switch (e.getOp()) {
1✔
324
            case AND: {
325
                Result left = e.getArguments().get(0).flatten(t, f);
1✔
326
                Result right = e.getArguments().get(1).flatten(t, f);
1✔
327

328
                if (right.stmts.isEmpty()) {
1✔
329
                    return new Result(left.stmts, JassIm.ImOperatorCall(WurstOperator.AND, ImExprs(left.expr, right.expr)));
1✔
330
                } else {
331
                    ArrayList<ImStmt> stmts = Lists.newArrayList(left.stmts);
1✔
332
                    ImVar tempVar = JassIm.ImVar(e.attrTrace(), WurstTypeBool.instance().imTranslateType(t), "andLeft", false);
1✔
333
                    f.getLocals().add(tempVar);
1✔
334
                    ImStmts thenBlock = JassIm.ImStmts();
1✔
335
                    // if left is true then check right
336
                    thenBlock.addAll(right.stmts);
1✔
337
                    thenBlock.add(ImSet(trace, ImVarAccess(tempVar), right.expr));
1✔
338
                    // else the result is false
339
                    ImStmts elseBlock = JassIm.ImStmts(ImSet(trace, ImVarAccess(tempVar), JassIm.ImBoolVal(false)));
1✔
340
                    stmts.add(ImIf(trace, left.expr, thenBlock, elseBlock));
1✔
341
                    return new Result(stmts, JassIm.ImVarAccess(tempVar));
1✔
342
                }
343
            }
344
            case OR: {
345
                Result left = e.getArguments().get(0).flatten(t, f);
1✔
346
                Result right = e.getArguments().get(1).flatten(t, f);
1✔
347

348
                if (right.stmts.isEmpty()) {
1✔
349
                    return new Result(left.stmts, JassIm.ImOperatorCall(WurstOperator.OR, ImExprs(left.expr, right.expr)));
1✔
350
                } else {
351
                    ArrayList<ImStmt> stmts = Lists.newArrayList(left.stmts);
1✔
352
                    ImVar tempVar = JassIm.ImVar(trace, WurstTypeBool.instance().imTranslateType(t), "andLeft", false);
1✔
353
                    f.getLocals().add(tempVar);
1✔
354
                    // if left is true then result is ture
355
                    ImStmts thenBlock = JassIm.ImStmts(ImSet(trace, ImVarAccess(tempVar), JassIm.ImBoolVal(true)));
1✔
356
                    // else check right
357
                    ImStmts elseBlock = JassIm.ImStmts();
1✔
358
                    elseBlock.addAll(right.stmts);
1✔
359
                    elseBlock.add(ImSet(trace, ImVarAccess(tempVar), right.expr));
1✔
360
                    stmts.add(ImIf(trace, left.expr, thenBlock, elseBlock));
1✔
361
                    return new Result(stmts, JassIm.ImVarAccess(tempVar));
1✔
362
                }
363
            }
364
            default:
365
                MultiResult r = flattenExprs(t, f, e.getArguments());
1✔
366
                return new Result(r.stmts, JassIm.ImOperatorCall(e.getOp(), ImExprs(r.exprs)));
1✔
367
        }
368
    }
369

370

371
    public static Result flatten(ImConst e, ImTranslator t, ImFunction f) {
372
        e.setParent(null);
1✔
373
        return new Result(e);
1✔
374
    }
375

376

377
    public static Result flatten(ImStatementExpr e, ImTranslator t, ImFunction f) {
378
        List<ImStmt> stmts = Lists.newArrayList();
1✔
379
        flattenStatementsInto(stmts, e.getStatements(), t, f);
1✔
380
        Result r = e.getExpr().flatten(t, f);
1✔
381
        stmts.addAll(r.stmts);
1✔
382
        return new Result(stmts, r.expr);
1✔
383
    }
384

385
    public static ResultL flattenL(ImStatementExpr e, ImTranslator t, ImFunction f) {
386
        List<ImStmt> stmts = Lists.newArrayList();
×
387
        flattenStatementsInto(stmts, e.getStatements(), t, f);
×
388
        ResultL r = ((ImLExpr) e.getExpr()).flattenL(t, f);
×
389
        stmts.addAll(r.stmts);
×
390
        return new ResultL(stmts, r.getExpr());
×
391
    }
392

393

394
    public static Result flatten(ImTupleExpr e, ImTranslator t, ImFunction f) {
395
        MultiResult r = flattenExprs(t, f, e.getExprs());
1✔
396
        return new Result(r.stmts, JassIm.ImTupleExpr(ImExprs(r.exprs)));
1✔
397
    }
398

399
    public static ResultL flattenL(ImTupleExpr e, ImTranslator t, ImFunction f) {
400
        @SuppressWarnings({"unchecked", "rawtypes"})
401
        List<ImLExpr> exprs = (List) e.getExprs();
×
402
        MultiResultL r = flattenExprsL(t, f, exprs);
×
403
        ImExprs newExprs = ImExprs();
×
404
        newExprs.addAll(r.getLExprs());
×
405
        return new ResultL(r.stmts, JassIm.ImTupleExpr(newExprs));
×
406
    }
407

408

409
    public static Result flatten(ImTupleSelection e, ImTranslator t, ImFunction f) {
410
        return flattenL(e, t, f);
1✔
411
    }
412

413
    public static ResultL flattenL(ImTupleSelection e, ImTranslator t, ImFunction f) {
414
        Result r = e.getTupleExpr().flatten(t, f);
1✔
415
        ImLExpr tupleExpr;
416
        List<ImStmt> stmts;
417
        if (r.expr instanceof ImLExpr) {
1✔
418
            tupleExpr = (ImLExpr) r.expr;
1✔
419
            stmts = r.stmts;
1✔
420
        } else {
421
            // in the unlikely event that this is not an l-value (e.g. foo().x)
422
            // we create a temporary variable and store the result there
423
            ImVar v = JassIm.ImVar(e.attrTrace(), r.expr.attrTyp(), "tuple_temp", false);
×
424
            f.getLocals().add(v);
×
425
            stmts = new ArrayList<>(r.stmts);
×
426
            stmts.add(JassIm.ImSet(e.attrTrace(), ImVarAccess(v), r.expr));
×
427
            tupleExpr = JassIm.ImVarAccess(v);
×
428
        }
429
        return new ResultL(stmts, JassIm.ImTupleSelection(tupleExpr, e.getTupleIndex()));
1✔
430
    }
431

432
    public static ResultL flattenL(ImVarAccess e, ImTranslator t, ImFunction f) {
433
        e.setParent(null);
1✔
434
        return new ResultL(e);
1✔
435
    }
436

437

438
    public static ResultL flatten(ImLExpr e, ImTranslator t, ImFunction f) {
439
        return e.flattenL(t, f);
1✔
440
    }
441

442
    public static ResultL flattenL(ImVarArrayAccess e, ImTranslator t, ImFunction f) {
443
        MultiResult indexes = flattenExprs(t, f, e.getIndexes());
1✔
444
        return new ResultL(indexes.stmts, ImVarArrayAccess(e.getTrace(), e.getVar(), ImExprs(indexes.exprs)));
1✔
445
    }
446

447

448
    public static void flattenFunc(ImFunction f, ImTranslator translator) {
449
        ImStmts newBody = flattenStatements(f.getBody(), translator, f);
1✔
450
        f.setBody(newBody);
1✔
451
    }
1✔
452

453
    public static void flattenProg(ImProg imProg, ImTranslator translator) {
454
        imProg.getFunctions().parallelStream().forEach(f -> f.flatten(translator));
1✔
455
        imProg.getClasses().parallelStream().forEach(c ->
1✔
456
            c.getFunctions().parallelStream().forEach(f -> f.flatten(translator)));
1✔
457

458
        translator.assertProperties(AssertProperty.FLAT);
1✔
459
    }
1✔
460

461
    public static Result flatten(ImCompiletimeExpr e, ImTranslator translator, ImFunction f) {
462
        e.setParent(null);
×
463
        return new Result(e);
×
464
    }
465

466

467
    private static MultiResult flattenExprs(ImTranslator t, ImFunction f, ImExpr... exprs) {
468
        return flattenExprs(t, f, Arrays.asList(exprs));
×
469
    }
470

471
    private static MultiResult flattenExprs(ImTranslator t, ImFunction f, List<ImExpr> exprs) {
472
        // TODO optimize this function to use less temporary variables
473
        List<ImStmt> stmts = Lists.newArrayList();
1✔
474
        List<ImExpr> newExprs = Lists.newArrayList();
1✔
475
        List<Result> results = Lists.newArrayList();
1✔
476
        int withStmts = -1;
1✔
477
        for (int i = 0; i < exprs.size(); i++) {
1✔
478
            Result r = exprs.get(i).flatten(t, f);
1✔
479
            results.add(r);
1✔
480
            if (!r.stmts.isEmpty()) {
1✔
481
                withStmts = i;
1✔
482
            }
483
        }
484
        for (int i = 0; i < exprs.size(); i++) {
1✔
485
            ImExpr e = exprs.get(i);
1✔
486
            Result r = results.get(i);
1✔
487

488
            stmts.addAll(r.stmts);
1✔
489
            if (r.expr.attrPurity() instanceof Pure
1✔
490
                || i >= withStmts) {
491
                newExprs.add(r.expr);
1✔
492
            } else {
493
                ImVar tempVar = JassIm.ImVar(e.attrTrace(), r.expr.attrTyp(), "temp", false);
1✔
494
                f.getLocals().add(tempVar);
1✔
495
                stmts.add(ImSet(e.attrTrace(), ImVarAccess(tempVar), r.expr));
1✔
496
                newExprs.add(JassIm.ImVarAccess(tempVar));
1✔
497
            }
498
        }
499
        return new MultiResult(stmts, newExprs);
1✔
500
    }
501

502
    private static MultiResultL flattenExprsL(ImTranslator t, ImFunction f, List<ImLExpr> exprs) {
503
        // TODO optimize this function to use less temporary variables
504
        List<ImStmt> stmts = Lists.newArrayList();
×
505
        List<ImLExpr> newExprs = Lists.newArrayList();
×
506
        List<ResultL> results = Lists.newArrayList();
×
507
        int withStmts = -1;
×
508
        for (int i = 0; i < exprs.size(); i++) {
×
509
            ResultL r = exprs.get(i).flattenL(t, f);
×
510
            results.add(r);
×
511
            if (!r.stmts.isEmpty()) {
×
512
                withStmts = i;
×
513
            }
514
        }
515
        for (int i = 0; i < exprs.size(); i++) {
×
516
            ImExpr e = exprs.get(i);
×
517
            ResultL r = results.get(i);
×
518

519
            stmts.addAll(r.stmts);
×
520
            if (r.expr.attrPurity() instanceof Pure
×
521
                || i >= withStmts) {
522
                newExprs.add(r.getExpr());
×
523
            } else {
524
                ImVar tempVar = JassIm.ImVar(e.attrTrace(), r.expr.attrTyp(), "temp", false);
×
525
                f.getLocals().add(tempVar);
×
526
                stmts.add(ImSet(e.attrTrace(), ImVarAccess(tempVar), r.expr));
×
527
                newExprs.add(JassIm.ImVarAccess(tempVar));
×
528
            }
529
        }
530
        return new MultiResultL(stmts, newExprs);
×
531
    }
532

533

534
    public static Result flatten(ImMemberAccess e,
535
                                 ImTranslator t, ImFunction f) {
536
        Result rr = e.getReceiver().flatten(t, f);
1✔
537
        MultiResult ir = flattenExprs(t, f, e.getIndexes());
1✔
538
        Result res = new Result(rr.stmts, ImMemberAccess(e.getTrace(), rr.expr, e.getTypeArguments().copy(), e.getVar(), ImExprs(ir.exprs)));
1✔
539
        res.addStmts(ir.stmts);
1✔
540
        return res;
1✔
541
    }
542

543
    public static ResultL flattenL(ImMemberAccess e,
544
                                   ImTranslator t, ImFunction f) {
545
        Result rr = e.getReceiver().flatten(t, f);
×
546
        MultiResult ir = flattenExprs(t, f, e.getIndexes());
×
547
        ResultL res = new ResultL(rr.stmts, ImMemberAccess(e.getTrace(), rr.expr, e.getTypeArguments(), e.getVar(), ImExprs(ir.exprs)));
×
548
        res.addStmts(ir.stmts);
×
549
        return res;
×
550
    }
551

552

553
    public static Result flatten(ImGetStackTrace e, ImTranslator translator,
554
                                 ImFunction f) {
555
        e.setParent(null);
1✔
556
        return new Result(e);
1✔
557
    }
558

559

560
    public static Result flatten(ImVarargLoop s, ImTranslator translator, ImFunction f) {
561
        return new Result(Collections.singletonList(
1✔
562
            JassIm.ImVarargLoop(s.getTrace(), flattenStatements(s.getBody(), translator, f), s.getLoopVar())));
1✔
563
    }
564

565

566
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc