fix: broken labeled jumps
This commit is contained in:
parent
130fe17441
commit
274a925ff8
@ -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) {
|
||||||
|
@ -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");
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user