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

wurstscript / WurstScript / 265

29 Sep 2025 09:00AM UTC coverage: 62.244% (+0.02%) from 62.222%
265

Pull #1096

circleci

Frotty
restore determinism, fix tests
Pull Request #1096: Perf improvements

17480 of 28083 relevant lines covered (62.24%)

0.62 hits per line

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

68.03
de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/intermediatelang/interpreter/ProgramState.java
1
package de.peeeq.wurstscript.intermediatelang.interpreter;
2

3
import com.google.common.collect.ImmutableList;
4
import com.google.common.collect.Lists;
5
import de.peeeq.wurstio.jassinterpreter.InterpreterException;
6
import de.peeeq.wurstscript.ast.Element;
7
import de.peeeq.wurstscript.attributes.CompileError;
8
import de.peeeq.wurstscript.gui.WurstGui;
9
import de.peeeq.wurstscript.intermediatelang.*;
10
import de.peeeq.wurstscript.jassIm.*;
11
import de.peeeq.wurstscript.parser.WPos;
12
import de.peeeq.wurstscript.utils.LineOffsets;
13
import de.peeeq.wurstscript.utils.Utils;
14
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
15
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
16

17
import java.io.PrintStream;
18
import java.util.*;
19

20
public class ProgramState extends State {
21

22
    public static final int GENERATED_BY_WURST = 42;
23
    private de.peeeq.wurstscript.jassIm.Element lastStatement;
24
    protected WurstGui gui;
25
    private PrintStream outStream = System.err;
1✔
26
    private final List<NativesProvider> nativeProviders = Lists.newArrayList();
1✔
27
    private ImProg prog;
28
    private int objectIdCounter;
29
    private final Int2ObjectOpenHashMap<ILconstObject> indexToObject = new Int2ObjectOpenHashMap<>();
1✔
30
    private final Int2ObjectOpenHashMap<IlConstHandle> handleMap = new Int2ObjectOpenHashMap<>();
1✔
31
    private final Deque<ILStackFrame> stackFrames = new ArrayDeque<>();
1✔
32
    private final Deque<de.peeeq.wurstscript.jassIm.Element> lastStatements = new ArrayDeque<>();
1✔
33
    private final boolean isCompiletime;
34

35

36
    public ProgramState(WurstGui gui, ImProg prog, boolean isCompiletime) {
1✔
37
        this.gui = gui;
1✔
38
        this.prog = prog;
1✔
39
        this.isCompiletime = isCompiletime;
1✔
40
    }
1✔
41

42
    public void setLastStatement(ImStmt s) {
43
        lastStatement = s;
1✔
44
    }
1✔
45

46
    public de.peeeq.wurstscript.jassIm.Element getLastStatement() {
47
        return lastStatement;
1✔
48
    }
49

50
    public WurstGui getGui() {
51
        return gui;
×
52
    }
53

54

55
    public void writeBack(boolean injectObjects) {
56
    }
×
57

58

59
    public PrintStream getOutStream() {
60
        return outStream;
×
61
    }
62

63
    public void setOutStream(PrintStream os) {
64
        outStream = os;
×
65
        for (NativesProvider natives : nativeProviders) {
×
66
            natives.setOutStream(os);
×
67
        }
×
68
    }
×
69

70
    public void addNativeProvider(NativesProvider np) {
71
        np.setOutStream(outStream);
1✔
72
        nativeProviders.add(np);
1✔
73
    }
1✔
74

75
    public Iterable<NativesProvider> getNativeProviders() {
76
        return nativeProviders;
1✔
77
    }
78

79
    public ProgramState setProg(ImProg p) {
80
        prog = p;
×
81
        return this;
×
82
    }
83

84
    public ImProg getProg() {
85
        return prog;
1✔
86
    }
87

88
    public ILconstObject allocate(ImClassType clazz, Element trace) {
89
        objectIdCounter++;
1✔
90
        ILconstObject res = new ILconstObject(clazz, objectIdCounter, trace);
1✔
91
        indexToObject.put(objectIdCounter, res);
1✔
92
        return res;
1✔
93
    }
94

95
    protected Object classKey(ImClass clazz) {
96
        return clazz;
×
97
    }
98

99
    public void deallocate(ILconstObject obj, ImClass clazz, Element trace) {
100
        assertAllocated(obj, trace);
1✔
101
        obj.destroy();
1✔
102
        // TODO recycle ids
103
    }
1✔
104

105
    public void assertAllocated(ILconstObject obj, Element trace) {
106
        if (obj == null) {
1✔
107
            throw new InterpreterException(trace, "Null pointer dereference");
×
108
        }
109
        if (obj.isDestroyed()) {
1✔
110
            throw new InterpreterException(trace, "Object already destroyed");
×
111
        }
112
    }
1✔
113

114
    public boolean isInstanceOf(ILconstObject obj, ImClass clazz, Element trace) {
115
        if (obj == null) {
1✔
116
            return false;
1✔
117
        }
118
        assertAllocated(obj, trace);
1✔
119
        return obj.getImClass().isSubclassOf(clazz); // TODO more efficient check
1✔
120
    }
121

122
    public int getTypeId(ILconstObject obj, Element trace) {
123
        assertAllocated(obj, trace);
1✔
124
        return obj.getImClass().attrTypeId();
1✔
125
    }
126

127
    private ImClass findClazz(Object key) {
128
        for (ImClass c : prog.getClasses()) {
×
129
            if (classKey(c).equals(key)) {
×
130
                return c;
×
131
            }
132
        }
×
133
        throw new Error("no class found for key " + key);
×
134
    }
135

136
    public void pushStackframe(ImFunction f, ILconst[] args, WPos trace) {
137
        stackFrames.push(new ILStackFrame(f, args, trace));
1✔
138
        de.peeeq.wurstscript.jassIm.Element stmt = this.lastStatement;
1✔
139
        if (stmt == null) {
1✔
140
            stmt = f;
1✔
141
        }
142
        lastStatements.push(stmt);
1✔
143
    }
1✔
144

145
    public void pushStackframe(ImCompiletimeExpr f, WPos trace) {
146
        stackFrames.push(new ILStackFrame(f, trace));
1✔
147
        de.peeeq.wurstscript.jassIm.Element stmt = this.lastStatement;
1✔
148
        if (stmt == null) {
1✔
149
            stmt = f;
1✔
150
        }
151
        lastStatements.push(stmt);
1✔
152
    }
1✔
153

154
    public void popStackframe() {
155
        if (!stackFrames.isEmpty()) {
1✔
156
            stackFrames.pop();
1✔
157
        }
158
        if (!lastStatements.isEmpty()) {
1✔
159
            lastStatement = lastStatements.pop();
1✔
160
        }
161
    }
1✔
162

163
    public void resetStackframes() {
164
        stackFrames.clear();
1✔
165
        lastStatements.clear();
1✔
166
    }
1✔
167

168
    public StackTrace getStackFrames() {
169
        return new StackTrace(stackFrames);
1✔
170
    }
171

172
    public void compilationError(String errorMessage) {
173
        de.peeeq.wurstscript.jassIm.Element lastStatement = getLastStatement();
×
174
        if (lastStatement != null) {
×
175
            WPos source = lastStatement.attrTrace().attrSource();
×
176
            getGui().sendError(new CompileError(source, errorMessage));
×
177
        } else {
×
178
            getGui().sendError(new CompileError(new WPos("", new LineOffsets(), 0, 0), errorMessage));
×
179
        }
180
        for (ILStackFrame sf : Utils.iterateReverse(getStackFrames().getStackFrames())) {
×
181
            getGui().sendError(sf.makeCompileError());
×
182
        }
×
183
    }
×
184

185
    public ILconst getObjectByIndex(int val) {
186
        return indexToObject.get(val);
1✔
187
    }
188

189
    public Map<Integer, IlConstHandle> getHandleMap() {
190
        return handleMap;
×
191
    }
192

193
    public ILconst getHandleByIndex(int val) {
194
        return handleMap.get(val);
×
195
    }
196

197
    public ILconstObject toObject(ILconst val) {
198
        if (val instanceof ILconstObject) {
1✔
199
            return (ILconstObject) val;
1✔
200
        } else if (val instanceof ILconstInt) {
1✔
201
            return indexToObject.get(((ILconstInt) val).getVal());
1✔
202
        }
203
        throw new InterpreterException(this, "Value " + val + " (" + val.getClass().getSimpleName() + ") cannot be cast to object.");
×
204
    }
205

206
    public static class StackTrace {
207
        private final List<ILStackFrame> stackFrames;
208

209
        public StackTrace(Deque<ILStackFrame> frames) {
1✔
210
            // copy once into an array-backed list
211
            this.stackFrames = Collections.unmodifiableList(new ArrayList<>(frames));
1✔
212
        }
1✔
213

214
        public void appendTo(StringBuilder sb) {
215
            for (ILStackFrame sf : stackFrames) {
1✔
216
                sb.append(sf.getMessage()).append('\n');
1✔
217
            }
1✔
218
        }
1✔
219

220
        @Override public String toString() {
221
            StringBuilder sb = new StringBuilder(stackFrames.size() * 32);
×
222
            appendTo(sb);
×
223
            return sb.toString();
×
224
        }
225

226
        public List<ILStackFrame> getStackFrames() { return stackFrames; }
×
227

228
        public Iterable<ILStackFrame> getStackFramesReversed() {
229
            return () -> new Iterator<ILStackFrame>() {
×
230
                int i = stackFrames.size() - 1;
×
231
                @Override public boolean hasNext() { return i >= 0; }
×
232
                @Override public ILStackFrame next() { return stackFrames.get(i--); }
×
233
            };
234
        }
235
    }
236

237

238
    public boolean isCompiletime() {
239
        return isCompiletime;
1✔
240
    }
241

242
    // Reuse a shared, empty LocalState (ensure it's safe/side-effect free)
243
    private static final LocalState EMPTY_LOCAL_STATE = new LocalState();
1✔
244

245
    @Override
246
    protected ILconstArray getArray(ImVar v) {
247
        Object2ObjectOpenHashMap<ImVar, ILconstArray> arrayValues = ensureArrayValues();
1✔
248
        ILconstArray r = arrayValues.get(v);
1✔
249
        if (r != null) return r;
1✔
250

251
        r = createArrayConstantFromType(v.getType());
1✔
252
        arrayValues.put(v, r);
1✔
253

254
        // Initialize from globalInits only once
255
        List<ImSet> inits = prog.getGlobalInits().get(v);
1✔
256
        if (inits != null && !inits.isEmpty()) {
1✔
257
            // evaluate with a reusable local state to avoid per-init allocations
258
            final LocalState ls = EMPTY_LOCAL_STATE;
1✔
259
            for (int i = 0; i < inits.size(); i++) {
1✔
260
                ILconst val = inits.get(i).getRight().evaluate(this, ls);
1✔
261
                r.set(i, val);
1✔
262
            }
263
        }
264
        return r;
1✔
265
    }
266

267

268

269

270
    public Collection<ILconstObject> getAllObjects() {
271
        return indexToObject.values();
1✔
272
    }
273

274
}
275

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