From 14e4aade351fdf07f94fdaffe9222805155d8b84 Mon Sep 17 00:00:00 2001 From: TopchetoEU <36534413+TopchetoEU@users.noreply.github.com> Date: Sat, 23 Nov 2024 20:09:29 +0200 Subject: [PATCH] regress: remove infrastructure needed for ES6 stuff, simplify loops --- .../jscript/compilation/CompileResult.java | 72 +++---------------- .../jscript/compilation/CompoundNode.java | 21 ++---- .../jscript/compilation/JavaScript.java | 72 ++++++++++++------- .../jscript/compilation/LabelContext.java | 35 +++++++-- .../compilation/control/BreakNode.java | 4 +- .../compilation/control/ContinueNode.java | 4 +- .../compilation/control/DoWhileNode.java | 3 +- .../compilation/control/ForInNode.java | 34 +++++---- .../jscript/compilation/control/ForNode.java | 8 +-- .../compilation/control/SwitchNode.java | 34 ++++----- .../jscript/compilation/control/TryNode.java | 17 ++--- .../compilation/control/WhileNode.java | 2 +- 12 files changed, 140 insertions(+), 166 deletions(-) diff --git a/src/main/java/me/topchetoeu/jscript/compilation/CompileResult.java b/src/main/java/me/topchetoeu/jscript/compilation/CompileResult.java index c0fb4e1..89e5b76 100644 --- a/src/main/java/me/topchetoeu/jscript/compilation/CompileResult.java +++ b/src/main/java/me/topchetoeu/jscript/compilation/CompileResult.java @@ -3,8 +3,6 @@ package me.topchetoeu.jscript.compilation; import java.util.List; import java.util.ArrayList; import java.util.LinkedList; -import java.util.function.Consumer; -import java.util.function.IntFunction; import me.topchetoeu.jscript.common.FunctionBody; import me.topchetoeu.jscript.common.Instruction; @@ -14,7 +12,7 @@ import me.topchetoeu.jscript.common.environment.Key; import me.topchetoeu.jscript.common.mapping.FunctionMap; import me.topchetoeu.jscript.common.mapping.FunctionMap.FunctionMapBuilder; import me.topchetoeu.jscript.common.parsing.Location; -import me.topchetoeu.jscript.compilation.scope.Scope; +import me.topchetoeu.jscript.compilation.scope.FunctionScope; public final class CompileResult { public static final class ChildData { @@ -27,15 +25,12 @@ public final class CompileResult { } } - public final List> instructions; + public final List instructions; public final List children; public final FunctionMapBuilder map; public final Environment env; public int length; - public Runnable buildTask = () -> { - throw new IllegalStateException("Compile result is not ready to be built"); - }; - public final Scope scope; + public final FunctionScope scope; public int temp() { instructions.add(null); @@ -43,21 +38,14 @@ public final class CompileResult { } public CompileResult add(Instruction instr) { - instructions.add(i -> instr); - return this; - } - public CompileResult add(IntFunction instr) { instructions.add(instr); return this; } public CompileResult set(int i, Instruction instr) { - instructions.set(i, _i -> instr); - return this; - } - public CompileResult set(int i, IntFunctioninstr) { instructions.set(i, instr); return this; } + public int size() { return instructions.size(); } public void setDebug(Location loc, BreakpointType type) { @@ -79,62 +67,25 @@ public final class CompileResult { setLocationAndDebug(instructions.size() - 1, loc, type); } - public void beginScope() { - // for (var cap : scope.capturables()) { - // add(_i -> Instruction.capInit(cap.index().index)); - // } - } - public void reallocScope() { - for (var cap : scope.capturables()) { - add(_i -> cap.index().toGet()); - add(_i -> Instruction.capFree(cap.index().index)); - add(_i -> cap.index().toInit()); - } - - scope.end(); - } - public void endScope() { - for (var cap : scope.capturables()) { - add(_i -> Instruction.capFree(cap.index().index)); - } - for (var var : scope.locals()) { - add(_i -> Instruction.varFree(var.index().index)); - } - - scope.end(); - } - public int addChild(CompileResult res) { this.children.add(res); return this.children.size() - 1; } public Instruction[] instructions() { - var res = new Instruction[instructions.size()]; - var i = 0; - for (var suppl : instructions) { - res[i] = suppl.apply(i); - i++; - } - return res; + return instructions.toArray(new Instruction[0]); } public FunctionMap map() { - return map.build(scope); + return map.build(scope.localNames(), scope.captureNames()); } public FunctionBody body() { var builtChildren = new FunctionBody[children.size()]; - for (var i = 0; i < children.size(); i++) builtChildren[i] = children.get(i).body(); - var instrRes = new Instruction[instructions.size()]; - var i = 0; + var instrRes = instructions(); - for (var suppl : instructions) { - instrRes[i] = suppl.apply(i); - // System.out.println(instrRes[i]); - i++; - } + for (var instr : instrRes) System.out.println(instr); return new FunctionBody( scope.localsCount(), scope.capturablesCount(), scope.capturesCount(), @@ -143,7 +94,7 @@ public final class CompileResult { } public CompileResult subtarget() { - return new CompileResult(env, new Scope(scope), this); + return new CompileResult(env, new FunctionScope(scope), this); } public CompileResult setEnvironment(Environment env) { @@ -160,16 +111,15 @@ public final class CompileResult { return new CompileResult(env.child(), scope, this); } - public CompileResult(Environment env, Scope scope, int length, Consumer task) { + public CompileResult(Environment env, FunctionScope scope, int length) { this.scope = scope; this.instructions = new ArrayList<>(); this.children = new LinkedList<>(); this.map = FunctionMap.builder(); this.env = env; this.length = length; - this.buildTask = () -> task.accept(this); } - private CompileResult(Environment env, Scope scope, CompileResult parent) { + private CompileResult(Environment env, FunctionScope scope, CompileResult parent) { this.scope = scope; this.instructions = parent.instructions; this.children = parent.children; diff --git a/src/main/java/me/topchetoeu/jscript/compilation/CompoundNode.java b/src/main/java/me/topchetoeu/jscript/compilation/CompoundNode.java index b99a75f..66b2e6d 100644 --- a/src/main/java/me/topchetoeu/jscript/compilation/CompoundNode.java +++ b/src/main/java/me/topchetoeu/jscript/compilation/CompoundNode.java @@ -14,7 +14,6 @@ import me.topchetoeu.jscript.common.parsing.Source; public class CompoundNode extends Node { public final Node[] statements; - public boolean hasScope; public Location end; @Override public void resolve(CompileResult target) { @@ -24,12 +23,9 @@ public class CompoundNode extends Node { public void compile(CompileResult target, boolean pollute, boolean singleEntry, BreakpointType type) { List statements = new ArrayList(); - var subtarget = hasScope ? target.subtarget() : target; - if (hasScope) subtarget.beginScope(); - for (var stm : this.statements) { if (stm instanceof FunctionStatementNode func) { - func.compile(subtarget, false); + func.compile(target, false); } else statements.add(stm); } @@ -39,12 +35,10 @@ public class CompoundNode extends Node { for (var i = 0; i < statements.size(); i++) { var stm = statements.get(i); - if (i != statements.size() - 1) stm.compile(subtarget, false, BreakpointType.STEP_OVER); - else stm.compile(subtarget, polluted = pollute, BreakpointType.STEP_OVER); + if (i != statements.size() - 1) stm.compile(target, false, BreakpointType.STEP_OVER); + else stm.compile(target, polluted = pollute, BreakpointType.STEP_OVER); } - if (hasScope) subtarget.endScope(); - if (!polluted && pollute) { target.add(Instruction.pushUndefined()); } @@ -59,9 +53,8 @@ public class CompoundNode extends Node { return this; } - public CompoundNode(Location loc, boolean hasScope, Node ...statements) { + public CompoundNode(Location loc, Node ...statements) { super(loc); - this.hasScope = hasScope; this.statements = statements; } @@ -92,9 +85,9 @@ public class CompoundNode extends Node { children.addAll(Arrays.asList(comp.statements)); children.add(curr.result); - return ParseRes.res(new CompoundNode(loc, comp.hasScope, children.toArray(new Node[0])), n); + return ParseRes.res(new CompoundNode(loc, children.toArray(new Node[0])), n); } - else return ParseRes.res(new CompoundNode(loc, false, prev, curr.result), n); + else return ParseRes.res(new CompoundNode(loc, prev, curr.result), n); } public static ParseRes parse(Source src, int i) { var n = Parsing.skipEmpty(src, i); @@ -124,6 +117,6 @@ public class CompoundNode extends Node { statements.add(res.result); } - return ParseRes.res(new CompoundNode(loc, true, statements.toArray(new Node[0])).setEnd(src.loc(i + n - 1)), n); + return ParseRes.res(new CompoundNode(loc, statements.toArray(new Node[0])).setEnd(src.loc(i + n - 1)), n); } } diff --git a/src/main/java/me/topchetoeu/jscript/compilation/JavaScript.java b/src/main/java/me/topchetoeu/jscript/compilation/JavaScript.java index 5110a11..8217fa6 100644 --- a/src/main/java/me/topchetoeu/jscript/compilation/JavaScript.java +++ b/src/main/java/me/topchetoeu/jscript/compilation/JavaScript.java @@ -3,6 +3,7 @@ package me.topchetoeu.jscript.compilation; import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; +import java.util.List; import java.util.Set; import me.topchetoeu.jscript.common.SyntaxException; @@ -17,9 +18,7 @@ import me.topchetoeu.jscript.compilation.control.ContinueNode; import me.topchetoeu.jscript.compilation.control.DebugNode; import me.topchetoeu.jscript.compilation.control.DeleteNode; import me.topchetoeu.jscript.compilation.control.DoWhileNode; -import me.topchetoeu.jscript.compilation.control.ForInNode; import me.topchetoeu.jscript.compilation.control.ForNode; -import me.topchetoeu.jscript.compilation.control.ForOfNode; import me.topchetoeu.jscript.compilation.control.IfNode; import me.topchetoeu.jscript.compilation.control.ReturnNode; import me.topchetoeu.jscript.compilation.control.SwitchNode; @@ -29,7 +28,6 @@ import me.topchetoeu.jscript.compilation.control.WhileNode; import me.topchetoeu.jscript.compilation.scope.FunctionScope; import me.topchetoeu.jscript.compilation.values.ArgumentsNode; import me.topchetoeu.jscript.compilation.values.ArrayNode; -import me.topchetoeu.jscript.compilation.values.ClassValueNode; import me.topchetoeu.jscript.compilation.values.ObjectNode; import me.topchetoeu.jscript.compilation.values.RegexNode; import me.topchetoeu.jscript.compilation.values.SuperNode; @@ -49,16 +47,8 @@ import me.topchetoeu.jscript.compilation.values.operations.TypeofNode; public final class JavaScript { public static enum DeclarationType { - VAR(false, false), - CONST(true, true), - LET(true, false); - - public final boolean strict, readonly; - - private DeclarationType(boolean strict, boolean readonly) { - this.strict = strict; - this.readonly = readonly; - } + @Deprecated + VAR; } public static final Key COMPILE_ROOT = Key.of(); @@ -93,7 +83,6 @@ public final class JavaScript { return ParseRes.first(src, i, (s, j) -> statement ? ParseRes.failed() : ObjectNode.parse(s, j), (s, j) -> statement ? ParseRes.failed() : FunctionNode.parseFunction(s, j, false), - (s, j) -> statement ? ParseRes.failed() : ClassValueNode.parse(s, j), JavaScript::parseLiteral, StringNode::parse, RegexNode::parse, @@ -102,7 +91,6 @@ public final class JavaScript { ChangeNode::parsePrefixIncrease, OperationNode::parsePrefix, ArrayNode::parse, - (s, j) -> statement ? ParseRes.failed() : FunctionArrowNode.parse(s, j), JavaScript::parseParens, CallNode::parseNew, TypeofNode::parse, @@ -188,14 +176,13 @@ public final class JavaScript { return res.addN(end.n); } - public static ParseRes parseStatement(Source src, int i) { + public static ParseRes parseStatement(Source src, int i) { var n = Parsing.skipEmpty(src, i); if (src.is(i + n, ";")) return ParseRes.res(new DiscardNode(src.loc(i+ n), null), n + 1); if (Parsing.isIdentifier(src, i + n, "with")) return ParseRes.error(src.loc(i + n), "'with' statements are not allowed."); - ParseRes res = ParseRes.first(src, i + n, - ClassStatementNode::parse, + ParseRes res = ParseRes.first(src, i + n, VariableDeclareNode::parse, ReturnNode::parse, ThrowNode::parse, @@ -206,8 +193,6 @@ public final class JavaScript { WhileNode::parse, SwitchNode::parse, ForNode::parse, - ForInNode::parse, - ForOfNode::parse, DoWhileNode::parse, TryNode::parse, CompoundNode::parse, @@ -231,13 +216,11 @@ public final class JavaScript { return ParseRes.failed(); } - public static ParseRes parseDeclarationType(Source src, int i) { + public static ParseRes parseDeclarationType(Source src, int i) { var res = Parsing.parseIdentifier(src, i); if (!res.isSuccess()) return res.chainError(); - if (res.result.equals("var")) return ParseRes.res(DeclarationType.VAR, res.n); - if (res.result.equals("let")) return ParseRes.res(DeclarationType.LET, res.n); - if (res.result.equals("const")) return ParseRes.res(DeclarationType.CONST, res.n); + if (res.result.equals("var")) return ParseRes.res(true, res.n); return ParseRes.failed(); } @@ -272,9 +255,8 @@ public final class JavaScript { env = env.child(); env.add(COMPILE_ROOT, env); - var func = new FunctionValueNode(null, null, new Parameters(Arrays.asList()), new CompoundNode(null, true, statements), null); + var func = new FunctionValueNode(null, null, Arrays.asList(), new CompoundNode(null, statements), null); var res = func.compileBody(env, new FunctionScope(true), true, null, null); - res.buildTask.run(); return res; } @@ -299,4 +281,42 @@ public final class JavaScript { return ParseRes.res(nameRes.result, n); } + + public static ParseRes> parseParameters(Source src, int i) { + var n = Parsing.skipEmpty(src, i); + + var openParen = Parsing.parseOperator(src, i + n, "("); + if (!openParen.isSuccess()) return openParen.chainError(src.loc(i + n), "Expected a parameter list"); + n += openParen.n; + + var params = new ArrayList(); + + var closeParen = Parsing.parseOperator(src, i + n, ")"); + n += closeParen.n; + + if (!closeParen.isSuccess()) { + while (true) { + n += Parsing.skipEmpty(src, i + n); + + var param = VariableNode.parse(src, i + n); + if (!param.isSuccess()) return ParseRes.error(src.loc(i + n), "Expected a parameter or a closing brace"); + n += param.n; + n += Parsing.skipEmpty(src, i + n); + + params.add(param.result); + + if (src.is(i + n, ",")) { + n++; + n += Parsing.skipEmpty(src, i + n); + } + + if (src.is(i + n, ")")) { + n++; + break; + } + } + } + + return ParseRes.res(params, n); + } } diff --git a/src/main/java/me/topchetoeu/jscript/compilation/LabelContext.java b/src/main/java/me/topchetoeu/jscript/compilation/LabelContext.java index 22f371c..a9cfe03 100644 --- a/src/main/java/me/topchetoeu/jscript/compilation/LabelContext.java +++ b/src/main/java/me/topchetoeu/jscript/compilation/LabelContext.java @@ -1,8 +1,9 @@ package me.topchetoeu.jscript.compilation; +import java.util.ArrayList; import java.util.HashMap; import java.util.LinkedList; -import java.util.function.IntFunction; +import java.util.Stack; import java.util.function.IntSupplier; import me.topchetoeu.jscript.common.Instruction; @@ -18,6 +19,8 @@ public class LabelContext { private final LinkedList list = new LinkedList<>(); private final HashMap map = new HashMap<>(); + private final Stack> deferredAdders = new Stack<>(); + public IntSupplier get() { return list.peekLast(); } @@ -25,15 +28,31 @@ public class LabelContext { return map.get(name); } - public IntFunction getJump() { + public void flushAdders() { + for (var adder : deferredAdders.peek()) { + adder.run(); + } + + deferredAdders.pop(); + } + + public boolean jump(CompileResult target) { var res = get(); - if (res == null) return null; - else return i -> Instruction.jmp(res.getAsInt() - i); + if (res != null) { + var tmp = target.temp(); + this.deferredAdders.peek().add(() -> target.set(tmp, Instruction.jmp(res.getAsInt() - tmp))); + return true; + } + else return false; } - public IntFunction getJump(String name) { + public boolean jump(CompileResult target, String name) { var res = get(name); - if (res == null) return null; - else return i -> Instruction.jmp(res.getAsInt() - i); + if (res != null) { + var tmp = target.temp(); + this.deferredAdders.peek().add(() -> target.set(tmp, Instruction.jmp(res.getAsInt() - tmp))); + return true; + } + else return false; } public void push(IntSupplier jumpTarget) { @@ -48,6 +67,7 @@ public class LabelContext { public void pushLoop(Location loc, String name, IntSupplier jumpTarget) { push(jumpTarget); push(loc, name, jumpTarget); + deferredAdders.push(new ArrayList<>()); } public void pop() { @@ -61,6 +81,7 @@ public class LabelContext { public void popLoop(String name) { pop(); pop(name); + flushAdders(); } 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 ee2c7aa..bd2e877 100644 --- a/src/main/java/me/topchetoeu/jscript/compilation/control/BreakNode.java +++ b/src/main/java/me/topchetoeu/jscript/compilation/control/BreakNode.java @@ -15,12 +15,10 @@ public class BreakNode extends Node { public final String label; @Override public void compile(CompileResult target, boolean pollute) { - var res = LabelContext.getBreak(target.env).getJump(); - if (res == null) { + if (!LabelContext.getBreak(target.env).jump(target)) { if (label != null) throw new SyntaxException(loc(), String.format("Undefined label '%s'", label)); else throw new SyntaxException(loc(), "Illegal break statement"); } - target.add(res); if (pollute) target.add(Instruction.pushUndefined()); } diff --git a/src/main/java/me/topchetoeu/jscript/compilation/control/ContinueNode.java b/src/main/java/me/topchetoeu/jscript/compilation/control/ContinueNode.java index 2b8a677..f0b13ed 100644 --- a/src/main/java/me/topchetoeu/jscript/compilation/control/ContinueNode.java +++ b/src/main/java/me/topchetoeu/jscript/compilation/control/ContinueNode.java @@ -15,12 +15,10 @@ public class ContinueNode extends Node { public final String label; @Override public void compile(CompileResult target, boolean pollute) { - var res = LabelContext.getCont(target.env).getJump(); - if (res == null) { + if (!LabelContext.getCont(target.env).jump(target)) { if (label != null) throw new SyntaxException(loc(), String.format("Undefined label '%s'", label)); else throw new SyntaxException(loc(), "Illegal continue statement"); } - target.add(res); if (pollute) target.add(Instruction.pushUndefined()); } diff --git a/src/main/java/me/topchetoeu/jscript/compilation/control/DoWhileNode.java b/src/main/java/me/topchetoeu/jscript/compilation/control/DoWhileNode.java index 1f3de82..6f64061 100644 --- a/src/main/java/me/topchetoeu/jscript/compilation/control/DoWhileNode.java +++ b/src/main/java/me/topchetoeu/jscript/compilation/control/DoWhileNode.java @@ -27,13 +27,14 @@ public class DoWhileNode extends Node { LabelContext.pushLoop(target.env, loc(), label, end, start); body.compile(target, false, BreakpointType.STEP_OVER); - LabelContext.popLoop(target.env, label); mid.set(target.size()); condition.compile(target, true, BreakpointType.STEP_OVER); int endI = target.size(); end.set(endI + 1); + LabelContext.popLoop(target.env, label); + target.add(Instruction.jmpIf(start - endI)); } diff --git a/src/main/java/me/topchetoeu/jscript/compilation/control/ForInNode.java b/src/main/java/me/topchetoeu/jscript/compilation/control/ForInNode.java index 454cfb3..17de917 100644 --- a/src/main/java/me/topchetoeu/jscript/compilation/control/ForInNode.java +++ b/src/main/java/me/topchetoeu/jscript/compilation/control/ForInNode.java @@ -8,14 +8,15 @@ import me.topchetoeu.jscript.common.parsing.Parsing; import me.topchetoeu.jscript.common.parsing.Source; import me.topchetoeu.jscript.compilation.CompileResult; import me.topchetoeu.jscript.compilation.CompoundNode; -import me.topchetoeu.jscript.compilation.DeferredIntSupplier; import me.topchetoeu.jscript.compilation.JavaScript; import me.topchetoeu.jscript.compilation.LabelContext; +import me.topchetoeu.jscript.compilation.DeferredIntSupplier; import me.topchetoeu.jscript.compilation.Node; -import me.topchetoeu.jscript.compilation.patterns.Binding; +import me.topchetoeu.jscript.compilation.values.VariableNode; public class ForInNode extends Node { - public final Binding binding; + public final boolean isDecl; + public final VariableNode binding; public final Node object, body; public final String label; @@ -25,8 +26,6 @@ public class ForInNode extends Node { } @Override public void compile(CompileResult target, boolean pollute) { - binding.declareLateInit(target); - object.compile(target, true, BreakpointType.STEP_OVER); target.add(Instruction.keys(false, true)); @@ -35,27 +34,32 @@ public class ForInNode extends Node { int mid = target.temp(); target.add(Instruction.loadMember("value")).setLocation(binding.loc()); - binding.assign(target, false); + target.add(VariableNode.toInit(target, loc(), binding.name)); + target.setLocationAndDebug(object.loc(), BreakpointType.STEP_OVER); var end = new DeferredIntSupplier(); LabelContext.pushLoop(target.env, loc(), label, end, start); CompoundNode.compileMultiEntry(body, target, false, BreakpointType.STEP_OVER); - LabelContext.popLoop(target.env, label); int endI = target.size(); target.add(Instruction.jmp(start - endI)); target.add(Instruction.discard()); target.set(mid, Instruction.jmpIfNot(endI - mid + 1)); + + end.set(endI); + LabelContext.popLoop(target.env, label); + if (pollute) target.add(Instruction.pushUndefined()); } - public ForInNode(Location loc, String label, Binding binding, Node object, Node body) { + public ForInNode(Location loc, String label, VariableNode binding, boolean isDecl, Node object, Node body) { super(loc); this.label = label; this.binding = binding; + this.isDecl = isDecl; this.object = object; this.body = body; } @@ -76,9 +80,15 @@ public class ForInNode extends Node { n++; n += Parsing.skipEmpty(src, i + n); - var binding = Binding.parse(src, i + n); - if (!binding.isSuccess()) return ParseRes.error(src.loc(i + n), "Expected a binding in for-in loop"); - n += binding.n; + var varKw = JavaScript.parseDeclarationType(src, i + n); + n += varKw.n; + n += Parsing.skipEmpty(src, i + n); + + var bindingLoc = src.loc(i + n); + + var name = Parsing.parseIdentifier(src, i + n); + if (!name.isSuccess()) return name.chainError(src.loc(i + n), "Expected a variable name"); + n += name.n; n += Parsing.skipEmpty(src, i + n); if (!Parsing.isIdentifier(src, i + n, "in")) return ParseRes.error(src.loc(i + n), "Expected 'in' keyword after variable declaration"); @@ -96,6 +106,6 @@ public class ForInNode extends Node { if (!bodyRes.isSuccess()) return bodyRes.chainError(src.loc(i + n), "Expected a for-in body"); n += bodyRes.n; - return ParseRes.res(new ForInNode(loc, label.result, binding.result, obj.result, bodyRes.result), n); + return ParseRes.res(new ForInNode(loc, label.result, new VariableNode(bindingLoc, name.result), varKw.isSuccess(), obj.result, bodyRes.result), n); } } diff --git a/src/main/java/me/topchetoeu/jscript/compilation/control/ForNode.java b/src/main/java/me/topchetoeu/jscript/compilation/control/ForNode.java index 2b78601..8d82215 100644 --- a/src/main/java/me/topchetoeu/jscript/compilation/control/ForNode.java +++ b/src/main/java/me/topchetoeu/jscript/compilation/control/ForNode.java @@ -25,8 +25,6 @@ public class ForNode extends Node { } @Override public void compile(CompileResult target, boolean pollute) { var subtarget = target.subtarget(); - subtarget.scope.singleEntry = false; - subtarget.beginScope(); declaration.compile(subtarget, false, BreakpointType.STEP_OVER); @@ -38,20 +36,16 @@ public class ForNode extends Node { LabelContext.pushLoop(subtarget.env, loc(), label, end, start); CompoundNode.compileMultiEntry(body, subtarget, false, BreakpointType.STEP_OVER); - LabelContext.popLoop(subtarget.env, label); - - subtarget.reallocScope(); CompoundNode.compileMultiEntry(assignment, subtarget, false, BreakpointType.STEP_OVER); int endI = subtarget.size(); end.set(endI); + LabelContext.popLoop(subtarget.env, label); subtarget.add(Instruction.jmp(start - endI)); subtarget.set(mid, Instruction.jmpIfNot(endI - mid + 1)); if (pollute) subtarget.add(Instruction.pushUndefined()); - - subtarget.endScope(); } public ForNode(Location loc, String label, Node declaration, Node condition, Node assignment, Node body) { diff --git a/src/main/java/me/topchetoeu/jscript/compilation/control/SwitchNode.java b/src/main/java/me/topchetoeu/jscript/compilation/control/SwitchNode.java index 51cb2cc..db40293 100644 --- a/src/main/java/me/topchetoeu/jscript/compilation/control/SwitchNode.java +++ b/src/main/java/me/topchetoeu/jscript/compilation/control/SwitchNode.java @@ -43,41 +43,37 @@ public class SwitchNode extends Node { value.compile(target, true, BreakpointType.STEP_OVER); - var subtarget = target.subtarget(); - subtarget.beginScope(); - // TODO: create a jump map for (var ccase : cases) { - subtarget.add(Instruction.dup()); - ccase.value.compile(subtarget, true); - subtarget.add(Instruction.operation(Operation.EQUALS)); - caseToStatement.put(subtarget.temp(), ccase.statementI); + target.add(Instruction.dup()); + ccase.value.compile(target, true); + target.add(Instruction.operation(Operation.EQUALS)); + caseToStatement.put(target.temp(), ccase.statementI); } - int start = subtarget.temp(); + int start = target.temp(); var end = new DeferredIntSupplier(); LabelContext.getBreak(target.env).push(loc(), label, end); for (var stm : body) { - statementToIndex.put(statementToIndex.size(), subtarget.size()); - stm.compile(subtarget, false, BreakpointType.STEP_OVER); + statementToIndex.put(statementToIndex.size(), target.size()); + stm.compile(target, false, BreakpointType.STEP_OVER); } + + int endI = target.size(); + end.set(endI); LabelContext.getBreak(target.env).pop(label); - subtarget.endScope(); + target.add(Instruction.discard()); + if (pollute) target.add(Instruction.pushUndefined()); - int endI = subtarget.size(); - end.set(endI); - subtarget.add(Instruction.discard()); - if (pollute) subtarget.add(Instruction.pushUndefined()); - - if (defaultI < 0 || defaultI >= body.length) subtarget.set(start, Instruction.jmp(endI - start)); - else subtarget.set(start, Instruction.jmp(statementToIndex.get(defaultI) - start)); + if (defaultI < 0 || defaultI >= body.length) target.set(start, Instruction.jmp(endI - start)); + else target.set(start, Instruction.jmp(statementToIndex.get(defaultI) - start)); for (var el : caseToStatement.entrySet()) { var i = statementToIndex.get(el.getValue()); if (i == null) i = endI; - subtarget.set(el.getKey(), Instruction.jmpIf(i - el.getKey())); + target.set(el.getKey(), Instruction.jmpIf(i - el.getKey())); } } diff --git a/src/main/java/me/topchetoeu/jscript/compilation/control/TryNode.java b/src/main/java/me/topchetoeu/jscript/compilation/control/TryNode.java index 18700b3..f9e8846 100644 --- a/src/main/java/me/topchetoeu/jscript/compilation/control/TryNode.java +++ b/src/main/java/me/topchetoeu/jscript/compilation/control/TryNode.java @@ -12,7 +12,6 @@ import me.topchetoeu.jscript.compilation.DeferredIntSupplier; import me.topchetoeu.jscript.compilation.JavaScript; import me.topchetoeu.jscript.compilation.LabelContext; import me.topchetoeu.jscript.compilation.Node; -import me.topchetoeu.jscript.compilation.scope.Variable; public class TryNode extends Node { public final CompoundNode tryBody; @@ -42,17 +41,11 @@ public class TryNode extends Node { catchStart = target.size() - start; if (captureName != null) { - var subtarget = target.subtarget(); - subtarget.beginScope(); - subtarget.scope.singleEntry = true; - - var catchVar = subtarget.scope.defineStrict(new Variable(captureName, false), catchBody.loc()); - subtarget.add(Instruction.loadError()); - subtarget.add(catchVar.index().toInit()); - catchBody.compile(subtarget, false); - subtarget.endScope(); - - subtarget.scope.end(); + var catchVar = target.scope.defineCatch(captureName); + target.add(Instruction.loadError()); + target.add(catchVar.index().toInit()); + catchBody.compile(target, false); + target.scope.undefineCatch(); } else catchBody.compile(target, false); diff --git a/src/main/java/me/topchetoeu/jscript/compilation/control/WhileNode.java b/src/main/java/me/topchetoeu/jscript/compilation/control/WhileNode.java index d6d9447..49c0509 100644 --- a/src/main/java/me/topchetoeu/jscript/compilation/control/WhileNode.java +++ b/src/main/java/me/topchetoeu/jscript/compilation/control/WhileNode.java @@ -30,10 +30,10 @@ public class WhileNode extends Node { LabelContext.pushLoop(target.env, loc(), label, end, start); CompoundNode.compileMultiEntry(body, target, false, BreakpointType.STEP_OVER); - LabelContext.popLoop(target.env, label); var endI = target.size(); end.set(endI + 1); + LabelContext.popLoop(target.env, label); target.add(Instruction.jmp(start - end.getAsInt())); target.set(mid, Instruction.jmpIfNot(end.getAsInt() - mid + 1));