diff --git a/src/main/java/me/topchetoeu/jscript/compilation/LabelContext.java b/src/main/java/me/topchetoeu/jscript/compilation/LabelContext.java index 0c8eb2f..6bb0124 100644 --- a/src/main/java/me/topchetoeu/jscript/compilation/LabelContext.java +++ b/src/main/java/me/topchetoeu/jscript/compilation/LabelContext.java @@ -19,7 +19,8 @@ public class LabelContext { private final LinkedList list = new LinkedList<>(); private final HashMap map = new HashMap<>(); - private final Stack> deferredAdders = new Stack<>(); + private final LinkedList> deferredList = new LinkedList<>(); + private final HashMap> deferredMap = new HashMap<>(); public IntSupplier get() { return list.peekLast(); @@ -28,28 +29,41 @@ public class LabelContext { return map.get(name); } - public void flushAdders() { - for (var adder : deferredAdders.peek()) { + public void flushAdders(String name) { + for (var adder : deferredList.peek()) { 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) { var res = get(); if (res != null) { 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; } else return false; } public boolean jump(CompileResult target, String name) { - var res = get(name); + var res = name == null ? get() : get(name); if (res != null) { 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; } else return false; @@ -67,7 +81,8 @@ public class LabelContext { public void pushLoop(Location loc, String name, IntSupplier jumpTarget) { push(jumpTarget); push(loc, name, jumpTarget); - deferredAdders.push(new ArrayList<>()); + deferredList.push(new ArrayList<>()); + if (name != null) deferredMap.put(name, new ArrayList<>()); } public void pop() { @@ -81,7 +96,7 @@ public class LabelContext { public void popLoop(String name) { pop(); pop(name); - flushAdders(); + flushAdders(name); } public static LabelContext getBreak(Environment env) { diff --git a/src/main/java/me/topchetoeu/jscript/compilation/control/BreakNode.java b/src/main/java/me/topchetoeu/jscript/compilation/control/BreakNode.java index 32203c6..c2e00a9 100644 --- a/src/main/java/me/topchetoeu/jscript/compilation/control/BreakNode.java +++ b/src/main/java/me/topchetoeu/jscript/compilation/control/BreakNode.java @@ -18,7 +18,7 @@ public class BreakNode extends Node { } @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)); else throw new SyntaxException(loc(), "Illegal break statement"); }