• 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

97.02
de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/translation/imtranslation/MultiArrayEliminator.java
1
package de.peeeq.wurstscript.translation.imtranslation;
2

3
import com.google.common.collect.Lists;
4
import com.google.common.collect.Maps;
5
import de.peeeq.wurstscript.WurstOperator;
6
import de.peeeq.wurstscript.attributes.CompileError;
7
import de.peeeq.wurstscript.jassIm.*;
8
import de.peeeq.wurstscript.translation.imoptimizer.Replacer;
9
import de.peeeq.wurstscript.types.TypesHelper;
10

11
import java.util.HashMap;
12
import java.util.List;
13
import java.util.Map;
14

15
public class MultiArrayEliminator {
16
    private final ImProg prog;
17
    private final HashMap<ImVar, GetSetPair> getSetMap = Maps.newHashMap();
1✔
18
    private final ImTranslator translator;
19
    private final boolean generateStacktraces;
20
    private final Replacer replacer = new Replacer();
1✔
21

22
    private static class GetSetPair {
23
        ImFunction getter;
24
        ImFunction setter;
25

26
        public GetSetPair(ImFunction get, ImFunction set) {
1✔
27
            getter = get;
1✔
28
            setter = set;
1✔
29
        }
1✔
30
    }
31

32
    public MultiArrayEliminator(ImProg imProg, ImTranslator tr, boolean generateStacktraces) {
1✔
33
        this.prog = imProg;
1✔
34
        this.translator = tr;
1✔
35
        this.generateStacktraces = generateStacktraces;
1✔
36
    }
1✔
37

38
    public void run() {
39
        List<ImVar> oldVars = Lists.newArrayList();
1✔
40
        List<ImVar> newVars = Lists.newArrayList();
1✔
41
        for (ImVar v : prog.getGlobals()) {
1✔
42
            if (v.getType() instanceof ImArrayTypeMulti) {
1✔
43
                ImArrayTypeMulti type = (ImArrayTypeMulti) v.getType();
1✔
44
                List<Integer> arraySize = type.getArraySize();
1✔
45
                if (arraySize.size() == 2) {
1✔
46
                    oldVars.add(v);
1✔
47
                    int size0 = arraySize.get(0);
1✔
48
                    List<ImVar> newArrays = Lists.newArrayList();
1✔
49
                    for (int i = 0; i < size0; i++) {
1✔
50
                        ImVar newVar = JassIm.ImVar(v.getTrace(), JassIm.ImArrayType(type.getEntryType()), v.getName() + "_" + i, false);
1✔
51
                        newArrays.add(newVar);
1✔
52
                    }
53
                    ImFunction setFunc = generateSetFunc(v, newArrays);
1✔
54
                    ImFunction getFunc = generateGetFunc(v, newArrays);
1✔
55
                    prog.getFunctions().add(setFunc);
1✔
56
                    prog.getFunctions().add(getFunc);
1✔
57
                    getSetMap.put(v, new GetSetPair(getFunc, setFunc));
1✔
58

59
                    newVars.addAll(newArrays);
1✔
60
                } else if (arraySize.size() == 1) {
1✔
61
                    // just remove the size
62
                    v.setType(JassIm.ImArrayType(type.getEntryType()));
1✔
63
                } else {
64
                    throw new CompileError(v, "Unsupported array sizes " + arraySize);
×
65
                }
66
            }
67
        }
1✔
68
        for (ImFunction function : prog.getFunctions()) {
1✔
69
            for (ImVar v : function.getLocals()) {
1✔
70
                if (v.getType() instanceof ImArrayTypeMulti) {
1✔
71
                    ImArrayTypeMulti type = (ImArrayTypeMulti) v.getType();
1✔
72
                    List<Integer> arraySize = type.getArraySize();
1✔
73
                    if (arraySize.size() == 1) {
1✔
74
                        // just remove the size
75
                        v.setType(JassIm.ImArrayType(type.getEntryType()));
1✔
76
                    } else {
77
                        throw new CompileError(v, "Unsupported array sizes " + arraySize);
×
78
                    }
79
                }
80
            }
1✔
81
        }
1✔
82

83
        replaceVars(prog, getSetMap);
1✔
84
        prog.getGlobals().removeAll(oldVars);
1✔
85
        prog.getGlobals().addAll(newVars);
1✔
86

87
    }
1✔
88

89
    private void replaceVars(Element e, Map<ImVar, GetSetPair> oldToNewVar) {
90

91
        if (e instanceof ImSet) {
1✔
92
            ImSet set = (ImSet) e;
1✔
93

94
            // normalize statement expression on left hand side
95
            ImStmts stmts = JassIm.ImStmts();
1✔
96
            ImLExpr left = set.getLeft();
1✔
97
            while (left instanceof ImStatementExpr) {
1✔
98
                ImStatementExpr se = (ImStatementExpr) left;
1✔
99
                stmts.addAll(se.getStatements().removeAll());
1✔
100
                left = (ImLExpr) se.getExpr();
1✔
101
                left.setParent(null);
1✔
102
            }
1✔
103
            if (left != set.getLeft()) {
1✔
104
                set.setLeft(left);
1✔
105

106
                // replace vars in statements:
107
                for (ImStmt s : stmts) {
1✔
108
                    replaceVars(s, oldToNewVar);
×
109
                }
×
110

111
                // move statements around set-statement
112
                Element setParent = set.getParent();
1✔
113
                set.setParent(null);
1✔
114
                stmts.add(set);
1✔
115
                replacer.replaceInParent(setParent, set, ImHelper.statementExprVoid(stmts));
1✔
116
            }
117

118

119
            if (left instanceof ImVarArrayAccess) {
1✔
120
                ImVarArrayAccess va = (ImVarArrayAccess) left;
1✔
121
                if (va.getIndexes().size() > 1) {
1✔
122
                    if (getSetMap.containsKey(va.getVar())) {
1✔
123
                        // process children (but not the updatedExpr):
124
                        replaceVars(va.getIndexes(), oldToNewVar);
1✔
125
                        replaceVars(set.getRight(), oldToNewVar);
1✔
126
                        ImExprs args = JassIm.ImExprs();
1✔
127
                        for (ImExpr val : va.getIndexes()) {
1✔
128
                            args.add(val.copy());
1✔
129
                        }
1✔
130
                        args.add(set.getRight().copy());
1✔
131

132
                        if (generateStacktraces) {
1✔
133
                            args.add(JassIm.ImStringVal("when writing array " + va.getVar().getName() + StackTraceInjector2.getCallPos(va.getTrace().attrSource())));
1✔
134
                        }
135

136
                        replacer.replace(set,
1✔
137
                            JassIm.ImFunctionCall(set.getTrace(), getSetMap.get(va.getVar()).setter, JassIm.ImTypeArguments(), args, false, CallType.NORMAL));
1✔
138
                        return;
1✔
139
                    }
140
                }
141
            }
142
        }
143
        // process children
144
        for (int i = 0; i < e.size(); i++) {
1✔
145
            replaceVars(e.get(i), oldToNewVar);
1✔
146
        }
147

148
        if (e instanceof ImVarArrayAccess) {
1✔
149
            ImVarArrayAccess am = (ImVarArrayAccess) e;
1✔
150
            if (am.getIndexes().size() > 1) {
1✔
151
                if (am.isUsedAsLValue()) {
1✔
152
                    throw new CompileError(am.attrTrace().attrSource(), "Invalid multi array access " + e);
×
153
                }
154
                ImExprs args = JassIm.ImExprs();
1✔
155
                for (ImExpr val : am.getIndexes()) {
1✔
156
                    args.add(val.copy());
1✔
157
                }
1✔
158
                if (generateStacktraces) {
1✔
159
                    args.add(JassIm.ImStringVal("when reading array " + am.getVar().getName() + " in " + StackTraceInjector2.getCallPos(am.getTrace().attrSource())));
1✔
160
                }
161
                if (getSetMap.containsKey(am.getVar())) {
1✔
162
                    replacer.replace(am,
1✔
163
                        JassIm.ImFunctionCall(am.attrTrace(), getSetMap.get(am.getVar()).getter, JassIm.ImTypeArguments(), args, false, CallType.NORMAL));
1✔
164
                }
165
            }
166
        }
167

168
    }
1✔
169

170

171
    private ImFunction generateSetFunc(ImVar aVar, List<ImVar> newArrays) {
172
        ImArrayTypeMulti mtype = (ImArrayTypeMulti) aVar.getType();
1✔
173
        ImVars locals = JassIm.ImVars();
1✔
174
        ImVar instanceId = JassIm.ImVar(aVar.getTrace(), TypesHelper.imInt(), "instanceId", false);
1✔
175
        ImVar arrayIndex = JassIm.ImVar(aVar.getTrace(), TypesHelper.imInt(), "arrayIndex", false);
1✔
176
        ImVar value = JassIm.ImVar(aVar.getTrace(), mtype.getEntryType(), "value", false);
1✔
177
        ImFunctionCall error = imError(aVar, "Index out of Bounds");
1✔
178
        ImStmts thenBlock = JassIm.ImStmts(error);
1✔
179
        ImStmts elseBlock = JassIm.ImStmts();
1✔
180
        generateBinSearchSet(elseBlock, instanceId, arrayIndex, value, newArrays, 0, newArrays.size() - 1, aVar.getTrace());
1✔
181
        ImExpr highCond = JassIm.ImOperatorCall(WurstOperator.GREATER_EQ, JassIm.ImExprs(JassIm.ImVarAccess(arrayIndex), JassIm.ImIntVal(mtype.getArraySize().get(0))));
1✔
182
        ImExpr lowCond = JassIm.ImOperatorCall(WurstOperator.LESS, JassIm.ImExprs(JassIm.ImVarAccess(arrayIndex), JassIm.ImIntVal(0)));
1✔
183
        ImExpr condition = JassIm.ImOperatorCall(WurstOperator.OR, JassIm.ImExprs(lowCond, highCond));
1✔
184
        ImStmts body = JassIm.ImStmts(JassIm.ImIf(aVar.getTrace(),
1✔
185
                condition, thenBlock, elseBlock));
186

187
        ImFunction setFunc = JassIm.ImFunction(aVar.getTrace(), aVar.getName() + "_set", JassIm.ImTypeVars(), JassIm.ImVars(instanceId, arrayIndex, value), JassIm.ImVoid(), locals, body, Lists.newArrayList());
1✔
188
        if (generateStacktraces) {
1✔
189
            ImVar stackPos = JassIm.ImVar(aVar.getTrace(), TypesHelper.imString(), "stackPos", false);
1✔
190
            setFunc.getParameters().add(stackPos);
1✔
191
            if (error.getFunc().getParameters().size() == 2) {
1✔
192
                error.getArguments().add(JassIm.ImVarAccess(stackPos));
1✔
193
            }
194
        }
195
        return setFunc;
1✔
196
    }
197

198
    private ImFunctionCall imError(ImVar aVar, String msg) {
199
        return translator.imError(aVar.getTrace(), JassIm.ImStringVal(msg));
1✔
200
    }
201

202

203
    private void generateBinSearchSet(ImStmts stmts, ImVar indexVar1, ImVar indexVar2, ImVar value, List<ImVar> newArrays, int start,
204
                                      int end, de.peeeq.wurstscript.ast.Element trace) {
205
        if (start == end) {
1✔
206
            stmts.add(JassIm.ImSet(value.getTrace(), JassIm.ImVarArrayAccess(trace, newArrays.get(start), JassIm.ImExprs(JassIm.ImVarAccess(indexVar1))), JassIm.ImVarAccess(value)));
1✔
207
        } else {
208
            int mid = (start + end) / 2;
1✔
209
            ImStmts thenBlock = JassIm.ImStmts();
1✔
210
            ImStmts elseBlock = JassIm.ImStmts();
1✔
211
            ImExpr condition = JassIm
1✔
212
                    .ImOperatorCall(
1✔
213
                            WurstOperator.LESS_EQ,
214
                            JassIm.ImExprs(JassIm.ImVarAccess(indexVar2),
1✔
215
                                    JassIm.ImIntVal(mid)));
1✔
216
            stmts.add(JassIm.ImIf(value.getTrace(), condition, thenBlock,
1✔
217
                    elseBlock));
218

219
            generateBinSearchSet(thenBlock, indexVar1, indexVar2, value, newArrays, start, mid, trace);
1✔
220
            generateBinSearchSet(elseBlock, indexVar1, indexVar2, value, newArrays, mid + 1, end, trace);
1✔
221
        }
222
    }
1✔
223

224
    private ImFunction generateGetFunc(ImVar aVar, List<ImVar> newArrays) {
225
        ImArrayTypeMulti mtype = (ImArrayTypeMulti) aVar.getType();
1✔
226
        ImVar returnVal = JassIm.ImVar(aVar.getTrace(), mtype.getEntryType(), "returnVal", false);
1✔
227
        ImVars locals = JassIm.ImVars(returnVal);
1✔
228
        ImVar instanceId = JassIm.ImVar(aVar.getTrace(), TypesHelper.imInt(), "index1", false);
1✔
229
        ImVar arrayIndex = JassIm.ImVar(aVar.getTrace(), TypesHelper.imInt(), "index2", false);
1✔
230
        ImFunctionCall error = imError(aVar, "Index out of Bounds");
1✔
231
        ImStmts thenBlock = JassIm.ImStmts(error);
1✔
232
        ImStmts elseBlock = JassIm.ImStmts();
1✔
233
        generateBinSearchGet(elseBlock, instanceId, arrayIndex, returnVal, newArrays, 0, newArrays.size() - 1, aVar.getTrace());
1✔
234
        ImExpr highCond = JassIm.ImOperatorCall(WurstOperator.GREATER_EQ, JassIm.ImExprs(JassIm.ImVarAccess(arrayIndex), JassIm.ImIntVal(mtype.getArraySize().get(0))));
1✔
235
        ImExpr lowCond = JassIm.ImOperatorCall(WurstOperator.LESS, JassIm.ImExprs(JassIm.ImVarAccess(arrayIndex), JassIm.ImIntVal(0)));
1✔
236
        ImExpr condition = JassIm.ImOperatorCall(WurstOperator.OR, JassIm.ImExprs(lowCond, highCond));
1✔
237
        ImStmts body = JassIm.ImStmts(JassIm.ImIf(aVar.getTrace(),
1✔
238
                condition, thenBlock, elseBlock),
239
                JassIm.ImReturn(returnVal.getTrace(), JassIm.ImVarAccess(returnVal)));
1✔
240

241
        ImFunction getFunc = JassIm.ImFunction(aVar.getTrace(), aVar.getName() + "_get", JassIm.ImTypeVars(), JassIm.ImVars(instanceId, arrayIndex), mtype.getEntryType(), locals, body, Lists.newArrayList());
1✔
242
        if (generateStacktraces) {
1✔
243
            ImVar stackPos = JassIm.ImVar(aVar.getTrace(), TypesHelper.imString(), "stackPos", false);
1✔
244
            getFunc.getParameters().add(stackPos);
1✔
245
            if (error.getFunc().getParameters().size() == 2) {
1✔
246
                error.getArguments().add(JassIm.ImVarAccess(stackPos));
1✔
247
            }
248
        }
249
        return getFunc;
1✔
250
    }
251

252

253
    private void generateBinSearchGet(ImStmts stmts, ImVar indexVar1, ImVar indexVar2, ImVar resultVar, List<ImVar> newArrays, int start,
254
                                      int end, de.peeeq.wurstscript.ast.Element trace) {
255
        if (start == end) {
1✔
256
            stmts.add(JassIm.ImSet(resultVar.getTrace(), JassIm.ImVarAccess(resultVar), JassIm.ImVarArrayAccess(trace, newArrays.get(start), JassIm.ImExprs(JassIm.ImVarAccess(indexVar1)))));
1✔
257
        } else {
258
            int mid = (start + end) / 2;
1✔
259
            ImStmts thenBlock = JassIm.ImStmts();
1✔
260
            ImStmts elseBlock = JassIm.ImStmts();
1✔
261
            ImExpr condition = JassIm
1✔
262
                    .ImOperatorCall(
1✔
263
                            WurstOperator.LESS_EQ,
264
                            JassIm.ImExprs(JassIm.ImVarAccess(indexVar2),
1✔
265
                                    JassIm.ImIntVal(mid)));
1✔
266
            stmts.add(JassIm.ImIf(resultVar.getTrace(), condition, thenBlock,
1✔
267
                    elseBlock));
268

269
            generateBinSearchGet(thenBlock, indexVar1, indexVar2, resultVar, newArrays, start, mid, trace);
1✔
270
            generateBinSearchGet(elseBlock, indexVar1, indexVar2, resultVar, newArrays, mid + 1, end, trace);
1✔
271
        }
272
    }
1✔
273
}
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

© 2025 Coveralls, Inc