fix: broken labeled jumps

This commit is contained in:
TopchetoEU 2024-12-13 02:27:57 +02:00
parent 130fe17441
commit 274a925ff8
Signed by: topchetoeu
GPG Key ID: 6531B8583E5F6ED4
2 changed files with 25 additions and 10 deletions

View File

@ -19,7 +19,8 @@ public class LabelContext {
private final LinkedList<IntSupplier> list = new LinkedList<>(); private final LinkedList<IntSupplier> list = new LinkedList<>();
private final HashMap<String, IntSupplier> map = new HashMap<>(); private final HashMap<String, IntSupplier> map = new HashMap<>();
private final Stack<ArrayList<Runnable>> deferredAdders = new Stack<>(); private final LinkedList<ArrayList<Runnable>> deferredList = new LinkedList<>();
private final HashMap<String, ArrayList<Runnable>> deferredMap = new HashMap<>();
public IntSupplier get() { public IntSupplier get() {
return list.peekLast(); return list.peekLast();
@ -28,28 +29,41 @@ public class LabelContext {
return map.get(name); return map.get(name);
} }
public void flushAdders() { public void flushAdders(String name) {
for (var adder : deferredAdders.peek()) { for (var adder : deferredList.peek()) {
adder.run(); adder.run();
} }
deferredAdders.pop(); deferredList.pop();
if (name != null) {
var adders = deferredMap.remove(name);
if (adders != null) {
for (var adder : adders) adder.run();
}
}
} }
public boolean jump(CompileResult target) { public boolean jump(CompileResult target) {
var res = get(); var res = get();
if (res != null) { if (res != null) {
var tmp = target.temp(); var tmp = target.temp();
this.deferredAdders.peek().add(() -> target.set(tmp, Instruction.jmp(res.getAsInt() - tmp))); this.deferredList.peek().add(() -> target.set(tmp, Instruction.jmp(res.getAsInt() - tmp)));
return true; return true;
} }
else return false; else return false;
} }
public boolean jump(CompileResult target, String name) { public boolean jump(CompileResult target, String name) {
var res = get(name); var res = name == null ? get() : get(name);
if (res != null) { if (res != null) {
var tmp = target.temp(); var tmp = target.temp();
this.deferredAdders.peek().add(() -> target.set(tmp, Instruction.jmp(res.getAsInt() - tmp))); Runnable task = () -> target.set(tmp, Instruction.jmp(res.getAsInt() - tmp));
if (name == null) this.deferredList.peekLast().add(task);
else if (deferredMap.containsKey(name)) this.deferredMap.get(name).add(task);
else return false;
return true; return true;
} }
else return false; else return false;
@ -67,7 +81,8 @@ public class LabelContext {
public void pushLoop(Location loc, String name, IntSupplier jumpTarget) { public void pushLoop(Location loc, String name, IntSupplier jumpTarget) {
push(jumpTarget); push(jumpTarget);
push(loc, name, jumpTarget); push(loc, name, jumpTarget);
deferredAdders.push(new ArrayList<>()); deferredList.push(new ArrayList<>());
if (name != null) deferredMap.put(name, new ArrayList<>());
} }
public void pop() { public void pop() {
@ -81,7 +96,7 @@ public class LabelContext {
public void popLoop(String name) { public void popLoop(String name) {
pop(); pop();
pop(name); pop(name);
flushAdders(); flushAdders(name);
} }
public static LabelContext getBreak(Environment env) { public static LabelContext getBreak(Environment env) {

View File

@ -18,7 +18,7 @@ public class BreakNode extends Node {
} }
@Override public void compile(CompileResult target, boolean pollute) { @Override public void compile(CompileResult target, boolean pollute) {
if (!LabelContext.getBreak(target.env).jump(target)) { if (!LabelContext.getBreak(target.env).jump(target, label)) {
if (label != null) throw new SyntaxException(loc(), String.format("Undefined label '%s'", label)); if (label != null) throw new SyntaxException(loc(), String.format("Undefined label '%s'", label));
else throw new SyntaxException(loc(), "Illegal break statement"); else throw new SyntaxException(loc(), "Illegal break statement");
} }