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

wurstscript / WurstScript / 271

29 Sep 2025 12:12PM UTC coverage: 64.649% (+2.4%) from 62.222%
271

Pull #1096

circleci

Frotty
Merge branch 'perf-improvements' of https://github.com/wurstscript/WurstScript into perf-improvements
Pull Request #1096: Perf improvements

18202 of 28155 relevant lines covered (64.65%)

0.65 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.Lists;
4
import de.peeeq.wurstio.jassinterpreter.InterpreterException;
5
import de.peeeq.wurstscript.ast.Element;
6
import de.peeeq.wurstscript.attributes.CompileError;
7
import de.peeeq.wurstscript.gui.WurstGui;
8
import de.peeeq.wurstscript.intermediatelang.*;
9
import de.peeeq.wurstscript.jassIm.*;
10
import de.peeeq.wurstscript.parser.WPos;
11
import de.peeeq.wurstscript.utils.LineOffsets;
12
import de.peeeq.wurstscript.utils.Utils;
13
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
14
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
15

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

19
public class ProgramState extends State {
20

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

34

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

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

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

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

53

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

57

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

236

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

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

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

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

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

266

267

268

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

273
}
274

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