Skip to content

Commit c7c44d8

Browse files
committed
properly store generic vars
1 parent 03f3069 commit c7c44d8

1 file changed

Lines changed: 110 additions & 27 deletions

File tree

  • de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/intermediatelang/interpreter

de.peeeq.wurstscript/src/main/java/de/peeeq/wurstscript/intermediatelang/interpreter/ProgramState.java

Lines changed: 110 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
11
package de.peeeq.wurstscript.intermediatelang.interpreter;
22

3-
import com.google.common.base.Objects;
4-
import com.google.common.collect.ImmutableList;
53
import com.google.common.collect.Lists;
64
import de.peeeq.wurstio.jassinterpreter.InterpreterException;
75
import de.peeeq.wurstscript.ast.Element;
@@ -10,7 +8,7 @@
108
import de.peeeq.wurstscript.intermediatelang.*;
119
import de.peeeq.wurstscript.jassIm.*;
1210
import de.peeeq.wurstscript.parser.WPos;
13-
import de.peeeq.wurstscript.translation.imtranslation.ImPrinter;
11+
import de.peeeq.wurstscript.translation.imtojass.ImAttrType;
1412
import de.peeeq.wurstscript.utils.LineOffsets;
1513
import de.peeeq.wurstscript.utils.Utils;
1614
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
@@ -35,11 +33,40 @@ public class ProgramState extends State {
3533
private final Deque<de.peeeq.wurstscript.jassIm.Element> lastStatements = new ArrayDeque<>();
3634
private final boolean isCompiletime;
3735

36+
private final Map<ImVar, ImClass> genericStaticOwner = new HashMap<>();
37+
38+
private final Object2ObjectOpenHashMap<String, ILconst> genericStaticVals = new Object2ObjectOpenHashMap<>();
39+
private final Object2ObjectOpenHashMap<String, ILconstArray> genericStaticArrays = new Object2ObjectOpenHashMap<>();
40+
3841

3942
public ProgramState(WurstGui gui, ImProg prog, boolean isCompiletime) {
4043
this.gui = gui;
4144
this.prog = prog;
4245
this.isCompiletime = isCompiletime;
46+
47+
identifyGenericStaticGlobals();
48+
}
49+
50+
private void identifyGenericStaticGlobals() {
51+
Map<String, ImClass> classMap = new HashMap<>();
52+
for (ImClass c : prog.getClasses()) {
53+
classMap.put(c.getName(), c);
54+
}
55+
56+
for (ImVar global : prog.getGlobals()) {
57+
String n = global.getName();
58+
int underscore = n.indexOf('_');
59+
if (underscore <= 0) continue;
60+
61+
String className = n.substring(0, underscore);
62+
ImClass owner = classMap.get(className);
63+
if (owner == null) continue;
64+
65+
// Only generic classes need per-instantiation statics:
66+
if (owner.getTypeVariables().isEmpty()) continue;
67+
68+
genericStaticOwner.put(global, owner);
69+
}
4370
}
4471

4572
public void setLastStatement(ImStmt s) {
@@ -162,9 +189,51 @@ public void pushStackframeWithTypes(ImFunction f, @Nullable ILconstObject receiv
162189
lastStatements.push(stmt);
163190
}
164191

192+
private @Nullable String genericStaticKey(ImVar v) {
193+
ImClass owner = genericStaticOwner.get(v);
194+
if (owner == null) return null;
195+
196+
ImClassType inst = currentReceiverInstantiationFor(owner);
197+
if (inst == null) {
198+
// Happens if accessed without a receiver context (static-only code path).
199+
// You can refine later; for now keep a stable bucket.
200+
return v.getName() + "|<no-receiver>";
201+
}
202+
return v.getName() + "|" + instantiationKey(inst);
203+
}
204+
205+
private @Nullable ImClassType currentReceiverInstantiationFor(ImClass owner) {
206+
ILStackFrame top = stackFrames.peek();
207+
if (top == null || top.receiver == null) return null;
208+
209+
ImClassType rt = top.receiver.getType();
210+
// resolve possible type vars inside type args
211+
ImType resolved = resolveType(rt);
212+
if (resolved instanceof ImClassType) {
213+
rt = (ImClassType) resolved;
214+
}
215+
216+
ImClassType adapted = adaptToSuperclass(rt, owner);
217+
return adapted != null ? adapted : rt;
218+
}
219+
220+
private @Nullable ImClassType adaptToSuperclass(ImClassType ct, ImClass owner) {
221+
if (ct.getClassDef() == owner) return ct;
165222

166-
// NEW: Resolve a generic type using current stack frame's type substitutions
167-
// Replace both resolveType(...) and substituteTypeVars(...) with this:
223+
// Walk super types, substituting this ct's type args into the superclass types
224+
List<ImTypeVar> tvs = ct.getClassDef().getTypeVariables();
225+
ImTypeArguments tas = ct.getTypeArguments();
226+
227+
for (ImClassType scRaw : ct.getClassDef().getSuperClasses()) {
228+
ImType scSubst = ImAttrType.substituteType(scRaw, tas, tvs);
229+
scSubst = resolveType(scSubst);
230+
if (scSubst instanceof ImClassType) {
231+
ImClassType r = adaptToSuperclass((ImClassType) scSubst, owner);
232+
if (r != null) return r;
233+
}
234+
}
235+
return null;
236+
}
168237

169238
public ImType resolveType(ImType t) {
170239
return resolveTypeDeep(t, 32); // small budget to avoid cycles
@@ -404,9 +473,6 @@ public ILStackFrame next() {
404473
}
405474
}
406475

407-
private final Object2ObjectOpenHashMap<String, ILconst> genericStaticVals = new Object2ObjectOpenHashMap<>();
408-
409-
410476
public String instantiationKey(ImClassType ct) {
411477
StringBuilder sb = new StringBuilder();
412478
sb.append(ct.getClassDef().getName());
@@ -425,33 +491,32 @@ public String instantiationKey(ImClassType ct) {
425491

426492
@Override
427493
public void setVal(ImVar v, ILconst val) {
428-
if (v.isGlobal() && v.getType() instanceof ImTypeVarRef) {
429-
ILStackFrame top = stackFrames.peek();
430-
if (top != null && top.receiver != null) {
431-
ImTypeArguments tas = top.receiver.getType().getTypeArguments();
432-
ImType resolved = resolveType(tas.get(0).getType()); // <<< resolve
433-
String s = v.getName() + resolved;
434-
genericStaticVals.put(s, val);
435-
return;
436-
}
494+
String key = genericStaticKey(v);
495+
if (key != null) {
496+
genericStaticVals.put(key, val);
497+
return;
437498
}
438499
super.setVal(v, val);
439500
}
440501

502+
@Override
441503
public @Nullable ILconst getVal(ImVar v) {
442-
if (v.isGlobal() && v.getType() instanceof ImTypeVarRef) {
443-
System.out.println("looking for generic static var " + v);
444-
ILStackFrame top = stackFrames.peek();
445-
if (top != null && top.receiver != null) {
446-
ImTypeArguments tas = top.receiver.getType().getTypeArguments();
447-
ImType resolved = resolveType(tas.get(0).getType()); // <<< resolve
448-
String s = v.getName() + resolved;
449-
return genericStaticVals.get(s);
504+
String key = genericStaticKey(v);
505+
if (key != null) {
506+
ILconst existing = genericStaticVals.get(key);
507+
if (existing != null) return existing;
508+
509+
// Initialize from the normal global init machinery once, then copy into this instantiation bucket:
510+
ILconst init = super.getVal(v);
511+
if (init != null) {
512+
genericStaticVals.put(key, init);
450513
}
514+
return init;
451515
}
452516
return super.getVal(v);
453517
}
454518

519+
455520
public boolean isCompiletime() {
456521
return isCompiletime;
457522
}
@@ -461,17 +526,35 @@ public boolean isCompiletime() {
461526

462527
@Override
463528
protected ILconstArray getArray(ImVar v) {
529+
String key = genericStaticKey(v);
530+
if (key != null) {
531+
ILconstArray arr = genericStaticArrays.get(key);
532+
if (arr != null) return arr;
533+
534+
ILconstArray r = createArrayConstantFromType(v.getType());
535+
genericStaticArrays.put(key, r);
536+
537+
List<ImSet> inits = prog.getGlobalInits().get(v);
538+
if (inits != null && !inits.isEmpty()) {
539+
final LocalState ls = EMPTY_LOCAL_STATE;
540+
for (int i = 0; i < inits.size(); i++) {
541+
ILconst val = inits.get(i).getRight().evaluate(this, ls);
542+
r.set(i, val);
543+
}
544+
}
545+
return r;
546+
}
547+
548+
// non-generic case = your existing logic
464549
Object2ObjectOpenHashMap<ImVar, ILconstArray> arrayValues = ensureArrayValues();
465550
ILconstArray r = arrayValues.get(v);
466551
if (r != null) return r;
467552

468553
r = createArrayConstantFromType(v.getType());
469554
arrayValues.put(v, r);
470555

471-
// Initialize from globalInits only once
472556
List<ImSet> inits = prog.getGlobalInits().get(v);
473557
if (inits != null && !inits.isEmpty()) {
474-
// evaluate with a reusable local state to avoid per-init allocations
475558
final LocalState ls = EMPTY_LOCAL_STATE;
476559
for (int i = 0; i < inits.size(); i++) {
477560
ILconst val = inits.get(i).getRight().evaluate(this, ls);

0 commit comments

Comments
 (0)