From 2e8e123ec43884ddbc83397d653c5d4bce309c8a Mon Sep 17 00:00:00 2001 From: TopchetoEU <36534413+TopchetoEU@users.noreply.github.com> Date: Mon, 9 Dec 2024 23:37:08 +0200 Subject: [PATCH] small parser fixes --- .../jscript/common/parsing/Parsing.java | 1 + .../jscript/compilation/CompoundNode.java | 15 +----- .../jscript/compilation/FunctionNode.java | 13 ++--- .../compilation/FunctionStatementNode.java | 2 +- .../jscript/compilation/JavaScript.java | 2 +- .../compilation/VariableDeclareNode.java | 2 +- .../compilation/control/DoWhileNode.java | 1 + .../compilation/control/ForInNode.java | 5 +- .../jscript/compilation/control/ForNode.java | 22 ++++---- .../jscript/compilation/control/IfNode.java | 8 +-- .../compilation/control/SwitchNode.java | 5 +- .../jscript/compilation/control/TryNode.java | 4 +- .../compilation/control/WhileNode.java | 3 +- .../members/PropertyMemberNode.java | 7 --- .../jscript/compilation/values/ArrayNode.java | 4 +- .../jscript/compilation/values/RegexNode.java | 51 +++++++++++-------- .../compilation/values/VariableNode.java | 2 +- .../values/operations/DiscardNode.java | 2 +- .../values/operations/VariableAssignNode.java | 4 +- 19 files changed, 73 insertions(+), 80 deletions(-) diff --git a/src/main/java/me/topchetoeu/jscript/common/parsing/Parsing.java b/src/main/java/me/topchetoeu/jscript/common/parsing/Parsing.java index 96886d8..1af3a10 100644 --- a/src/main/java/me/topchetoeu/jscript/common/parsing/Parsing.java +++ b/src/main/java/me/topchetoeu/jscript/common/parsing/Parsing.java @@ -113,6 +113,7 @@ public class Parsing { return ParseRes.res((char)newC, n); } else if (c == '\n') return ParseRes.res(null, n); + else n--; } return ParseRes.res(src.at(i + n), n + 1); diff --git a/src/main/java/me/topchetoeu/jscript/compilation/CompoundNode.java b/src/main/java/me/topchetoeu/jscript/compilation/CompoundNode.java index bd761eb..0754795 100644 --- a/src/main/java/me/topchetoeu/jscript/compilation/CompoundNode.java +++ b/src/main/java/me/topchetoeu/jscript/compilation/CompoundNode.java @@ -23,7 +23,7 @@ public class CompoundNode extends Node { for (var stm : statements) stm.compileFunctions(target); } - public void compile(CompileResult target, boolean pollute, boolean singleEntry, BreakpointType type) { + public void compile(CompileResult target, boolean pollute, BreakpointType type) { List statements = new ArrayList(); for (var stm : this.statements) { @@ -47,10 +47,6 @@ public class CompoundNode extends Node { } } - @Override public void compile(CompileResult target, boolean pollute, BreakpointType type) { - compile(target, pollute, true, type); - } - public CompoundNode setEnd(Location loc) { this.end = loc; return this; @@ -61,15 +57,6 @@ public class CompoundNode extends Node { this.statements = statements; } - public static void compileMultiEntry(Node node, CompileResult target, boolean pollute, BreakpointType type) { - if (node instanceof CompoundNode comp) { - comp.compile(target, pollute, false, type); - } - else { - node.compile(target, pollute, type); - } - } - public static ParseRes parseComma(Source src, int i, Node prev, int precedence) { if (precedence > 1) return ParseRes.failed(); diff --git a/src/main/java/me/topchetoeu/jscript/compilation/FunctionNode.java b/src/main/java/me/topchetoeu/jscript/compilation/FunctionNode.java index 9499cda..107d0d5 100644 --- a/src/main/java/me/topchetoeu/jscript/compilation/FunctionNode.java +++ b/src/main/java/me/topchetoeu/jscript/compilation/FunctionNode.java @@ -37,12 +37,7 @@ public abstract class FunctionNode extends Node { body.resolve(target); - for (var param : params) { - var index = scope.define(param.name); - - target.add(Instruction.loadArg(i++)); - target.add(index.index().toSet(false)); - } + for (var param : params) scope.define(param.name); // if (selfName != null && !scope.has(selfName, false)) { // var i = scope.defineSpecial(new Variable(selfName, true), end); @@ -52,6 +47,12 @@ public abstract class FunctionNode extends Node { // } body.compileFunctions(target); + + for (var param : params) { + target.add(Instruction.loadArg(i++)).setLocation(param.loc()); + target.add(scope.define(param.name).index().toSet(false)).setLocation(param.loc()); + } + body.compile(target, lastReturn, BreakpointType.NONE); return target; diff --git a/src/main/java/me/topchetoeu/jscript/compilation/FunctionStatementNode.java b/src/main/java/me/topchetoeu/jscript/compilation/FunctionStatementNode.java index b8c4c85..97a4e09 100644 --- a/src/main/java/me/topchetoeu/jscript/compilation/FunctionStatementNode.java +++ b/src/main/java/me/topchetoeu/jscript/compilation/FunctionStatementNode.java @@ -22,7 +22,7 @@ public class FunctionStatementNode extends FunctionNode { @Override public void compile(CompileResult target, boolean pollute, String name, BreakpointType bp) { target.add(Instruction.loadFunc(target.childrenIndices.get(this), name(name), captures(target))).setLocation(loc()); - target.add(VariableNode.toSet(target, end, this.name, false, true)); + target.add(VariableNode.toSet(target, end, this.name, false, true)).setLocation(loc()); if (pollute) target.add(Instruction.pushUndefined()); } diff --git a/src/main/java/me/topchetoeu/jscript/compilation/JavaScript.java b/src/main/java/me/topchetoeu/jscript/compilation/JavaScript.java index 7fda233..829d1f0 100644 --- a/src/main/java/me/topchetoeu/jscript/compilation/JavaScript.java +++ b/src/main/java/me/topchetoeu/jscript/compilation/JavaScript.java @@ -193,8 +193,8 @@ public final class JavaScript { IfNode::parse, WhileNode::parse, SwitchNode::parse, - ForInNode::parse, ForNode::parse, + ForInNode::parse, DoWhileNode::parse, TryNode::parse, CompoundNode::parse, diff --git a/src/main/java/me/topchetoeu/jscript/compilation/VariableDeclareNode.java b/src/main/java/me/topchetoeu/jscript/compilation/VariableDeclareNode.java index cb7170d..083bf57 100644 --- a/src/main/java/me/topchetoeu/jscript/compilation/VariableDeclareNode.java +++ b/src/main/java/me/topchetoeu/jscript/compilation/VariableDeclareNode.java @@ -32,7 +32,7 @@ public class VariableDeclareNode extends Node { for (var entry : values) { if (entry.value != null) { entry.value.compile(target, true); - target.add(VariableNode.toSet(target, loc(), entry.var.name, false, true)); + target.add(VariableNode.toSet(target, loc(), entry.var.name, false, true)).setLocation(loc()); } } 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 559f96f..704218b 100644 --- a/src/main/java/me/topchetoeu/jscript/compilation/control/DoWhileNode.java +++ b/src/main/java/me/topchetoeu/jscript/compilation/control/DoWhileNode.java @@ -62,6 +62,7 @@ public class DoWhileNode extends Node { var bodyRes = JavaScript.parseStatement(src, i + n); if (!bodyRes.isSuccess()) return bodyRes.chainError(src.loc(i + n), "Expected a do-while body."); n += bodyRes.n; + n += Parsing.skipEmpty(src, i + n); if (!Parsing.isIdentifier(src, i + n, "while")) return ParseRes.failed(); n += 5; 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 5e915e7..b176632 100644 --- a/src/main/java/me/topchetoeu/jscript/compilation/control/ForInNode.java +++ b/src/main/java/me/topchetoeu/jscript/compilation/control/ForInNode.java @@ -7,7 +7,6 @@ import me.topchetoeu.jscript.common.parsing.ParseRes; 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.JavaScript; import me.topchetoeu.jscript.compilation.LabelContext; import me.topchetoeu.jscript.compilation.DeferredIntSupplier; @@ -38,14 +37,14 @@ public class ForInNode extends Node { int mid = target.temp(); target.add(Instruction.loadMember("value")).setLocation(binding.loc()); - target.add(VariableNode.toSet(target, loc(), binding.name, false, true)); + target.add(VariableNode.toSet(target, loc(), binding.name, false, true)).setLocation(binding.loc()); 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); + body.compile(target, false, BreakpointType.STEP_OVER); int endI = target.size(); 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 91825d5..7eb2852 100644 --- a/src/main/java/me/topchetoeu/jscript/compilation/control/ForNode.java +++ b/src/main/java/me/topchetoeu/jscript/compilation/control/ForNode.java @@ -7,7 +7,6 @@ import me.topchetoeu.jscript.common.parsing.ParseRes; 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; @@ -24,31 +23,34 @@ public class ForNode extends Node { body.resolve(target); } @Override public void compileFunctions(CompileResult target) { - declaration.compileFunctions(target); - assignment.compileFunctions(target); - condition.compileFunctions(target); + if (declaration != null) declaration.compileFunctions(target); + if (assignment != null) assignment.compileFunctions(target); + if (condition != null) condition.compileFunctions(target); body.compileFunctions(target); } @Override public void compile(CompileResult target, boolean pollute) { - declaration.compile(target, false, BreakpointType.STEP_OVER); + if (declaration != null) declaration.compile(target, false, BreakpointType.STEP_OVER); int start = target.size(); - CompoundNode.compileMultiEntry(condition, target, true, BreakpointType.STEP_OVER); - int mid = target.temp(); + int mid = -1; + if (condition != null) { + condition.compile(target, true, BreakpointType.STEP_OVER); + mid = target.temp(); + } var end = new DeferredIntSupplier(); LabelContext.pushLoop(target.env, loc(), label, end, start); - CompoundNode.compileMultiEntry(body, target, false, BreakpointType.STEP_OVER); + body.compile(target, false, BreakpointType.STEP_OVER); - CompoundNode.compileMultiEntry(assignment, target, false, BreakpointType.STEP_OVER); + if (assignment != null) assignment.compile(target, false, BreakpointType.STEP_OVER); int endI = target.size(); end.set(endI); LabelContext.popLoop(target.env, label); target.add(Instruction.jmp(start - endI)); - target.set(mid, Instruction.jmpIfNot(endI - mid + 1)); + if (mid >= 0) target.set(mid, Instruction.jmpIfNot(endI - mid + 1)); if (pollute) target.add(Instruction.pushUndefined()); } diff --git a/src/main/java/me/topchetoeu/jscript/compilation/control/IfNode.java b/src/main/java/me/topchetoeu/jscript/compilation/control/IfNode.java index 8564d03..d6013b9 100644 --- a/src/main/java/me/topchetoeu/jscript/compilation/control/IfNode.java +++ b/src/main/java/me/topchetoeu/jscript/compilation/control/IfNode.java @@ -23,7 +23,7 @@ public class IfNode extends Node { @Override public void compileFunctions(CompileResult target) { condition.compileFunctions(target); body.compileFunctions(target); - if (elseBody != null) body.compileFunctions(target); + if (elseBody != null) elseBody.compileFunctions(target); } @Override public void compile(CompileResult target, boolean pollute, BreakpointType breakpoint) { condition.compile(target, true, breakpoint); @@ -33,7 +33,7 @@ public class IfNode extends Node { var end = new DeferredIntSupplier(); LabelContext.getBreak(target.env).push(loc(), label, end); - body.compile(target, false, BreakpointType.STEP_OVER); + body.compile(target, pollute, BreakpointType.STEP_OVER); LabelContext.getBreak(target.env).pop(label); int endI = target.size(); @@ -46,11 +46,11 @@ public class IfNode extends Node { var end = new DeferredIntSupplier(); LabelContext.getBreak(target.env).push(loc(), label, end); - body.compile(target, false, BreakpointType.STEP_OVER); + body.compile(target, pollute, BreakpointType.STEP_OVER); int mid = target.temp(); - elseBody.compile(target, false, BreakpointType.STEP_OVER); + elseBody.compile(target, pollute, BreakpointType.STEP_OVER); LabelContext.getBreak(target.env).pop(label); int endI = target.size(); 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 cce1309..f32baa2 100644 --- a/src/main/java/me/topchetoeu/jscript/compilation/control/SwitchNode.java +++ b/src/main/java/me/topchetoeu/jscript/compilation/control/SwitchNode.java @@ -62,7 +62,7 @@ public class SwitchNode extends Node { int start = target.temp(); var end = new DeferredIntSupplier(); - LabelContext.getBreak(target.env).push(loc(), label, end); + LabelContext.getBreak(target.env).pushLoop(loc(), label, end); for (var stm : body) { statementToIndex.put(statementToIndex.size(), target.size()); stm.compile(target, false, BreakpointType.STEP_OVER); @@ -70,7 +70,7 @@ public class SwitchNode extends Node { int endI = target.size(); end.set(endI); - LabelContext.getBreak(target.env).pop(label); + LabelContext.getBreak(target.env).popLoop(label); target.add(Instruction.discard()); if (pollute) target.add(Instruction.pushUndefined()); @@ -104,6 +104,7 @@ public class SwitchNode extends Node { var val = JavaScript.parseExpression(src, i + n, 0); if (!val.isSuccess()) return val.chainError(src.loc(i + n), "Expected a value after 'case'"); n += val.n; + n += Parsing.skipEmpty(src, i + n); if (!src.is(i + n, ":")) return ParseRes.error(src.loc(i + n), "Expected colons after 'case' value"); n++; 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 ffdef9e..f2dcda1 100644 --- a/src/main/java/me/topchetoeu/jscript/compilation/control/TryNode.java +++ b/src/main/java/me/topchetoeu/jscript/compilation/control/TryNode.java @@ -46,8 +46,8 @@ public class TryNode extends Node { if (captureName != null) { var catchVar = target.scope.defineCatch(captureName); - target.add(Instruction.loadError()); - target.add(catchVar.index().toSet(false)); + target.add(Instruction.loadError()).setLocation(catchBody.loc()); + target.add(catchVar.index().toSet(false)).setLocation(catchBody.loc()); catchBody.compile(target, false); target.scope.undefineCatch(); } 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 c1ba16e..13bbc2f 100644 --- a/src/main/java/me/topchetoeu/jscript/compilation/control/WhileNode.java +++ b/src/main/java/me/topchetoeu/jscript/compilation/control/WhileNode.java @@ -7,7 +7,6 @@ import me.topchetoeu.jscript.common.parsing.ParseRes; 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; @@ -33,7 +32,7 @@ public class WhileNode extends Node { LabelContext.pushLoop(target.env, loc(), label, end, start); - CompoundNode.compileMultiEntry(body, target, false, BreakpointType.STEP_OVER); + body.compile(target, false, BreakpointType.STEP_OVER); var endI = target.size(); end.set(endI + 1); diff --git a/src/main/java/me/topchetoeu/jscript/compilation/members/PropertyMemberNode.java b/src/main/java/me/topchetoeu/jscript/compilation/members/PropertyMemberNode.java index 4522750..279e560 100644 --- a/src/main/java/me/topchetoeu/jscript/compilation/members/PropertyMemberNode.java +++ b/src/main/java/me/topchetoeu/jscript/compilation/members/PropertyMemberNode.java @@ -42,13 +42,6 @@ public final class PropertyMemberNode extends FunctionNode implements Member { key.compile(target, true); target.add(Instruction.loadFunc(target.childrenIndices.get(this), name(name), captures(target))).setLocation(loc()); - target.add(VariableNode.toSet(target, end, name(name), false, true)); - target.add(Instruction.defProp(isSetter())); - } - - - @Override public void compile(CompileResult target, boolean pollute) { - super.compile(target, pollute); target.add(Instruction.defProp(isSetter())); } diff --git a/src/main/java/me/topchetoeu/jscript/compilation/values/ArrayNode.java b/src/main/java/me/topchetoeu/jscript/compilation/values/ArrayNode.java index ccfeb75..8e4ba22 100644 --- a/src/main/java/me/topchetoeu/jscript/compilation/values/ArrayNode.java +++ b/src/main/java/me/topchetoeu/jscript/compilation/values/ArrayNode.java @@ -16,7 +16,9 @@ public class ArrayNode extends Node { public final Node[] statements; @Override public void compileFunctions(CompileResult target) { - for (var stm : statements) stm.compileFunctions(target); + for (var stm : statements) { + if (stm != null) stm.compileFunctions(target); + } } @Override public void compile(CompileResult target, boolean pollute) { diff --git a/src/main/java/me/topchetoeu/jscript/compilation/values/RegexNode.java b/src/main/java/me/topchetoeu/jscript/compilation/values/RegexNode.java index 26807d4..11cab99 100644 --- a/src/main/java/me/topchetoeu/jscript/compilation/values/RegexNode.java +++ b/src/main/java/me/topchetoeu/jscript/compilation/values/RegexNode.java @@ -31,28 +31,35 @@ public class RegexNode extends Node { var inBrackets = false; - while (true) { - if (src.is(i + n, '[')) { - n++; - inBrackets = true; - source.append(src.at(i + n)); - continue; - } - else if (src.is(i + n, ']')) { - n++; - inBrackets = false; - source.append(src.at(i + n)); - continue; - } - else if (src.is(i + n, '/') && !inBrackets) { - n++; - break; - } - - var charRes = Parsing.parseChar(src, i + n); - if (charRes.result == null) return ParseRes.error(src.loc(i + n), "Multiline regular expressions are not allowed"); - source.append(charRes.result); - n++; + loop: while (true) { + switch (src.at(i + n)) { + case '[': + inBrackets = true; + source.append('['); + n++; + continue; + case ']': + inBrackets = false; + source.append(']'); + n++; + continue; + case '/': + n++; + if (inBrackets) { + source.append('/'); + continue; + } + else break loop; + case '\\': + source.append('\\'); + source.append(src.at(i + n + 1)); + n += 2; + break; + default: + source.append(src.at(i + n)); + n++; + break; + } } while (true) { diff --git a/src/main/java/me/topchetoeu/jscript/compilation/values/VariableNode.java b/src/main/java/me/topchetoeu/jscript/compilation/values/VariableNode.java index 39f4b99..9e76617 100644 --- a/src/main/java/me/topchetoeu/jscript/compilation/values/VariableNode.java +++ b/src/main/java/me/topchetoeu/jscript/compilation/values/VariableNode.java @@ -23,7 +23,7 @@ public class VariableNode extends Node implements ChangeTarget { } @Override public void afterAssign(CompileResult target, boolean pollute) { - target.add(VariableNode.toSet(target, loc(), name, pollute, false)); + target.add(VariableNode.toSet(target, loc(), name, pollute, false)).setLocation(loc()); } @Override public void compile(CompileResult target, boolean pollute) { diff --git a/src/main/java/me/topchetoeu/jscript/compilation/values/operations/DiscardNode.java b/src/main/java/me/topchetoeu/jscript/compilation/values/operations/DiscardNode.java index ba4b697..3e2315c 100644 --- a/src/main/java/me/topchetoeu/jscript/compilation/values/operations/DiscardNode.java +++ b/src/main/java/me/topchetoeu/jscript/compilation/values/operations/DiscardNode.java @@ -14,7 +14,7 @@ public class DiscardNode extends Node { public final Node value; @Override public void compileFunctions(CompileResult target) { - value.compileFunctions(target); + if (value != null) value.compileFunctions(target); } @Override public void compile(CompileResult target, boolean pollute) { diff --git a/src/main/java/me/topchetoeu/jscript/compilation/values/operations/VariableAssignNode.java b/src/main/java/me/topchetoeu/jscript/compilation/values/operations/VariableAssignNode.java index 9be0d0e..7474a0e 100644 --- a/src/main/java/me/topchetoeu/jscript/compilation/values/operations/VariableAssignNode.java +++ b/src/main/java/me/topchetoeu/jscript/compilation/values/operations/VariableAssignNode.java @@ -22,11 +22,11 @@ public class VariableAssignNode extends Node { target.add(VariableNode.toGet(target, loc(), name)); FunctionNode.compileWithName(value, target, true, name); target.add(Instruction.operation(operation)); - target.add(VariableNode.toSet(target, loc(), name, pollute, false)); + target.add(VariableNode.toSet(target, loc(), name, pollute, false)).setLocation(loc()); } else { FunctionNode.compileWithName(value, target, true, name); - target.add(VariableNode.toSet(target, loc(), name, pollute, false)); + target.add(VariableNode.toSet(target, loc(), name, pollute, false)).setLocation(loc()); } }