From 49dd72566914112e55a08bd3ec00735da45ce966 Mon Sep 17 00:00:00 2001 From: TopchetoEU <36534413+TopchetoEU@users.noreply.github.com> Date: Thu, 29 Feb 2024 00:23:14 +0200 Subject: [PATCH] refactor: fully separate event loop from context --- .../{compilation => common}/FunctionBody.java | 2 +- .../{compilation => common}/Instruction.java | 3 +- .../topchetoeu/jscript/common/Location.java | 12 ++- .../jscript/{core => common}/Operation.java | 2 +- .../me/topchetoeu/jscript/common/Reading.java | 5 - .../mapping/ConvertType.java | 2 +- .../mapping/FunctionMap.java | 18 +++- .../compilation/AssignableStatement.java | 2 +- .../jscript/compilation/CompileResult.java | 15 +-- .../compilation/CompoundStatement.java | 3 +- .../jscript/compilation/Statement.java | 2 +- .../compilation/ThrowSyntaxStatement.java | 1 + .../compilation/VariableDeclareStatement.java | 3 +- .../compilation/control/BreakStatement.java | 2 +- .../control/ContinueStatement.java | 2 +- .../compilation/control/DebugStatement.java | 2 +- .../compilation/control/DeleteStatement.java | 2 +- .../compilation/control/DoWhileStatement.java | 4 +- .../compilation/control/ForInStatement.java | 6 +- .../compilation/control/ForStatement.java | 4 +- .../compilation/control/IfStatement.java | 6 +- .../compilation/control/ReturnStatement.java | 2 +- .../compilation/control/SwitchStatement.java | 8 +- .../compilation/control/ThrowStatement.java | 2 +- .../compilation/control/TryStatement.java | 4 +- .../compilation/control/WhileStatement.java | 6 +- .../jscript/compilation/parsing/Operator.java | 2 +- .../jscript/compilation/parsing/Parsing.java | 59 ++++------ .../compilation/values/ArrayStatement.java | 2 +- .../compilation/values/CallStatement.java | 8 +- .../compilation/values/ChangeStatement.java | 4 +- .../compilation/values/ConstantStatement.java | 2 +- .../compilation/values/DiscardStatement.java | 2 +- .../compilation/values/FunctionStatement.java | 6 +- .../values/GlobalThisStatement.java | 2 +- .../values/IndexAssignStatement.java | 6 +- .../compilation/values/IndexStatement.java | 6 +- .../compilation/values/LazyAndStatement.java | 2 +- .../compilation/values/LazyOrStatement.java | 2 +- .../compilation/values/ObjectStatement.java | 2 +- .../values/OperationStatement.java | 4 +- .../compilation/values/RegexStatement.java | 2 +- .../compilation/values/TypeofStatement.java | 2 +- .../values/VariableAssignStatement.java | 4 +- .../values/VariableIndexStatement.java | 2 +- .../compilation/values/VariableStatement.java | 4 +- .../me/topchetoeu/jscript/core/Compiler.java | 11 +- .../me/topchetoeu/jscript/core/Context.java | 87 ++++++--------- .../me/topchetoeu/jscript/core/Engine.java | 102 ++++++++++++------ .../topchetoeu/jscript/core/Environment.java | 70 +++++------- .../me/topchetoeu/jscript/core/EventLoop.java | 81 +++----------- .../topchetoeu/jscript/core/Extensions.java | 21 ++-- .../me/topchetoeu/jscript/core/Frame.java | 4 +- .../jscript/core/InstructionRunner.java | 3 +- .../jscript/core/debug/DebugContext.java | 45 ++++---- ...DebugController.java => DebugHandler.java} | 29 +++-- .../core/exceptions/EngineException.java | 5 +- .../jscript/core/values/CodeFunction.java | 2 +- .../jscript/core/values/Values.java | 8 +- .../jscript/lib/AsyncFunctionLib.java | 18 ++-- .../lib/AsyncGeneratorFunctionLib.java | 22 ++-- .../jscript/lib/EnvironmentLib.java | 39 ------- .../topchetoeu/jscript/lib/FunctionLib.java | 5 +- .../jscript/lib/GeneratorFunctionLib.java | 18 ++-- .../me/topchetoeu/jscript/lib/Internals.java | 15 ++- .../me/topchetoeu/jscript/lib/PromiseLib.java | 29 +++-- .../topchetoeu/jscript/utils/JSCompiler.java | 34 ++++++ .../topchetoeu/jscript/utils/JScriptRepl.java | 41 ++++--- .../jscript/utils/debug/DebugHandler.java | 33 ------ .../jscript/utils/debug/Debugger.java | 33 +++++- .../jscript/utils/filesystem/File.java | 13 ++- .../jscript/utils/filesystem/Filesystem.java | 6 +- .../jscript/utils/filesystem/MemoryFile.java | 1 + .../utils/interop/NativeWrapperProvider.java | 6 +- .../mapping/SourceMap.java | 3 +- .../{common => utils/mapping}/VLQ.java | 2 +- .../jscript/utils/modules/ModuleRepo.java | 8 +- .../jscript/utils/modules/SourceModule.java | 2 +- .../permissions/PermissionsProvider.java | 6 +- 79 files changed, 526 insertions(+), 519 deletions(-) rename src/java/me/topchetoeu/jscript/{compilation => common}/FunctionBody.java (90%) rename src/java/me/topchetoeu/jscript/{compilation => common}/Instruction.java (96%) rename src/java/me/topchetoeu/jscript/{core => common}/Operation.java (96%) rename src/java/me/topchetoeu/jscript/{compilation => common}/mapping/ConvertType.java (58%) rename src/java/me/topchetoeu/jscript/{compilation => common}/mapping/FunctionMap.java (86%) rename src/java/me/topchetoeu/jscript/core/debug/{DebugController.java => DebugHandler.java} (71%) delete mode 100644 src/java/me/topchetoeu/jscript/lib/EnvironmentLib.java create mode 100644 src/java/me/topchetoeu/jscript/utils/JSCompiler.java delete mode 100644 src/java/me/topchetoeu/jscript/utils/debug/DebugHandler.java rename src/java/me/topchetoeu/jscript/{compilation => utils}/mapping/SourceMap.java (97%) rename src/java/me/topchetoeu/jscript/{common => utils/mapping}/VLQ.java (98%) diff --git a/src/java/me/topchetoeu/jscript/compilation/FunctionBody.java b/src/java/me/topchetoeu/jscript/common/FunctionBody.java similarity index 90% rename from src/java/me/topchetoeu/jscript/compilation/FunctionBody.java rename to src/java/me/topchetoeu/jscript/common/FunctionBody.java index 6334eed..d0328a0 100644 --- a/src/java/me/topchetoeu/jscript/compilation/FunctionBody.java +++ b/src/java/me/topchetoeu/jscript/common/FunctionBody.java @@ -1,4 +1,4 @@ -package me.topchetoeu.jscript.compilation; +package me.topchetoeu.jscript.common; public class FunctionBody { public final FunctionBody[] children; diff --git a/src/java/me/topchetoeu/jscript/compilation/Instruction.java b/src/java/me/topchetoeu/jscript/common/Instruction.java similarity index 96% rename from src/java/me/topchetoeu/jscript/compilation/Instruction.java rename to src/java/me/topchetoeu/jscript/common/Instruction.java index b076242..949dfa5 100644 --- a/src/java/me/topchetoeu/jscript/compilation/Instruction.java +++ b/src/java/me/topchetoeu/jscript/common/Instruction.java @@ -1,11 +1,10 @@ -package me.topchetoeu.jscript.compilation; +package me.topchetoeu.jscript.common; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; import java.util.HashMap; -import me.topchetoeu.jscript.core.Operation; import me.topchetoeu.jscript.core.exceptions.SyntaxException; public class Instruction { diff --git a/src/java/me/topchetoeu/jscript/common/Location.java b/src/java/me/topchetoeu/jscript/common/Location.java index 1a65fc2..e3030b8 100644 --- a/src/java/me/topchetoeu/jscript/common/Location.java +++ b/src/java/me/topchetoeu/jscript/common/Location.java @@ -1,7 +1,9 @@ package me.topchetoeu.jscript.common; +import java.util.ArrayList; + public class Location implements Comparable { - public static final Location INTERNAL = new Location(0, 0, new Filename("jscript", "native")); + public static final Location INTERNAL = new Location(-1, -1, new Filename("jscript", "native")); private int line; private int start; private Filename filename; @@ -12,7 +14,13 @@ public class Location implements Comparable { @Override public String toString() { - return filename.toString() + ":" + line + ":" + start; + var res = new ArrayList(); + + if (filename != null) res.add(filename.toString()); + if (line >= 0) res.add(line + ""); + if (start >= 0) res.add(start + ""); + + return String.join(":", res); } public Location add(int n, boolean clone) { diff --git a/src/java/me/topchetoeu/jscript/core/Operation.java b/src/java/me/topchetoeu/jscript/common/Operation.java similarity index 96% rename from src/java/me/topchetoeu/jscript/core/Operation.java rename to src/java/me/topchetoeu/jscript/common/Operation.java index 6853ef5..262e99b 100644 --- a/src/java/me/topchetoeu/jscript/core/Operation.java +++ b/src/java/me/topchetoeu/jscript/common/Operation.java @@ -1,4 +1,4 @@ -package me.topchetoeu.jscript.core; +package me.topchetoeu.jscript.common; import java.util.HashMap; diff --git a/src/java/me/topchetoeu/jscript/common/Reading.java b/src/java/me/topchetoeu/jscript/common/Reading.java index 5242e46..30c0d5e 100644 --- a/src/java/me/topchetoeu/jscript/common/Reading.java +++ b/src/java/me/topchetoeu/jscript/common/Reading.java @@ -13,11 +13,6 @@ public class Reading { return reader.readLine(); } - /** - * Reads the given stream to a string - * @param in - * @return - */ public static String streamToString(InputStream in) { try { return new String(in.readAllBytes()); diff --git a/src/java/me/topchetoeu/jscript/compilation/mapping/ConvertType.java b/src/java/me/topchetoeu/jscript/common/mapping/ConvertType.java similarity index 58% rename from src/java/me/topchetoeu/jscript/compilation/mapping/ConvertType.java rename to src/java/me/topchetoeu/jscript/common/mapping/ConvertType.java index 397f887..22ff59b 100644 --- a/src/java/me/topchetoeu/jscript/compilation/mapping/ConvertType.java +++ b/src/java/me/topchetoeu/jscript/common/mapping/ConvertType.java @@ -1,4 +1,4 @@ -package me.topchetoeu.jscript.compilation.mapping; +package me.topchetoeu.jscript.common.mapping; public enum ConvertType { Exact, diff --git a/src/java/me/topchetoeu/jscript/compilation/mapping/FunctionMap.java b/src/java/me/topchetoeu/jscript/common/mapping/FunctionMap.java similarity index 86% rename from src/java/me/topchetoeu/jscript/compilation/mapping/FunctionMap.java rename to src/java/me/topchetoeu/jscript/common/mapping/FunctionMap.java index 21f4140..c9d63c5 100644 --- a/src/java/me/topchetoeu/jscript/compilation/mapping/FunctionMap.java +++ b/src/java/me/topchetoeu/jscript/common/mapping/FunctionMap.java @@ -1,4 +1,4 @@ -package me.topchetoeu.jscript.compilation.mapping; +package me.topchetoeu.jscript.common.mapping; import java.util.ArrayList; import java.util.Collections; @@ -9,8 +9,9 @@ import java.util.TreeMap; import java.util.TreeSet; import me.topchetoeu.jscript.common.Location; -import me.topchetoeu.jscript.compilation.Instruction.BreakpointType; +import me.topchetoeu.jscript.common.Instruction.BreakpointType; import me.topchetoeu.jscript.core.scope.LocalScopeRecord; +import me.topchetoeu.jscript.utils.mapping.SourceMap; public class FunctionMap { public static class FunctionMapBuilder { @@ -22,10 +23,12 @@ public class FunctionMap { } public FunctionMapBuilder setDebug(Location loc, BreakpointType type) { + if (loc == null || type == null || type == BreakpointType.NONE) return this; breakpoints.put(loc, type); return this; } public FunctionMapBuilder setLocation(int i, Location loc) { + if (loc == null || i < 0) return this; sourceMap.put(i, loc); return this; } @@ -36,9 +39,11 @@ public class FunctionMap { } public Location first() { + if (sourceMap.size() == 0) return null; return sourceMap.firstEntry().getValue(); } public Location last() { + if (sourceMap.size() == 0) return null; return sourceMap.lastEntry().getValue(); } @@ -68,7 +73,9 @@ public class FunctionMap { public Location toLocation(int pc, boolean approxiamte) { var res = pcToLoc.get(pc); if (!approxiamte || res != null) return res; - return pcToLoc.headMap(pc, true).lastEntry().getValue(); + var entry = pcToLoc.headMap(pc, true).lastEntry(); + if (entry == null) return null; + else return entry.getValue(); } public Location toLocation(int pc) { return toLocation(pc, false); @@ -85,9 +92,11 @@ public class FunctionMap { } public Location start() { + if (pcToLoc.size() == 0) return null; return pcToLoc.firstEntry().getValue(); } public Location end() { + if (pcToLoc.size() == 0) return null; return pcToLoc.lastEntry().getValue(); } @@ -126,6 +135,9 @@ public class FunctionMap { if (b != null) pcToLoc.remove(b); if (a != null) locToPc.remove(a); + + pcToLoc.put(pc, loc); + locToPc.put(loc, pc); } for (var el : breakpoints.entrySet()) { if (el.getValue() == null || el.getValue() == BreakpointType.NONE) continue; diff --git a/src/java/me/topchetoeu/jscript/compilation/AssignableStatement.java b/src/java/me/topchetoeu/jscript/compilation/AssignableStatement.java index 48284b4..9602c2e 100644 --- a/src/java/me/topchetoeu/jscript/compilation/AssignableStatement.java +++ b/src/java/me/topchetoeu/jscript/compilation/AssignableStatement.java @@ -1,7 +1,7 @@ package me.topchetoeu.jscript.compilation; import me.topchetoeu.jscript.common.Location; -import me.topchetoeu.jscript.core.Operation; +import me.topchetoeu.jscript.common.Operation; public abstract class AssignableStatement extends Statement { public abstract Statement toAssign(Statement val, Operation operation); diff --git a/src/java/me/topchetoeu/jscript/compilation/CompileResult.java b/src/java/me/topchetoeu/jscript/compilation/CompileResult.java index d9852df..2fd5098 100644 --- a/src/java/me/topchetoeu/jscript/compilation/CompileResult.java +++ b/src/java/me/topchetoeu/jscript/compilation/CompileResult.java @@ -4,10 +4,12 @@ import java.util.List; import java.util.LinkedList; import java.util.Vector; +import me.topchetoeu.jscript.common.FunctionBody; +import me.topchetoeu.jscript.common.Instruction; import me.topchetoeu.jscript.common.Location; -import me.topchetoeu.jscript.compilation.Instruction.BreakpointType; -import me.topchetoeu.jscript.compilation.mapping.FunctionMap; -import me.topchetoeu.jscript.compilation.mapping.FunctionMap.FunctionMapBuilder; +import me.topchetoeu.jscript.common.Instruction.BreakpointType; +import me.topchetoeu.jscript.common.mapping.FunctionMap; +import me.topchetoeu.jscript.common.mapping.FunctionMap.FunctionMapBuilder; import me.topchetoeu.jscript.core.scope.LocalScopeRecord; public class CompileResult { @@ -59,6 +61,9 @@ public class CompileResult { return child; } + public FunctionMap map() { + return map.build(scope); + } public FunctionBody body() { var builtChildren = new FunctionBody[children.size()]; @@ -67,10 +72,6 @@ public class CompileResult { return new FunctionBody(scope.localsCount(), length, instructions.toArray(Instruction[]::new), builtChildren); } - public FunctionMap map() { - return map.build(); - } - public CompileResult(LocalScopeRecord scope) { this.scope = scope; } diff --git a/src/java/me/topchetoeu/jscript/compilation/CompoundStatement.java b/src/java/me/topchetoeu/jscript/compilation/CompoundStatement.java index ef1f644..06eed66 100644 --- a/src/java/me/topchetoeu/jscript/compilation/CompoundStatement.java +++ b/src/java/me/topchetoeu/jscript/compilation/CompoundStatement.java @@ -3,8 +3,9 @@ package me.topchetoeu.jscript.compilation; import java.util.List; import java.util.Vector; +import me.topchetoeu.jscript.common.Instruction; import me.topchetoeu.jscript.common.Location; -import me.topchetoeu.jscript.compilation.Instruction.BreakpointType; +import me.topchetoeu.jscript.common.Instruction.BreakpointType; import me.topchetoeu.jscript.compilation.values.FunctionStatement; public class CompoundStatement extends Statement { diff --git a/src/java/me/topchetoeu/jscript/compilation/Statement.java b/src/java/me/topchetoeu/jscript/compilation/Statement.java index d077d4a..de9d23b 100644 --- a/src/java/me/topchetoeu/jscript/compilation/Statement.java +++ b/src/java/me/topchetoeu/jscript/compilation/Statement.java @@ -1,7 +1,7 @@ package me.topchetoeu.jscript.compilation; import me.topchetoeu.jscript.common.Location; -import me.topchetoeu.jscript.compilation.Instruction.BreakpointType; +import me.topchetoeu.jscript.common.Instruction.BreakpointType; public abstract class Statement { private Location _loc; diff --git a/src/java/me/topchetoeu/jscript/compilation/ThrowSyntaxStatement.java b/src/java/me/topchetoeu/jscript/compilation/ThrowSyntaxStatement.java index 4e88f06..b03b8a8 100644 --- a/src/java/me/topchetoeu/jscript/compilation/ThrowSyntaxStatement.java +++ b/src/java/me/topchetoeu/jscript/compilation/ThrowSyntaxStatement.java @@ -1,5 +1,6 @@ package me.topchetoeu.jscript.compilation; +import me.topchetoeu.jscript.common.Instruction; import me.topchetoeu.jscript.core.exceptions.SyntaxException; public class ThrowSyntaxStatement extends Statement { diff --git a/src/java/me/topchetoeu/jscript/compilation/VariableDeclareStatement.java b/src/java/me/topchetoeu/jscript/compilation/VariableDeclareStatement.java index 90e4ac6..1f4b6a4 100644 --- a/src/java/me/topchetoeu/jscript/compilation/VariableDeclareStatement.java +++ b/src/java/me/topchetoeu/jscript/compilation/VariableDeclareStatement.java @@ -2,8 +2,9 @@ package me.topchetoeu.jscript.compilation; import java.util.List; +import me.topchetoeu.jscript.common.Instruction; import me.topchetoeu.jscript.common.Location; -import me.topchetoeu.jscript.compilation.Instruction.BreakpointType; +import me.topchetoeu.jscript.common.Instruction.BreakpointType; import me.topchetoeu.jscript.compilation.values.FunctionStatement; public class VariableDeclareStatement extends Statement { diff --git a/src/java/me/topchetoeu/jscript/compilation/control/BreakStatement.java b/src/java/me/topchetoeu/jscript/compilation/control/BreakStatement.java index 85a76c7..eafae48 100644 --- a/src/java/me/topchetoeu/jscript/compilation/control/BreakStatement.java +++ b/src/java/me/topchetoeu/jscript/compilation/control/BreakStatement.java @@ -1,8 +1,8 @@ package me.topchetoeu.jscript.compilation.control; +import me.topchetoeu.jscript.common.Instruction; import me.topchetoeu.jscript.common.Location; import me.topchetoeu.jscript.compilation.CompileResult; -import me.topchetoeu.jscript.compilation.Instruction; import me.topchetoeu.jscript.compilation.Statement; public class BreakStatement extends Statement { diff --git a/src/java/me/topchetoeu/jscript/compilation/control/ContinueStatement.java b/src/java/me/topchetoeu/jscript/compilation/control/ContinueStatement.java index 404eadd..a703321 100644 --- a/src/java/me/topchetoeu/jscript/compilation/control/ContinueStatement.java +++ b/src/java/me/topchetoeu/jscript/compilation/control/ContinueStatement.java @@ -1,8 +1,8 @@ package me.topchetoeu.jscript.compilation.control; +import me.topchetoeu.jscript.common.Instruction; import me.topchetoeu.jscript.common.Location; import me.topchetoeu.jscript.compilation.CompileResult; -import me.topchetoeu.jscript.compilation.Instruction; import me.topchetoeu.jscript.compilation.Statement; public class ContinueStatement extends Statement { diff --git a/src/java/me/topchetoeu/jscript/compilation/control/DebugStatement.java b/src/java/me/topchetoeu/jscript/compilation/control/DebugStatement.java index 84b763d..20d23ef 100644 --- a/src/java/me/topchetoeu/jscript/compilation/control/DebugStatement.java +++ b/src/java/me/topchetoeu/jscript/compilation/control/DebugStatement.java @@ -1,8 +1,8 @@ package me.topchetoeu.jscript.compilation.control; +import me.topchetoeu.jscript.common.Instruction; import me.topchetoeu.jscript.common.Location; import me.topchetoeu.jscript.compilation.CompileResult; -import me.topchetoeu.jscript.compilation.Instruction; import me.topchetoeu.jscript.compilation.Statement; public class DebugStatement extends Statement { diff --git a/src/java/me/topchetoeu/jscript/compilation/control/DeleteStatement.java b/src/java/me/topchetoeu/jscript/compilation/control/DeleteStatement.java index fe21e2d..9355182 100644 --- a/src/java/me/topchetoeu/jscript/compilation/control/DeleteStatement.java +++ b/src/java/me/topchetoeu/jscript/compilation/control/DeleteStatement.java @@ -1,8 +1,8 @@ package me.topchetoeu.jscript.compilation.control; +import me.topchetoeu.jscript.common.Instruction; import me.topchetoeu.jscript.common.Location; import me.topchetoeu.jscript.compilation.CompileResult; -import me.topchetoeu.jscript.compilation.Instruction; import me.topchetoeu.jscript.compilation.Statement; public class DeleteStatement extends Statement { diff --git a/src/java/me/topchetoeu/jscript/compilation/control/DoWhileStatement.java b/src/java/me/topchetoeu/jscript/compilation/control/DoWhileStatement.java index 28cc45b..2417902 100644 --- a/src/java/me/topchetoeu/jscript/compilation/control/DoWhileStatement.java +++ b/src/java/me/topchetoeu/jscript/compilation/control/DoWhileStatement.java @@ -1,10 +1,10 @@ package me.topchetoeu.jscript.compilation.control; +import me.topchetoeu.jscript.common.Instruction; import me.topchetoeu.jscript.common.Location; +import me.topchetoeu.jscript.common.Instruction.BreakpointType; import me.topchetoeu.jscript.compilation.CompileResult; -import me.topchetoeu.jscript.compilation.Instruction; import me.topchetoeu.jscript.compilation.Statement; -import me.topchetoeu.jscript.compilation.Instruction.BreakpointType; public class DoWhileStatement extends Statement { public final Statement condition, body; diff --git a/src/java/me/topchetoeu/jscript/compilation/control/ForInStatement.java b/src/java/me/topchetoeu/jscript/compilation/control/ForInStatement.java index 188c1cc..216509a 100644 --- a/src/java/me/topchetoeu/jscript/compilation/control/ForInStatement.java +++ b/src/java/me/topchetoeu/jscript/compilation/control/ForInStatement.java @@ -1,11 +1,11 @@ package me.topchetoeu.jscript.compilation.control; +import me.topchetoeu.jscript.common.Instruction; import me.topchetoeu.jscript.common.Location; +import me.topchetoeu.jscript.common.Operation; +import me.topchetoeu.jscript.common.Instruction.BreakpointType; import me.topchetoeu.jscript.compilation.CompileResult; -import me.topchetoeu.jscript.compilation.Instruction; import me.topchetoeu.jscript.compilation.Statement; -import me.topchetoeu.jscript.compilation.Instruction.BreakpointType; -import me.topchetoeu.jscript.core.Operation; public class ForInStatement extends Statement { public final String varName; diff --git a/src/java/me/topchetoeu/jscript/compilation/control/ForStatement.java b/src/java/me/topchetoeu/jscript/compilation/control/ForStatement.java index 0012f96..9a59613 100644 --- a/src/java/me/topchetoeu/jscript/compilation/control/ForStatement.java +++ b/src/java/me/topchetoeu/jscript/compilation/control/ForStatement.java @@ -1,10 +1,10 @@ package me.topchetoeu.jscript.compilation.control; +import me.topchetoeu.jscript.common.Instruction; import me.topchetoeu.jscript.common.Location; +import me.topchetoeu.jscript.common.Instruction.BreakpointType; import me.topchetoeu.jscript.compilation.CompileResult; -import me.topchetoeu.jscript.compilation.Instruction; import me.topchetoeu.jscript.compilation.Statement; -import me.topchetoeu.jscript.compilation.Instruction.BreakpointType; public class ForStatement extends Statement { public final Statement declaration, assignment, condition, body; diff --git a/src/java/me/topchetoeu/jscript/compilation/control/IfStatement.java b/src/java/me/topchetoeu/jscript/compilation/control/IfStatement.java index 2eee62a..ba37671 100644 --- a/src/java/me/topchetoeu/jscript/compilation/control/IfStatement.java +++ b/src/java/me/topchetoeu/jscript/compilation/control/IfStatement.java @@ -1,10 +1,10 @@ package me.topchetoeu.jscript.compilation.control; +import me.topchetoeu.jscript.common.Instruction; import me.topchetoeu.jscript.common.Location; +import me.topchetoeu.jscript.common.Instruction.BreakpointType; import me.topchetoeu.jscript.compilation.CompileResult; -import me.topchetoeu.jscript.compilation.Instruction; import me.topchetoeu.jscript.compilation.Statement; -import me.topchetoeu.jscript.compilation.Instruction.BreakpointType; public class IfStatement extends Statement { public final Statement condition, body, elseBody; @@ -31,7 +31,7 @@ public class IfStatement extends Statement { elseBody.compile(target, pollute, breakpoint); int end = target.size(); - target.set(start, Instruction.jmpIfNot(mid - start - 1)); + target.set(start, Instruction.jmpIfNot(mid - start + 1)); target.set(mid, Instruction.jmp(end - mid)); } } diff --git a/src/java/me/topchetoeu/jscript/compilation/control/ReturnStatement.java b/src/java/me/topchetoeu/jscript/compilation/control/ReturnStatement.java index 5534c3e..4e915fd 100644 --- a/src/java/me/topchetoeu/jscript/compilation/control/ReturnStatement.java +++ b/src/java/me/topchetoeu/jscript/compilation/control/ReturnStatement.java @@ -1,8 +1,8 @@ package me.topchetoeu.jscript.compilation.control; +import me.topchetoeu.jscript.common.Instruction; import me.topchetoeu.jscript.common.Location; import me.topchetoeu.jscript.compilation.CompileResult; -import me.topchetoeu.jscript.compilation.Instruction; import me.topchetoeu.jscript.compilation.Statement; public class ReturnStatement extends Statement { diff --git a/src/java/me/topchetoeu/jscript/compilation/control/SwitchStatement.java b/src/java/me/topchetoeu/jscript/compilation/control/SwitchStatement.java index 9d0cf25..bf4988c 100644 --- a/src/java/me/topchetoeu/jscript/compilation/control/SwitchStatement.java +++ b/src/java/me/topchetoeu/jscript/compilation/control/SwitchStatement.java @@ -2,13 +2,13 @@ package me.topchetoeu.jscript.compilation.control; import java.util.HashMap; +import me.topchetoeu.jscript.common.Instruction; import me.topchetoeu.jscript.common.Location; +import me.topchetoeu.jscript.common.Operation; +import me.topchetoeu.jscript.common.Instruction.BreakpointType; +import me.topchetoeu.jscript.common.Instruction.Type; import me.topchetoeu.jscript.compilation.CompileResult; -import me.topchetoeu.jscript.compilation.Instruction; import me.topchetoeu.jscript.compilation.Statement; -import me.topchetoeu.jscript.compilation.Instruction.BreakpointType; -import me.topchetoeu.jscript.compilation.Instruction.Type; -import me.topchetoeu.jscript.core.Operation; public class SwitchStatement extends Statement { public static class SwitchCase { diff --git a/src/java/me/topchetoeu/jscript/compilation/control/ThrowStatement.java b/src/java/me/topchetoeu/jscript/compilation/control/ThrowStatement.java index 253268b..156f7ae 100644 --- a/src/java/me/topchetoeu/jscript/compilation/control/ThrowStatement.java +++ b/src/java/me/topchetoeu/jscript/compilation/control/ThrowStatement.java @@ -1,8 +1,8 @@ package me.topchetoeu.jscript.compilation.control; +import me.topchetoeu.jscript.common.Instruction; import me.topchetoeu.jscript.common.Location; import me.topchetoeu.jscript.compilation.CompileResult; -import me.topchetoeu.jscript.compilation.Instruction; import me.topchetoeu.jscript.compilation.Statement; public class ThrowStatement extends Statement { diff --git a/src/java/me/topchetoeu/jscript/compilation/control/TryStatement.java b/src/java/me/topchetoeu/jscript/compilation/control/TryStatement.java index 2ca8eb7..41ce48f 100644 --- a/src/java/me/topchetoeu/jscript/compilation/control/TryStatement.java +++ b/src/java/me/topchetoeu/jscript/compilation/control/TryStatement.java @@ -1,10 +1,10 @@ package me.topchetoeu.jscript.compilation.control; +import me.topchetoeu.jscript.common.Instruction; import me.topchetoeu.jscript.common.Location; +import me.topchetoeu.jscript.common.Instruction.BreakpointType; import me.topchetoeu.jscript.compilation.CompileResult; -import me.topchetoeu.jscript.compilation.Instruction; import me.topchetoeu.jscript.compilation.Statement; -import me.topchetoeu.jscript.compilation.Instruction.BreakpointType; public class TryStatement extends Statement { public final Statement tryBody; diff --git a/src/java/me/topchetoeu/jscript/compilation/control/WhileStatement.java b/src/java/me/topchetoeu/jscript/compilation/control/WhileStatement.java index f7b3953..459e4ef 100644 --- a/src/java/me/topchetoeu/jscript/compilation/control/WhileStatement.java +++ b/src/java/me/topchetoeu/jscript/compilation/control/WhileStatement.java @@ -1,11 +1,11 @@ package me.topchetoeu.jscript.compilation.control; +import me.topchetoeu.jscript.common.Instruction; import me.topchetoeu.jscript.common.Location; +import me.topchetoeu.jscript.common.Instruction.BreakpointType; +import me.topchetoeu.jscript.common.Instruction.Type; import me.topchetoeu.jscript.compilation.CompileResult; -import me.topchetoeu.jscript.compilation.Instruction; import me.topchetoeu.jscript.compilation.Statement; -import me.topchetoeu.jscript.compilation.Instruction.BreakpointType; -import me.topchetoeu.jscript.compilation.Instruction.Type; public class WhileStatement extends Statement { public final Statement condition, body; diff --git a/src/java/me/topchetoeu/jscript/compilation/parsing/Operator.java b/src/java/me/topchetoeu/jscript/compilation/parsing/Operator.java index 80ce38a..3e06258 100644 --- a/src/java/me/topchetoeu/jscript/compilation/parsing/Operator.java +++ b/src/java/me/topchetoeu/jscript/compilation/parsing/Operator.java @@ -3,7 +3,7 @@ package me.topchetoeu.jscript.compilation.parsing; import java.util.HashMap; import java.util.Map; -import me.topchetoeu.jscript.core.Operation; +import me.topchetoeu.jscript.common.Operation; public enum Operator { MULTIPLY("*", Operation.MULTIPLY, 13), diff --git a/src/java/me/topchetoeu/jscript/compilation/parsing/Parsing.java b/src/java/me/topchetoeu/jscript/compilation/parsing/Parsing.java index 2c1c21c..5ba65b6 100644 --- a/src/java/me/topchetoeu/jscript/compilation/parsing/Parsing.java +++ b/src/java/me/topchetoeu/jscript/compilation/parsing/Parsing.java @@ -8,14 +8,15 @@ import java.util.LinkedHashMap; import java.util.List; import me.topchetoeu.jscript.common.Filename; +import me.topchetoeu.jscript.common.Instruction; import me.topchetoeu.jscript.common.Location; +import me.topchetoeu.jscript.common.Operation; import me.topchetoeu.jscript.compilation.*; import me.topchetoeu.jscript.compilation.VariableDeclareStatement.Pair; import me.topchetoeu.jscript.compilation.control.*; import me.topchetoeu.jscript.compilation.control.SwitchStatement.SwitchCase; import me.topchetoeu.jscript.compilation.parsing.ParseRes.State; import me.topchetoeu.jscript.compilation.values.*; -import me.topchetoeu.jscript.core.Operation; import me.topchetoeu.jscript.core.scope.LocalScopeRecord; import me.topchetoeu.jscript.core.exceptions.SyntaxException; @@ -400,6 +401,10 @@ public class Parsing { return -1; } + private static boolean inBounds(List tokens, int i) { + return i >= 0 && i < tokens.size(); + } + private static String parseString(Location loc, String literal) { var res = new StringBuilder(); @@ -605,49 +610,41 @@ public class Parsing { } public static ParseRes parseIdentifier(List tokens, int i) { - try { + if (inBounds(tokens, i)) { if (tokens.get(i).isIdentifier()) { return ParseRes.res(tokens.get(i).identifier(), 1); } else return ParseRes.failed(); } - catch (IndexOutOfBoundsException e) { - return ParseRes.failed(); - } + else return ParseRes.failed(); } public static ParseRes parseOperator(List tokens, int i) { - try { + if (inBounds(tokens, i)) { if (tokens.get(i).isOperator()) { return ParseRes.res(tokens.get(i).operator(), 1); } else return ParseRes.failed(); } - catch (IndexOutOfBoundsException e) { - return ParseRes.failed(); - } + else return ParseRes.failed(); } public static boolean isIdentifier(List tokens, int i, String lit) { - try { + if (inBounds(tokens, i)) { if (tokens.get(i).isIdentifier(lit)) { return true; } else return false; } - catch (IndexOutOfBoundsException e) { - return false; - } + else return false; } public static boolean isOperator(List tokens, int i, Operator op) { - try { + if (inBounds(tokens, i)) { if (tokens.get(i).isOperator(op)) { return true; } else return false; } - catch (IndexOutOfBoundsException e) { - return false; - } + else return false; } public static boolean isStatementEnd(List tokens, int i) { if (isOperator(tokens, i, Operator.SEMICOLON)) return true; @@ -662,32 +659,27 @@ public class Parsing { public static ParseRes parseString(Filename filename, List tokens, int i) { var loc = getLoc(filename, tokens, i); - try { + if (inBounds(tokens, i)) { if (tokens.get(i).isString()) { return ParseRes.res(new ConstantStatement(loc, tokens.get(i).string()), 1); } else return ParseRes.failed(); } - catch (IndexOutOfBoundsException e) { - return ParseRes.failed(); - } + else return ParseRes.failed(); } public static ParseRes parseNumber(Filename filename, List tokens, int i) { var loc = getLoc(filename, tokens, i); - try { + if (inBounds(tokens, i)) { if (tokens.get(i).isNumber()) { return ParseRes.res(new ConstantStatement(loc, tokens.get(i).number()), 1); } else return ParseRes.failed(); } - catch (IndexOutOfBoundsException e) { - return ParseRes.failed(); - } - + else return ParseRes.failed(); } public static ParseRes parseRegex(Filename filename, List tokens, int i) { var loc = getLoc(filename, tokens, i); - try { + if (inBounds(tokens, i)) { if (tokens.get(i).isRegex()) { var val = tokens.get(i).regex(); var index = val.lastIndexOf('/'); @@ -697,9 +689,7 @@ public class Parsing { } else return ParseRes.failed(); } - catch (IndexOutOfBoundsException e) { - return ParseRes.failed(); - } + return ParseRes.failed(); } public static ParseRes parseArray(Filename filename, List tokens, int i) { @@ -776,15 +766,13 @@ public class Parsing { public static ParseRes parsePropName(Filename filename, List tokens, int i) { var loc = getLoc(filename, tokens, i); - try { + if (inBounds(tokens, i)) { var token = tokens.get(i); if (token.isNumber() || token.isIdentifier() || token.isString()) return ParseRes.res(token.rawValue, 1); else return ParseRes.error(loc, "Expected identifier, string or number literal."); } - catch (IndexOutOfBoundsException e) { - return ParseRes.failed(); - } + else return ParseRes.failed(); } public static ParseRes parseObjectProp(Filename filename, List tokens, int i) { var loc = getLoc(filename, tokens, i); @@ -1900,7 +1888,6 @@ public class Parsing { return target; } public static CompileResult compile(Filename filename, String raw) { - try { return compile(parse(filename, raw)); } - catch (SyntaxException e) { return compile(new ThrowSyntaxStatement(e)); } + return compile(parse(filename, raw)); } } diff --git a/src/java/me/topchetoeu/jscript/compilation/values/ArrayStatement.java b/src/java/me/topchetoeu/jscript/compilation/values/ArrayStatement.java index bc36644..e24e50b 100644 --- a/src/java/me/topchetoeu/jscript/compilation/values/ArrayStatement.java +++ b/src/java/me/topchetoeu/jscript/compilation/values/ArrayStatement.java @@ -1,8 +1,8 @@ package me.topchetoeu.jscript.compilation.values; +import me.topchetoeu.jscript.common.Instruction; import me.topchetoeu.jscript.common.Location; import me.topchetoeu.jscript.compilation.CompileResult; -import me.topchetoeu.jscript.compilation.Instruction; import me.topchetoeu.jscript.compilation.Statement; public class ArrayStatement extends Statement { diff --git a/src/java/me/topchetoeu/jscript/compilation/values/CallStatement.java b/src/java/me/topchetoeu/jscript/compilation/values/CallStatement.java index 38d44d6..412eacc 100644 --- a/src/java/me/topchetoeu/jscript/compilation/values/CallStatement.java +++ b/src/java/me/topchetoeu/jscript/compilation/values/CallStatement.java @@ -1,10 +1,10 @@ package me.topchetoeu.jscript.compilation.values; +import me.topchetoeu.jscript.common.Instruction; import me.topchetoeu.jscript.common.Location; +import me.topchetoeu.jscript.common.Instruction.BreakpointType; import me.topchetoeu.jscript.compilation.CompileResult; -import me.topchetoeu.jscript.compilation.Instruction; import me.topchetoeu.jscript.compilation.Statement; -import me.topchetoeu.jscript.compilation.Instruction.BreakpointType; public class CallStatement extends Statement { public final Statement func; @@ -24,8 +24,8 @@ public class CallStatement extends Statement { for (var arg : args) arg.compile(target, true); - if (isNew) target.add(Instruction.callNew(args.length)); - else target.add(Instruction.call(args.length)).setDebug(loc(), type); + if (isNew) target.add(Instruction.callNew(args.length)).setLocationAndDebug(loc(), type); + else target.add(Instruction.call(args.length)).setLocationAndDebug(loc(), type); if (!pollute) target.add(Instruction.discard()); } diff --git a/src/java/me/topchetoeu/jscript/compilation/values/ChangeStatement.java b/src/java/me/topchetoeu/jscript/compilation/values/ChangeStatement.java index 91fc07b..26ae605 100644 --- a/src/java/me/topchetoeu/jscript/compilation/values/ChangeStatement.java +++ b/src/java/me/topchetoeu/jscript/compilation/values/ChangeStatement.java @@ -1,11 +1,11 @@ package me.topchetoeu.jscript.compilation.values; +import me.topchetoeu.jscript.common.Instruction; import me.topchetoeu.jscript.common.Location; +import me.topchetoeu.jscript.common.Operation; import me.topchetoeu.jscript.compilation.AssignableStatement; import me.topchetoeu.jscript.compilation.CompileResult; -import me.topchetoeu.jscript.compilation.Instruction; import me.topchetoeu.jscript.compilation.Statement; -import me.topchetoeu.jscript.core.Operation; public class ChangeStatement extends Statement { public final AssignableStatement value; diff --git a/src/java/me/topchetoeu/jscript/compilation/values/ConstantStatement.java b/src/java/me/topchetoeu/jscript/compilation/values/ConstantStatement.java index 3470329..2def204 100644 --- a/src/java/me/topchetoeu/jscript/compilation/values/ConstantStatement.java +++ b/src/java/me/topchetoeu/jscript/compilation/values/ConstantStatement.java @@ -1,8 +1,8 @@ package me.topchetoeu.jscript.compilation.values; +import me.topchetoeu.jscript.common.Instruction; import me.topchetoeu.jscript.common.Location; import me.topchetoeu.jscript.compilation.CompileResult; -import me.topchetoeu.jscript.compilation.Instruction; import me.topchetoeu.jscript.compilation.Statement; public class ConstantStatement extends Statement { diff --git a/src/java/me/topchetoeu/jscript/compilation/values/DiscardStatement.java b/src/java/me/topchetoeu/jscript/compilation/values/DiscardStatement.java index 3e9650c..40ad0cd 100644 --- a/src/java/me/topchetoeu/jscript/compilation/values/DiscardStatement.java +++ b/src/java/me/topchetoeu/jscript/compilation/values/DiscardStatement.java @@ -1,8 +1,8 @@ package me.topchetoeu.jscript.compilation.values; +import me.topchetoeu.jscript.common.Instruction; import me.topchetoeu.jscript.common.Location; import me.topchetoeu.jscript.compilation.CompileResult; -import me.topchetoeu.jscript.compilation.Instruction; import me.topchetoeu.jscript.compilation.Statement; public class DiscardStatement extends Statement { diff --git a/src/java/me/topchetoeu/jscript/compilation/values/FunctionStatement.java b/src/java/me/topchetoeu/jscript/compilation/values/FunctionStatement.java index e084c5e..e714d73 100644 --- a/src/java/me/topchetoeu/jscript/compilation/values/FunctionStatement.java +++ b/src/java/me/topchetoeu/jscript/compilation/values/FunctionStatement.java @@ -1,12 +1,12 @@ package me.topchetoeu.jscript.compilation.values; +import me.topchetoeu.jscript.common.Instruction; import me.topchetoeu.jscript.common.Location; +import me.topchetoeu.jscript.common.Instruction.BreakpointType; +import me.topchetoeu.jscript.common.Instruction.Type; import me.topchetoeu.jscript.compilation.CompileResult; import me.topchetoeu.jscript.compilation.CompoundStatement; -import me.topchetoeu.jscript.compilation.Instruction; import me.topchetoeu.jscript.compilation.Statement; -import me.topchetoeu.jscript.compilation.Instruction.BreakpointType; -import me.topchetoeu.jscript.compilation.Instruction.Type; import me.topchetoeu.jscript.core.exceptions.SyntaxException; public class FunctionStatement extends Statement { diff --git a/src/java/me/topchetoeu/jscript/compilation/values/GlobalThisStatement.java b/src/java/me/topchetoeu/jscript/compilation/values/GlobalThisStatement.java index 1e9b2b4..b43cfc2 100644 --- a/src/java/me/topchetoeu/jscript/compilation/values/GlobalThisStatement.java +++ b/src/java/me/topchetoeu/jscript/compilation/values/GlobalThisStatement.java @@ -1,8 +1,8 @@ package me.topchetoeu.jscript.compilation.values; +import me.topchetoeu.jscript.common.Instruction; import me.topchetoeu.jscript.common.Location; import me.topchetoeu.jscript.compilation.CompileResult; -import me.topchetoeu.jscript.compilation.Instruction; import me.topchetoeu.jscript.compilation.Statement; public class GlobalThisStatement extends Statement { diff --git a/src/java/me/topchetoeu/jscript/compilation/values/IndexAssignStatement.java b/src/java/me/topchetoeu/jscript/compilation/values/IndexAssignStatement.java index 4e9b92f..1716336 100644 --- a/src/java/me/topchetoeu/jscript/compilation/values/IndexAssignStatement.java +++ b/src/java/me/topchetoeu/jscript/compilation/values/IndexAssignStatement.java @@ -1,11 +1,11 @@ package me.topchetoeu.jscript.compilation.values; +import me.topchetoeu.jscript.common.Instruction; import me.topchetoeu.jscript.common.Location; +import me.topchetoeu.jscript.common.Operation; +import me.topchetoeu.jscript.common.Instruction.BreakpointType; import me.topchetoeu.jscript.compilation.CompileResult; -import me.topchetoeu.jscript.compilation.Instruction; import me.topchetoeu.jscript.compilation.Statement; -import me.topchetoeu.jscript.compilation.Instruction.BreakpointType; -import me.topchetoeu.jscript.core.Operation; public class IndexAssignStatement extends Statement { public final Statement object; diff --git a/src/java/me/topchetoeu/jscript/compilation/values/IndexStatement.java b/src/java/me/topchetoeu/jscript/compilation/values/IndexStatement.java index f7d2a31..58315dc 100644 --- a/src/java/me/topchetoeu/jscript/compilation/values/IndexStatement.java +++ b/src/java/me/topchetoeu/jscript/compilation/values/IndexStatement.java @@ -1,12 +1,12 @@ package me.topchetoeu.jscript.compilation.values; +import me.topchetoeu.jscript.common.Instruction; import me.topchetoeu.jscript.common.Location; +import me.topchetoeu.jscript.common.Operation; +import me.topchetoeu.jscript.common.Instruction.BreakpointType; import me.topchetoeu.jscript.compilation.AssignableStatement; import me.topchetoeu.jscript.compilation.CompileResult; -import me.topchetoeu.jscript.compilation.Instruction; import me.topchetoeu.jscript.compilation.Statement; -import me.topchetoeu.jscript.compilation.Instruction.BreakpointType; -import me.topchetoeu.jscript.core.Operation; public class IndexStatement extends AssignableStatement { public final Statement object; diff --git a/src/java/me/topchetoeu/jscript/compilation/values/LazyAndStatement.java b/src/java/me/topchetoeu/jscript/compilation/values/LazyAndStatement.java index 8cf8813..306ec25 100644 --- a/src/java/me/topchetoeu/jscript/compilation/values/LazyAndStatement.java +++ b/src/java/me/topchetoeu/jscript/compilation/values/LazyAndStatement.java @@ -1,8 +1,8 @@ package me.topchetoeu.jscript.compilation.values; +import me.topchetoeu.jscript.common.Instruction; import me.topchetoeu.jscript.common.Location; import me.topchetoeu.jscript.compilation.CompileResult; -import me.topchetoeu.jscript.compilation.Instruction; import me.topchetoeu.jscript.compilation.Statement; public class LazyAndStatement extends Statement { diff --git a/src/java/me/topchetoeu/jscript/compilation/values/LazyOrStatement.java b/src/java/me/topchetoeu/jscript/compilation/values/LazyOrStatement.java index 7307edb..b1461ed 100644 --- a/src/java/me/topchetoeu/jscript/compilation/values/LazyOrStatement.java +++ b/src/java/me/topchetoeu/jscript/compilation/values/LazyOrStatement.java @@ -1,8 +1,8 @@ package me.topchetoeu.jscript.compilation.values; +import me.topchetoeu.jscript.common.Instruction; import me.topchetoeu.jscript.common.Location; import me.topchetoeu.jscript.compilation.CompileResult; -import me.topchetoeu.jscript.compilation.Instruction; import me.topchetoeu.jscript.compilation.Statement; public class LazyOrStatement extends Statement { diff --git a/src/java/me/topchetoeu/jscript/compilation/values/ObjectStatement.java b/src/java/me/topchetoeu/jscript/compilation/values/ObjectStatement.java index 1c46766..f5af390 100644 --- a/src/java/me/topchetoeu/jscript/compilation/values/ObjectStatement.java +++ b/src/java/me/topchetoeu/jscript/compilation/values/ObjectStatement.java @@ -3,9 +3,9 @@ package me.topchetoeu.jscript.compilation.values; import java.util.ArrayList; import java.util.Map; +import me.topchetoeu.jscript.common.Instruction; import me.topchetoeu.jscript.common.Location; import me.topchetoeu.jscript.compilation.CompileResult; -import me.topchetoeu.jscript.compilation.Instruction; import me.topchetoeu.jscript.compilation.Statement; public class ObjectStatement extends Statement { diff --git a/src/java/me/topchetoeu/jscript/compilation/values/OperationStatement.java b/src/java/me/topchetoeu/jscript/compilation/values/OperationStatement.java index 7e90a5e..cf66133 100644 --- a/src/java/me/topchetoeu/jscript/compilation/values/OperationStatement.java +++ b/src/java/me/topchetoeu/jscript/compilation/values/OperationStatement.java @@ -1,10 +1,10 @@ package me.topchetoeu.jscript.compilation.values; +import me.topchetoeu.jscript.common.Instruction; import me.topchetoeu.jscript.common.Location; +import me.topchetoeu.jscript.common.Operation; import me.topchetoeu.jscript.compilation.CompileResult; -import me.topchetoeu.jscript.compilation.Instruction; import me.topchetoeu.jscript.compilation.Statement; -import me.topchetoeu.jscript.core.Operation; public class OperationStatement extends Statement { public final Statement[] args; diff --git a/src/java/me/topchetoeu/jscript/compilation/values/RegexStatement.java b/src/java/me/topchetoeu/jscript/compilation/values/RegexStatement.java index b8b4bf2..fe2bdb8 100644 --- a/src/java/me/topchetoeu/jscript/compilation/values/RegexStatement.java +++ b/src/java/me/topchetoeu/jscript/compilation/values/RegexStatement.java @@ -1,8 +1,8 @@ package me.topchetoeu.jscript.compilation.values; +import me.topchetoeu.jscript.common.Instruction; import me.topchetoeu.jscript.common.Location; import me.topchetoeu.jscript.compilation.CompileResult; -import me.topchetoeu.jscript.compilation.Instruction; import me.topchetoeu.jscript.compilation.Statement; public class RegexStatement extends Statement { diff --git a/src/java/me/topchetoeu/jscript/compilation/values/TypeofStatement.java b/src/java/me/topchetoeu/jscript/compilation/values/TypeofStatement.java index 1abbf20..11ab78d 100644 --- a/src/java/me/topchetoeu/jscript/compilation/values/TypeofStatement.java +++ b/src/java/me/topchetoeu/jscript/compilation/values/TypeofStatement.java @@ -1,8 +1,8 @@ package me.topchetoeu.jscript.compilation.values; +import me.topchetoeu.jscript.common.Instruction; import me.topchetoeu.jscript.common.Location; import me.topchetoeu.jscript.compilation.CompileResult; -import me.topchetoeu.jscript.compilation.Instruction; import me.topchetoeu.jscript.compilation.Statement; public class TypeofStatement extends Statement { diff --git a/src/java/me/topchetoeu/jscript/compilation/values/VariableAssignStatement.java b/src/java/me/topchetoeu/jscript/compilation/values/VariableAssignStatement.java index 6445990..31bf6c9 100644 --- a/src/java/me/topchetoeu/jscript/compilation/values/VariableAssignStatement.java +++ b/src/java/me/topchetoeu/jscript/compilation/values/VariableAssignStatement.java @@ -1,10 +1,10 @@ package me.topchetoeu.jscript.compilation.values; +import me.topchetoeu.jscript.common.Instruction; import me.topchetoeu.jscript.common.Location; +import me.topchetoeu.jscript.common.Operation; import me.topchetoeu.jscript.compilation.CompileResult; -import me.topchetoeu.jscript.compilation.Instruction; import me.topchetoeu.jscript.compilation.Statement; -import me.topchetoeu.jscript.core.Operation; public class VariableAssignStatement extends Statement { public final String name; diff --git a/src/java/me/topchetoeu/jscript/compilation/values/VariableIndexStatement.java b/src/java/me/topchetoeu/jscript/compilation/values/VariableIndexStatement.java index 0c8dbb4..db3e4f0 100644 --- a/src/java/me/topchetoeu/jscript/compilation/values/VariableIndexStatement.java +++ b/src/java/me/topchetoeu/jscript/compilation/values/VariableIndexStatement.java @@ -1,8 +1,8 @@ package me.topchetoeu.jscript.compilation.values; +import me.topchetoeu.jscript.common.Instruction; import me.topchetoeu.jscript.common.Location; import me.topchetoeu.jscript.compilation.CompileResult; -import me.topchetoeu.jscript.compilation.Instruction; import me.topchetoeu.jscript.compilation.Statement; public class VariableIndexStatement extends Statement { diff --git a/src/java/me/topchetoeu/jscript/compilation/values/VariableStatement.java b/src/java/me/topchetoeu/jscript/compilation/values/VariableStatement.java index d251f9a..1ae3d2d 100644 --- a/src/java/me/topchetoeu/jscript/compilation/values/VariableStatement.java +++ b/src/java/me/topchetoeu/jscript/compilation/values/VariableStatement.java @@ -1,11 +1,11 @@ package me.topchetoeu.jscript.compilation.values; +import me.topchetoeu.jscript.common.Instruction; import me.topchetoeu.jscript.common.Location; +import me.topchetoeu.jscript.common.Operation; import me.topchetoeu.jscript.compilation.AssignableStatement; import me.topchetoeu.jscript.compilation.CompileResult; -import me.topchetoeu.jscript.compilation.Instruction; import me.topchetoeu.jscript.compilation.Statement; -import me.topchetoeu.jscript.core.Operation; public class VariableStatement extends AssignableStatement { public final String name; diff --git a/src/java/me/topchetoeu/jscript/core/Compiler.java b/src/java/me/topchetoeu/jscript/core/Compiler.java index c929a28..45fc51e 100644 --- a/src/java/me/topchetoeu/jscript/core/Compiler.java +++ b/src/java/me/topchetoeu/jscript/core/Compiler.java @@ -1,8 +1,17 @@ package me.topchetoeu.jscript.core; import me.topchetoeu.jscript.common.Filename; -import me.topchetoeu.jscript.compilation.FunctionBody; +import me.topchetoeu.jscript.common.FunctionBody; +import me.topchetoeu.jscript.core.exceptions.EngineException; public interface Compiler { + public Key KEY = new Key<>(); + public FunctionBody compile(Filename filename, String source); + + public static Compiler get(Extensions ext) { + return ext.get(KEY, (filename, src) -> { + throw EngineException.ofError("No compiler attached to engine."); + }); + } } diff --git a/src/java/me/topchetoeu/jscript/core/Context.java b/src/java/me/topchetoeu/jscript/core/Context.java index 16f31a6..64ba6b3 100644 --- a/src/java/me/topchetoeu/jscript/core/Context.java +++ b/src/java/me/topchetoeu/jscript/core/Context.java @@ -1,90 +1,66 @@ package me.topchetoeu.jscript.core; import java.util.Iterator; -import java.util.List; -import java.util.stream.Stream; -import java.util.stream.StreamSupport; import me.topchetoeu.jscript.common.Filename; import me.topchetoeu.jscript.core.debug.DebugContext; +import me.topchetoeu.jscript.core.values.CodeFunction; import me.topchetoeu.jscript.core.values.FunctionValue; -import me.topchetoeu.jscript.core.values.Symbol; import me.topchetoeu.jscript.core.exceptions.EngineException; -import me.topchetoeu.jscript.lib.EnvironmentLib; +import me.topchetoeu.jscript.core.scope.ValueVariable; public class Context implements Extensions { - public static final Context NULL = new Context(null); + public static final Context NULL = new Context(); public final Context parent; public final Environment environment; public final Frame frame; - public final Engine engine; + // public final Engine engine; public final int stackSize; - @Override public void add(Symbol key, T obj) { + @Override public void add(Key key, T obj) { if (environment != null) environment.add(key, obj); - else if (engine != null) engine.add(key, obj); + // else if (engine != null) engine.add(key, obj); } - @Override public T get(Symbol key) { + @Override public T get(Key key) { if (environment != null && environment.has(key)) return environment.get(key); - else if (engine != null && engine.has(key)) return engine.get(key); + // else if (engine != null && engine.has(key)) return engine.get(key); return null; } - @Override public boolean has(Symbol key) { + @Override public boolean has(Key key) { return - environment != null && environment.has(key) || - engine != null && engine.has(key); + environment != null && environment.has(key); + // engine != null && engine.has(key); } - @Override public boolean remove(Symbol key) { + @Override public boolean remove(Key key) { var res = false; if (environment != null) res |= environment.remove(key); - else if (engine != null) res |= engine.remove(key); + // else if (engine != null) res |= engine.remove(key); return res; } - @Override public Iterable keys() { - if (engine == null && environment == null) return List.of(); - if (engine == null) return environment.keys(); - if (environment == null) return engine.keys(); + @Override public Iterable> keys() { + return environment.keys(); - return () -> Stream.concat( - StreamSupport.stream(engine.keys().spliterator(), false), - StreamSupport.stream(environment.keys().spliterator(), false) - ).distinct().iterator(); + // if (engine == null && environment == null) return List.of(); + // if (engine == null) return environment.keys(); + // if (environment == null) return engine.keys(); + + // return () -> Stream.concat( + // StreamSupport.stream(engine.keys().spliterator(), false), + // StreamSupport.stream(environment.keys().spliterator(), false) + // ).distinct().iterator(); } public FunctionValue compile(Filename filename, String raw) { - var env = environment; - var result = Environment.compileFunc(this).call(this, null, raw, filename.toString(), new EnvironmentLib(env)); - DebugContext.get(this).onSource(filename, raw); - return (FunctionValue)result; - - // var rawMapChain = ((ArrayValue)Values.getMember(this, result, "mapChain")).toArray(); - // var breakpoints = new TreeSet<>( - // Arrays.stream(((ArrayValue)Values.getMember(this, result, "breakpoints")).toArray()) - // .map(v -> Location.parse(Values.toString(this, v))) - // .collect(Collectors.toList()) - // ); - // var maps = new SourceMap[rawMapChain.length]; - - // for (var i = 0; i < maps.length; i++) maps[i] = SourceMap.parse(Values.toString(this, (String)rawMapChain[i])); - - // var map = SourceMap.chain(maps); - - // if (map != null) { - // var newBreakpoints = new TreeSet(); - // for (var bp : breakpoints) { - // bp = map.toCompiled(bp); - // if (bp != null) newBreakpoints.add(bp); - // } - // breakpoints = newBreakpoints; - // } + var result = new CodeFunction(environment, filename.toString(), Compiler.get(this).compile(filename, raw), new ValueVariable[0]); + return result; } public Context pushFrame(Frame frame) { - var res = new Context(this, frame.function.environment, frame, engine, stackSize + 1); + var res = new Context(this, frame.function.environment, frame, stackSize + 1); return res; } @@ -111,11 +87,10 @@ public class Context implements Extensions { } - private Context(Context parent, Environment environment, Frame frame, Engine engine, int stackSize) { + private Context(Context parent, Environment environment, Frame frame, int stackSize) { this.parent = parent; this.environment = environment; this.frame = frame; - this.engine = engine; this.stackSize = stackSize; if (hasNotNull(Environment.MAX_STACK_COUNT) && stackSize > (int)get(Environment.MAX_STACK_COUNT)) { @@ -123,10 +98,10 @@ public class Context implements Extensions { } } - public Context(Engine engine) { - this(null, null, null, engine, 0); + public Context() { + this(null, null, null, 0); } - public Context(Engine engine, Environment env) { - this(null, env, null, engine, 0); + public Context(Environment env) { + this(null, env, null, 0); } } diff --git a/src/java/me/topchetoeu/jscript/core/Engine.java b/src/java/me/topchetoeu/jscript/core/Engine.java index 59d493e..5ca38c7 100644 --- a/src/java/me/topchetoeu/jscript/core/Engine.java +++ b/src/java/me/topchetoeu/jscript/core/Engine.java @@ -1,54 +1,92 @@ package me.topchetoeu.jscript.core; -import java.util.HashMap; +import java.util.concurrent.PriorityBlockingQueue; import me.topchetoeu.jscript.common.Filename; +import me.topchetoeu.jscript.common.ResultRunnable; import me.topchetoeu.jscript.common.events.DataNotifier; -import me.topchetoeu.jscript.compilation.FunctionBody; +import me.topchetoeu.jscript.core.exceptions.InterruptException; import me.topchetoeu.jscript.core.values.FunctionValue; -import me.topchetoeu.jscript.core.values.Symbol; -public class Engine extends EventLoop implements Extensions { - public static final HashMap functions = new HashMap<>(); +public class Engine implements EventLoop { + private static class Task implements Comparable> { + public final ResultRunnable runnable; + public final DataNotifier notifier = new DataNotifier<>(); + public final boolean micro; - private final Environment env = new Environment(); + public Task(ResultRunnable runnable, boolean micro) { + this.runnable = runnable; + this.micro = micro; + } - @Override - public void add(Symbol key, T obj) { - this.env.add(key, obj); - } - @Override - public T get(Symbol key) { - return this.env.get(key); - } - @Override - public boolean has(Symbol key) { - return this.env.has(key); - } - @Override - public boolean remove(Symbol key) { - return this.env.remove(key); - } - @Override - public Iterable keys() { - return env.keys(); + @Override + public int compareTo(Task other) { + return Integer.compare(this.micro ? 0 : 1, other.micro ? 0 : 1); + } } - public Engine copy() { - var res = new Engine(); - res.env.addAll(env); - return res; + private PriorityBlockingQueue> tasks = new PriorityBlockingQueue<>(); + private Thread thread; + + @Override + public DataNotifier pushMsg(ResultRunnable runnable, boolean micro) { + var msg = new Task(runnable, micro); + tasks.add(msg); + return msg.notifier; + } + + @SuppressWarnings("unchecked") + public void run(boolean untilEmpty) { + while (!untilEmpty || !tasks.isEmpty()) { + try { + var task = tasks.take(); + + try { + ((Task)task).notifier.next(task.runnable.run()); + } + catch (RuntimeException e) { + if (e instanceof InterruptException) throw e; + task.notifier.error(e); + } + } + catch (InterruptedException | InterruptException e) { + for (var msg : tasks) msg.notifier.error(new InterruptException(e)); + break; + } + } + } + + public Thread thread() { + return thread; + } + public Thread start() { + if (thread == null) { + thread = new Thread(() -> run(false), "Event loop #" + hashCode()); + thread.start(); + } + return thread; + } + public void stop() { + if (thread != null) thread.interrupt(); + thread = null; + } + + public boolean inLoopThread() { + return Thread.currentThread() == thread; + } + public boolean isRunning() { + return this.thread != null; } public DataNotifier pushMsg(boolean micro, Environment env, FunctionValue func, Object thisArg, Object ...args) { return pushMsg(() -> { - return func.call(new Context(this, env), thisArg, args); + return func.call(new Context(env), thisArg, args); }, micro); } public DataNotifier pushMsg(boolean micro, Environment env, Filename filename, String raw, Object thisArg, Object ...args) { return pushMsg(() -> { - var ctx = new Context(this, env); - return ctx.compile(filename, raw).call(new Context(this, env), thisArg, args); + var ctx = new Context(env); + return ctx.compile(filename, raw).call(new Context(env), thisArg, args); }, micro); } diff --git a/src/java/me/topchetoeu/jscript/core/Environment.java b/src/java/me/topchetoeu/jscript/core/Environment.java index eca0741..f848a53 100644 --- a/src/java/me/topchetoeu/jscript/core/Environment.java +++ b/src/java/me/topchetoeu/jscript/core/Environment.java @@ -5,77 +5,57 @@ import java.util.HashMap; import me.topchetoeu.jscript.core.scope.GlobalScope; import me.topchetoeu.jscript.core.values.FunctionValue; import me.topchetoeu.jscript.core.values.NativeFunction; -import me.topchetoeu.jscript.core.values.Symbol; +import me.topchetoeu.jscript.core.values.ObjectValue; import me.topchetoeu.jscript.core.exceptions.EngineException; import me.topchetoeu.jscript.utils.interop.NativeWrapperProvider; @SuppressWarnings("unchecked") public class Environment implements Extensions { + public static final Key COMPILE_FUNC = new Key<>(); - public static final HashMap symbols = new HashMap<>(); + public static final Key REGEX_CONSTR = new Key<>(); + public static final Key MAX_STACK_COUNT = new Key<>(); + public static final Key HIDE_STACK = new Key<>(); - public static final Symbol COMPILE_FUNC = Symbol.get("Environment.compile"); + public static final Key OBJECT_PROTO = new Key<>(); + public static final Key FUNCTION_PROTO = new Key<>(); + public static final Key ARRAY_PROTO = new Key<>(); + public static final Key BOOL_PROTO = new Key<>(); + public static final Key NUMBER_PROTO = new Key<>(); + public static final Key STRING_PROTO = new Key<>(); + public static final Key SYMBOL_PROTO = new Key<>(); + public static final Key ERROR_PROTO = new Key<>(); + public static final Key SYNTAX_ERR_PROTO = new Key<>(); + public static final Key TYPE_ERR_PROTO = new Key<>(); + public static final Key RANGE_ERR_PROTO = new Key<>(); - public static final Symbol REGEX_CONSTR = Symbol.get("Environment.regexConstructor"); - public static final Symbol STACK = Symbol.get("Environment.stack"); - public static final Symbol MAX_STACK_COUNT = Symbol.get("Environment.maxStackCount"); - public static final Symbol HIDE_STACK = Symbol.get("Environment.hideStack"); - - public static final Symbol OBJECT_PROTO = Symbol.get("Environment.objectPrototype"); - public static final Symbol FUNCTION_PROTO = Symbol.get("Environment.functionPrototype"); - public static final Symbol ARRAY_PROTO = Symbol.get("Environment.arrayPrototype"); - public static final Symbol BOOL_PROTO = Symbol.get("Environment.boolPrototype"); - public static final Symbol NUMBER_PROTO = Symbol.get("Environment.numberPrototype"); - public static final Symbol STRING_PROTO = Symbol.get("Environment.stringPrototype"); - public static final Symbol SYMBOL_PROTO = Symbol.get("Environment.symbolPrototype"); - public static final Symbol ERROR_PROTO = Symbol.get("Environment.errorPrototype"); - public static final Symbol SYNTAX_ERR_PROTO = Symbol.get("Environment.syntaxErrorPrototype"); - public static final Symbol TYPE_ERR_PROTO = Symbol.get("Environment.typeErrorPrototype"); - public static final Symbol RANGE_ERR_PROTO = Symbol.get("Environment.rangeErrorPrototype"); - - private HashMap data = new HashMap<>(); + private HashMap, Object> data = new HashMap<>(); public GlobalScope global; public WrapperProvider wrappers; - @Override public void add(Symbol key, T obj) { + @Override public void add(Key key, T obj) { data.put(key, obj); } - @Override public T get(Symbol key) { + @Override public T get(Key key) { return (T)data.get(key); } - @Override public boolean remove(Symbol key) { + @Override public boolean remove(Key key) { if (data.containsKey(key)) { data.remove(key); return true; } return false; } - @Override public boolean has(Symbol key) { + @Override public boolean has(Key key) { return data.containsKey(key); } - @Override public Iterable keys() { + @Override public Iterable> keys() { return data.keySet(); } - public static FunctionValue compileFunc(Extensions ext) { - return ext.init(COMPILE_FUNC, new NativeFunction("compile", args -> { - // var source = args.getString(0); - // var filename = args.getString(1); - - // var target = Parsing.compile(Filename.parse(filename), source); - // var res = new ObjectValue(); - - // res.defineProperty(args.ctx, "function", target.body()); - // res.defineProperty(args.ctx, "map", target.map()); - - // return res; - - throw EngineException.ofError("No compiler attached to engine."); - })); - } public static FunctionValue regexConstructor(Extensions ext) { - return ext.init(COMPILE_FUNC, new NativeFunction("RegExp", args -> { + return ext.init(REGEX_CONSTR, new NativeFunction("RegExp", args -> { throw EngineException.ofError("Regular expressions not supported.").setCtx(args.ctx); })); } @@ -95,8 +75,8 @@ public class Environment implements Extensions { return res; } - public Context context(Engine engine) { - return new Context(engine, this); + public Context context() { + return new Context(this); } public Environment(WrapperProvider nativeConverter, GlobalScope global) { diff --git a/src/java/me/topchetoeu/jscript/core/EventLoop.java b/src/java/me/topchetoeu/jscript/core/EventLoop.java index 4d9b7f1..4bb22e4 100644 --- a/src/java/me/topchetoeu/jscript/core/EventLoop.java +++ b/src/java/me/topchetoeu/jscript/core/EventLoop.java @@ -1,80 +1,23 @@ package me.topchetoeu.jscript.core; -import java.util.concurrent.PriorityBlockingQueue; - import me.topchetoeu.jscript.common.ResultRunnable; import me.topchetoeu.jscript.common.events.DataNotifier; -import me.topchetoeu.jscript.core.exceptions.InterruptException; +import me.topchetoeu.jscript.core.exceptions.EngineException; -public class EventLoop { - private static class Task implements Comparable { - public final ResultRunnable runnable; - public final DataNotifier notifier = new DataNotifier<>(); - public final boolean micro; +public interface EventLoop { + public static final Key KEY = new Key<>(); - public Task(ResultRunnable runnable, boolean micro) { - this.runnable = runnable; - this.micro = micro; - } - - @Override - public int compareTo(Task other) { - return Integer.compare(this.micro ? 0 : 1, other.micro ? 0 : 1); - } + public static EventLoop get(Extensions ext) { + if (ext.hasNotNull(KEY)) return ext.get(KEY); + else return new EventLoop() { + @Override public DataNotifier pushMsg(ResultRunnable runnable, boolean micro) { + throw EngineException.ofError("No event loop attached to environment."); + } + }; } - private PriorityBlockingQueue tasks = new PriorityBlockingQueue<>(); - private Thread thread; - - @SuppressWarnings("unchecked") - public DataNotifier pushMsg(ResultRunnable runnable, boolean micro) { - var msg = new Task(runnable, micro); - tasks.add(msg); - return (DataNotifier)msg.notifier; - } - public DataNotifier pushMsg(Runnable runnable, boolean micro) { + public DataNotifier pushMsg(ResultRunnable runnable, boolean micro); + public default DataNotifier pushMsg(Runnable runnable, boolean micro) { return pushMsg(() -> { runnable.run(); return null; }, micro); } - - public void run(boolean untilEmpty) { - while (!untilEmpty || !tasks.isEmpty()) { - try { - var task = tasks.take(); - - try { - task.notifier.next(task.runnable.run()); - } - catch (RuntimeException e) { - if (e instanceof InterruptException) throw e; - task.notifier.error(e); - } - } - catch (InterruptedException | InterruptException e) { - for (var msg : tasks) msg.notifier.error(new InterruptException(e)); - break; - } - } - } - - public Thread thread() { - return thread; - } - public Thread start() { - if (thread == null) { - thread = new Thread(() -> run(false), "Event loop #" + hashCode()); - thread.start(); - } - return thread; - } - public void stop() { - if (thread != null) thread.interrupt(); - thread = null; - } - - public boolean inLoopThread() { - return Thread.currentThread() == thread; - } - public boolean isRunning() { - return this.thread != null; - } } diff --git a/src/java/me/topchetoeu/jscript/core/Extensions.java b/src/java/me/topchetoeu/jscript/core/Extensions.java index 682ecca..fcb5bc0 100644 --- a/src/java/me/topchetoeu/jscript/core/Extensions.java +++ b/src/java/me/topchetoeu/jscript/core/Extensions.java @@ -1,34 +1,33 @@ package me.topchetoeu.jscript.core; -import me.topchetoeu.jscript.core.values.Symbol; - public interface Extensions { - T get(Symbol key); - void add(Symbol key, T obj); - Iterable keys(); + T get(Key key); + void add(Key key, T obj); + Iterable> keys(); - boolean has(Symbol key); - boolean remove(Symbol key); + boolean has(Key key); + boolean remove(Key key); - default boolean hasNotNull(Symbol key) { + default boolean hasNotNull(Key key) { return has(key) && get(key) != null; } - default T get(Symbol key, T defaultVal) { + default T get(Key key, T defaultVal) { if (has(key)) return get(key); else return defaultVal; } - default T init(Symbol key, T val) { + default T init(Key key, T val) { if (has(key)) return get(key); else { add(key, val); return val; } } + @SuppressWarnings("unchecked") default void addAll(Extensions source) { for (var key : source.keys()) { - add(key, source.get(key)); + add((Key)key, (Object)source.get(key)); } } } diff --git a/src/java/me/topchetoeu/jscript/core/Frame.java b/src/java/me/topchetoeu/jscript/core/Frame.java index e8483cc..b767961 100644 --- a/src/java/me/topchetoeu/jscript/core/Frame.java +++ b/src/java/me/topchetoeu/jscript/core/Frame.java @@ -3,7 +3,7 @@ package me.topchetoeu.jscript.core; import java.util.List; import java.util.Stack; -import me.topchetoeu.jscript.compilation.Instruction; +import me.topchetoeu.jscript.common.Instruction; import me.topchetoeu.jscript.core.debug.DebugContext; import me.topchetoeu.jscript.core.scope.LocalScope; import me.topchetoeu.jscript.core.scope.ValueVariable; @@ -159,7 +159,7 @@ public class Frame { returnValue = InstructionRunner.exec(ctx, instr, this); } catch (EngineException e) { - error = e.add(ctx, function.name, DebugContext.get(ctx).getMap(function).toLocation(codePtr, true)); + error = e.add(ctx, function.name, DebugContext.get(ctx).getMapOrEmpty(function).toLocation(codePtr, true)); } } } diff --git a/src/java/me/topchetoeu/jscript/core/InstructionRunner.java b/src/java/me/topchetoeu/jscript/core/InstructionRunner.java index 55bde56..78f42c1 100644 --- a/src/java/me/topchetoeu/jscript/core/InstructionRunner.java +++ b/src/java/me/topchetoeu/jscript/core/InstructionRunner.java @@ -2,7 +2,6 @@ package me.topchetoeu.jscript.core; import java.util.Collections; -import me.topchetoeu.jscript.compilation.Instruction; import me.topchetoeu.jscript.core.scope.ValueVariable; import me.topchetoeu.jscript.core.values.ArrayValue; import me.topchetoeu.jscript.core.values.CodeFunction; @@ -10,6 +9,8 @@ import me.topchetoeu.jscript.core.values.FunctionValue; import me.topchetoeu.jscript.core.values.ObjectValue; import me.topchetoeu.jscript.core.values.Symbol; import me.topchetoeu.jscript.core.values.Values; +import me.topchetoeu.jscript.common.Instruction; +import me.topchetoeu.jscript.common.Operation; import me.topchetoeu.jscript.core.exceptions.EngineException; public class InstructionRunner { diff --git a/src/java/me/topchetoeu/jscript/core/debug/DebugContext.java b/src/java/me/topchetoeu/jscript/core/debug/DebugContext.java index b94287a..b4cab7b 100644 --- a/src/java/me/topchetoeu/jscript/core/debug/DebugContext.java +++ b/src/java/me/topchetoeu/jscript/core/debug/DebugContext.java @@ -6,31 +6,31 @@ import java.util.List; import java.util.WeakHashMap; import me.topchetoeu.jscript.common.Filename; +import me.topchetoeu.jscript.common.FunctionBody; +import me.topchetoeu.jscript.common.Instruction; import me.topchetoeu.jscript.common.Location; -import me.topchetoeu.jscript.compilation.FunctionBody; -import me.topchetoeu.jscript.compilation.Instruction; -import me.topchetoeu.jscript.compilation.mapping.FunctionMap; +import me.topchetoeu.jscript.common.mapping.FunctionMap; import me.topchetoeu.jscript.core.Context; import me.topchetoeu.jscript.core.Extensions; import me.topchetoeu.jscript.core.Frame; +import me.topchetoeu.jscript.core.Key; import me.topchetoeu.jscript.core.values.CodeFunction; import me.topchetoeu.jscript.core.values.FunctionValue; -import me.topchetoeu.jscript.core.values.Symbol; import me.topchetoeu.jscript.core.exceptions.EngineException; -public class DebugContext implements DebugController { - public static final Symbol ENV_KEY = Symbol.get("Engine.debug"); - public static final Symbol IGNORE = Symbol.get("Engine.ignoreDebug"); +public class DebugContext { + public static final Key KEY = new Key<>(); + public static final Key IGNORE = new Key<>(); private HashMap sources; private WeakHashMap maps; - private DebugController debugger; + private DebugHandler debugger; - public boolean attachDebugger(DebugController debugger) { + public boolean attachDebugger(DebugHandler debugger) { if (this.debugger != null) return false; if (sources != null) { - for (var source : sources.entrySet()) debugger.onSource(source.getKey(), source.getValue()); + for (var source : sources.entrySet()) debugger.onSourceLoad(source.getKey(), source.getValue()); } this.debugger = debugger; @@ -41,8 +41,8 @@ public class DebugContext implements DebugController { return true; } - public DebugController debugger() { - if (debugger == null) return DebugController.empty(); + public DebugHandler debugger() { + if (debugger == null) return DebugHandler.empty(); else return debugger; } @@ -61,24 +61,27 @@ public class DebugContext implements DebugController { else return res; } public FunctionMap getMapOrEmpty(FunctionValue func) { - if (maps == null || !(func instanceof CodeFunction)) return null; + if (maps == null || !(func instanceof CodeFunction)) return FunctionMap.EMPTY; return getMapOrEmpty(((CodeFunction)func).body); } - @Override public void onFramePop(Context ctx, Frame frame) { + public void onFramePop(Context ctx, Frame frame) { if (debugger != null) debugger.onFramePop(ctx, frame); } - @Override public void onFramePush(Context ctx, Frame frame) { + public void onFramePush(Context ctx, Frame frame) { if (debugger != null) debugger.onFramePush(ctx, frame); } - @Override public boolean onInstruction(Context ctx, Frame frame, Instruction instruction, Object returnVal, EngineException error, boolean caught) { + public boolean onInstruction(Context ctx, Frame frame, Instruction instruction, Object returnVal, EngineException error, boolean caught) { if (debugger != null) return debugger.onInstruction(ctx, frame, instruction, returnVal, error, caught); else return false; } - @Override public void onSource(Filename filename, String source) { - if (debugger != null) debugger.onSource(filename, source); + public void onSource(Filename filename, String source) { + if (debugger != null) debugger.onSourceLoad(filename, source); if (sources != null) sources.put(filename, source); } + public void onFunctionLoad(FunctionBody func, FunctionMap map) { + if (maps != null) maps.put(func, map); + } private DebugContext(boolean enabled) { if (enabled) { @@ -92,10 +95,10 @@ public class DebugContext implements DebugController { } public static boolean enabled(Extensions exts) { - return exts.hasNotNull(ENV_KEY) && !exts.has(IGNORE); + return exts != null && exts.hasNotNull(KEY) && !exts.has(IGNORE); } public static DebugContext get(Extensions exts) { - if (enabled(exts)) return exts.get(ENV_KEY); + if (enabled(exts)) return exts.get(KEY); else return new DebugContext(false); } @@ -106,7 +109,7 @@ public class DebugContext implements DebugController { for (var el : ctx.frames()) { var name = el.function.name; - var map = dbgCtx.getMap(el.function); + var map = dbgCtx.getMapOrEmpty(el.function); Location loc = null; if (map != null) { diff --git a/src/java/me/topchetoeu/jscript/core/debug/DebugController.java b/src/java/me/topchetoeu/jscript/core/debug/DebugHandler.java similarity index 71% rename from src/java/me/topchetoeu/jscript/core/debug/DebugController.java rename to src/java/me/topchetoeu/jscript/core/debug/DebugHandler.java index e94e958..3e9ec4a 100644 --- a/src/java/me/topchetoeu/jscript/core/debug/DebugController.java +++ b/src/java/me/topchetoeu/jscript/core/debug/DebugHandler.java @@ -1,12 +1,14 @@ package me.topchetoeu.jscript.core.debug; import me.topchetoeu.jscript.common.Filename; -import me.topchetoeu.jscript.compilation.Instruction; +import me.topchetoeu.jscript.common.FunctionBody; +import me.topchetoeu.jscript.common.Instruction; +import me.topchetoeu.jscript.common.mapping.FunctionMap; import me.topchetoeu.jscript.core.Context; import me.topchetoeu.jscript.core.Frame; import me.topchetoeu.jscript.core.exceptions.EngineException; -public interface DebugController { +public interface DebugHandler { /** * Called when a script has been loaded * @param filename The name of the source @@ -14,7 +16,21 @@ public interface DebugController { * @param breakpoints A set of all the breakpointable locations in this source * @param map The source map associated with this file. null if this source map isn't mapped */ - void onSource(Filename filename, String source); + void onSourceLoad(Filename filename, String source); + + /** + * Called when a function body has been loaded + * @param body The body loaded + * @param map The map of the function + */ + void onFunctionLoad(FunctionBody body, FunctionMap map); + + // /** + // * Called when a function body has been loaded + // * @param body The body loaded + // * @param map The map of the function + // */ + // void onFunctionUnload(FunctionBody body, FunctionMap map); /** * Called immediatly before an instruction is executed, as well as after an instruction, if it has threw or returned. @@ -44,14 +60,15 @@ public interface DebugController { */ void onFramePop(Context ctx, Frame frame); - public static DebugController empty() { - return new DebugController () { + public static DebugHandler empty() { + return new DebugHandler () { @Override public void onFramePop(Context ctx, Frame frame) { } @Override public void onFramePush(Context ctx, Frame frame) { } @Override public boolean onInstruction(Context ctx, Frame frame, Instruction instruction, Object returnVal, EngineException error, boolean caught) { return false; } - @Override public void onSource(Filename filename, String source) { } + @Override public void onSourceLoad(Filename filename, String source) { } + @Override public void onFunctionLoad(FunctionBody body, FunctionMap map) { } }; } } diff --git a/src/java/me/topchetoeu/jscript/core/exceptions/EngineException.java b/src/java/me/topchetoeu/jscript/core/exceptions/EngineException.java index 27ed22e..f478e5c 100644 --- a/src/java/me/topchetoeu/jscript/core/exceptions/EngineException.java +++ b/src/java/me/topchetoeu/jscript/core/exceptions/EngineException.java @@ -5,7 +5,6 @@ import java.util.List; import me.topchetoeu.jscript.common.Location; import me.topchetoeu.jscript.core.Context; -import me.topchetoeu.jscript.core.Engine; import me.topchetoeu.jscript.core.Environment; import me.topchetoeu.jscript.core.values.ObjectValue; import me.topchetoeu.jscript.core.values.Values; @@ -35,7 +34,7 @@ public class EngineException extends RuntimeException { if (name.equals("")) name = null; if (ctx == null) this.ctx = null; - else this.ctx = new Context(ctx.engine, ctx.environment); + else this.ctx = new Context(ctx.environment); this.location = location; this.name = name; } @@ -44,7 +43,6 @@ public class EngineException extends RuntimeException { public final Object value; public EngineException cause; public Environment env = null; - public Engine engine = null; public final List stackTrace = new ArrayList<>(); public EngineException add(Context ctx, String name, Location location) { @@ -60,7 +58,6 @@ public class EngineException extends RuntimeException { } public EngineException setCtx(Context ctx) { if (this.env == null) this.env = ctx.environment; - if (this.engine == null) this.engine = ctx.engine; return this; } diff --git a/src/java/me/topchetoeu/jscript/core/values/CodeFunction.java b/src/java/me/topchetoeu/jscript/core/values/CodeFunction.java index e4e2a00..61336a3 100644 --- a/src/java/me/topchetoeu/jscript/core/values/CodeFunction.java +++ b/src/java/me/topchetoeu/jscript/core/values/CodeFunction.java @@ -1,6 +1,6 @@ package me.topchetoeu.jscript.core.values; -import me.topchetoeu.jscript.compilation.FunctionBody; +import me.topchetoeu.jscript.common.FunctionBody; import me.topchetoeu.jscript.core.Context; import me.topchetoeu.jscript.core.Environment; import me.topchetoeu.jscript.core.Frame; diff --git a/src/java/me/topchetoeu/jscript/core/values/Values.java b/src/java/me/topchetoeu/jscript/core/values/Values.java index 8f455ae..2dca2b8 100644 --- a/src/java/me/topchetoeu/jscript/core/values/Values.java +++ b/src/java/me/topchetoeu/jscript/core/values/Values.java @@ -12,9 +12,9 @@ import java.util.Iterator; import java.util.List; import java.util.Map; +import me.topchetoeu.jscript.common.Operation; import me.topchetoeu.jscript.core.Context; import me.topchetoeu.jscript.core.Environment; -import me.topchetoeu.jscript.core.Operation; import me.topchetoeu.jscript.core.debug.DebugContext; import me.topchetoeu.jscript.core.exceptions.ConvertException; import me.topchetoeu.jscript.core.exceptions.EngineException; @@ -664,7 +664,7 @@ public class Values { if (val instanceof FunctionValue) { res.append(val.toString()); - var loc = val instanceof CodeFunction ? dbg.getMap((CodeFunction)val).start() : null; + var loc = val instanceof CodeFunction ? dbg.getMapOrEmpty((CodeFunction)val).start() : null; if (loc != null) res.append(" @ " + loc); } @@ -734,10 +734,10 @@ public class Values { if (err instanceof EngineException) { var ee = ((EngineException)err); try { - return prefix + " " + ee.toString(new Context(ee.engine, ee.env)); + return prefix + " " + ee.toString(new Context(ee.env)); } catch (EngineException ex) { - return prefix + " " + toReadable(new Context(ee.engine, ee.env), ee.value); + return prefix + " " + toReadable(new Context(ee.env), ee.value); } } else if (err instanceof SyntaxException) { diff --git a/src/java/me/topchetoeu/jscript/lib/AsyncFunctionLib.java b/src/java/me/topchetoeu/jscript/lib/AsyncFunctionLib.java index 73be8e4..05a3d3f 100644 --- a/src/java/me/topchetoeu/jscript/lib/AsyncFunctionLib.java +++ b/src/java/me/topchetoeu/jscript/lib/AsyncFunctionLib.java @@ -13,7 +13,7 @@ import me.topchetoeu.jscript.utils.interop.WrapperName; @WrapperName("AsyncFunction") public class AsyncFunctionLib extends FunctionValue { - public final FunctionValue factory; + public final CodeFunction func; private static class AsyncHelper { public PromiseLib promise = new PromiseLib(); @@ -67,15 +67,19 @@ public class AsyncFunctionLib extends FunctionValue { @Override public Object call(Context ctx, Object thisArg, Object ...args) { var handler = new AsyncHelper(); - var func = factory.call(ctx, thisArg, new NativeFunction("await", handler::await)); - if (!(func instanceof CodeFunction)) throw EngineException.ofType("Return value of argument must be a js function."); - handler.frame = new Frame(ctx, thisArg, args, (CodeFunction)func); + + var newArgs = new Object[args.length + 1]; + newArgs[0] = new NativeFunction("await", handler::await); + System.arraycopy(args, 0, newArgs, 1, args.length); + + handler.frame = new Frame(ctx, thisArg, newArgs, (CodeFunction)func); handler.next(ctx, Values.NO_RETURN, null); return handler.promise; } - public AsyncFunctionLib(FunctionValue factory) { - super(factory.name, factory.length); - this.factory = factory; + public AsyncFunctionLib(FunctionValue func) { + super(func.name, func.length); + if (!(func instanceof CodeFunction)) throw EngineException.ofType("Return value of argument must be a js function."); + this.func = (CodeFunction)func; } } diff --git a/src/java/me/topchetoeu/jscript/lib/AsyncGeneratorFunctionLib.java b/src/java/me/topchetoeu/jscript/lib/AsyncGeneratorFunctionLib.java index 7e2ce55..6102b79 100644 --- a/src/java/me/topchetoeu/jscript/lib/AsyncGeneratorFunctionLib.java +++ b/src/java/me/topchetoeu/jscript/lib/AsyncGeneratorFunctionLib.java @@ -10,22 +10,24 @@ import me.topchetoeu.jscript.utils.interop.WrapperName; @WrapperName("AsyncGeneratorFunction") public class AsyncGeneratorFunctionLib extends FunctionValue { - public final FunctionValue factory; + public final CodeFunction func; @Override public Object call(Context ctx, Object thisArg, Object ...args) { var handler = new AsyncGeneratorLib(); - var func = factory.call(ctx, thisArg, - new NativeFunction("await", handler::await), - new NativeFunction("yield", handler::yield) - ); - if (!(func instanceof CodeFunction)) throw EngineException.ofType("Return value of argument must be a js function."); - handler.frame = new Frame(ctx, thisArg, args, (CodeFunction)func); + + var newArgs = new Object[args.length + 2]; + newArgs[0] = new NativeFunction("await", handler::await); + newArgs[1] = new NativeFunction("yield", handler::yield); + System.arraycopy(args, 0, newArgs, 2, args.length); + + handler.frame = new Frame(ctx, thisArg, newArgs, func); return handler; } - public AsyncGeneratorFunctionLib(FunctionValue factory) { - super(factory.name, factory.length); - this.factory = factory; + public AsyncGeneratorFunctionLib(CodeFunction func) { + super(func.name, func.length); + if (!(func instanceof CodeFunction)) throw EngineException.ofType("Return value of argument must be a js function."); + this.func = func; } } diff --git a/src/java/me/topchetoeu/jscript/lib/EnvironmentLib.java b/src/java/me/topchetoeu/jscript/lib/EnvironmentLib.java deleted file mode 100644 index 5d69727..0000000 --- a/src/java/me/topchetoeu/jscript/lib/EnvironmentLib.java +++ /dev/null @@ -1,39 +0,0 @@ -package me.topchetoeu.jscript.lib; - -import me.topchetoeu.jscript.core.Environment; -import me.topchetoeu.jscript.core.values.FunctionValue; -import me.topchetoeu.jscript.core.values.ObjectValue; -import me.topchetoeu.jscript.utils.interop.Arguments; -import me.topchetoeu.jscript.utils.interop.Expose; -import me.topchetoeu.jscript.utils.interop.ExposeType; -import me.topchetoeu.jscript.utils.interop.WrapperName; - -@WrapperName("Environment") -public class EnvironmentLib { - private Environment env; - - @Expose(value = "@@env", type = ExposeType.GETTER) - public Environment __env() { return env; } - - @Expose(type = ExposeType.GETTER) - public int __id(Arguments args) { - return env.hashCode(); - } - @Expose(type = ExposeType.GETTER) - public ObjectValue __global(Arguments args) { - return env.global.obj; - } - - @Expose(type = ExposeType.GETTER) - public FunctionValue __compile() { - return Environment.compileFunc(env); - } - @Expose(type = ExposeType.SETTER) - public void __compile(Arguments args) { - env.add(Environment.COMPILE_FUNC, args.convert(0, FunctionValue.class)); - } - - public EnvironmentLib(Environment env) { - this.env = env; - } -} diff --git a/src/java/me/topchetoeu/jscript/lib/FunctionLib.java b/src/java/me/topchetoeu/jscript/lib/FunctionLib.java index 99b07ba..3d16d5e 100644 --- a/src/java/me/topchetoeu/jscript/lib/FunctionLib.java +++ b/src/java/me/topchetoeu/jscript/lib/FunctionLib.java @@ -1,6 +1,7 @@ package me.topchetoeu.jscript.lib; import me.topchetoeu.jscript.core.values.ArrayValue; +import me.topchetoeu.jscript.core.values.CodeFunction; import me.topchetoeu.jscript.core.values.FunctionValue; import me.topchetoeu.jscript.core.values.NativeFunction; import me.topchetoeu.jscript.utils.interop.Arguments; @@ -44,10 +45,10 @@ public class FunctionLib { } @Expose(target = ExposeTarget.STATIC) public static FunctionValue __asyncGenerator(Arguments args) { - return new AsyncGeneratorFunctionLib(args.convert(0, FunctionValue.class)); + return new AsyncGeneratorFunctionLib(args.convert(0, CodeFunction.class)); } @Expose(target = ExposeTarget.STATIC) public static FunctionValue __generator(Arguments args) { - return new GeneratorFunctionLib(args.convert(0, FunctionValue.class)); + return new GeneratorFunctionLib(args.convert(0, CodeFunction.class)); } } diff --git a/src/java/me/topchetoeu/jscript/lib/GeneratorFunctionLib.java b/src/java/me/topchetoeu/jscript/lib/GeneratorFunctionLib.java index 2622677..36cdc65 100644 --- a/src/java/me/topchetoeu/jscript/lib/GeneratorFunctionLib.java +++ b/src/java/me/topchetoeu/jscript/lib/GeneratorFunctionLib.java @@ -10,18 +10,22 @@ import me.topchetoeu.jscript.utils.interop.WrapperName; @WrapperName("GeneratorFunction") public class GeneratorFunctionLib extends FunctionValue { - public final FunctionValue factory; + public final CodeFunction func; @Override public Object call(Context ctx, Object thisArg, Object ...args) { var handler = new GeneratorLib(); - var func = factory.call(ctx, thisArg, new NativeFunction("yield", handler::yield)); - if (!(func instanceof CodeFunction)) throw EngineException.ofType("Return value of argument must be a js function."); - handler.frame = new Frame(ctx, thisArg, args, (CodeFunction)func); + + var newArgs = new Object[args.length + 1]; + newArgs[0] = new NativeFunction("yield", handler::yield); + System.arraycopy(args, 0, newArgs, 1, args.length); + + handler.frame = new Frame(ctx, thisArg, newArgs, func); return handler; } - public GeneratorFunctionLib(FunctionValue factory) { - super(factory.name, factory.length); - this.factory = factory; + public GeneratorFunctionLib(CodeFunction func) { + super(func.name, func.length); + if (!(func instanceof CodeFunction)) throw EngineException.ofType("Return value of argument must be a js function."); + this.func = func; } } diff --git a/src/java/me/topchetoeu/jscript/lib/Internals.java b/src/java/me/topchetoeu/jscript/lib/Internals.java index 7d19ac7..476cbc6 100644 --- a/src/java/me/topchetoeu/jscript/lib/Internals.java +++ b/src/java/me/topchetoeu/jscript/lib/Internals.java @@ -4,9 +4,10 @@ import java.util.HashMap; import me.topchetoeu.jscript.core.Context; import me.topchetoeu.jscript.core.Environment; +import me.topchetoeu.jscript.core.EventLoop; +import me.topchetoeu.jscript.core.Key; import me.topchetoeu.jscript.core.scope.GlobalScope; import me.topchetoeu.jscript.core.values.FunctionValue; -import me.topchetoeu.jscript.core.values.Symbol; import me.topchetoeu.jscript.core.values.Values; import me.topchetoeu.jscript.core.exceptions.EngineException; import me.topchetoeu.jscript.utils.interop.Arguments; @@ -16,8 +17,8 @@ import me.topchetoeu.jscript.utils.interop.ExposeTarget; import me.topchetoeu.jscript.utils.modules.ModuleRepo; public class Internals { - private static final Symbol THREADS = new Symbol("Internals.threads"); - private static final Symbol I = new Symbol("Internals.i"); + private static final Key> THREADS = new Key<>(); + private static final Key I = new Key<>(); @Expose(target = ExposeTarget.STATIC) public static Object __require(Arguments args) { @@ -38,6 +39,8 @@ public class Internals { var delay = args.getDouble(1); var arguments = args.slice(2).args; + if (!args.ctx.hasNotNull(EventLoop.KEY)) throw EngineException.ofError("No event loop"); + var thread = new Thread(() -> { var ms = (long)delay; var ns = (int)((delay - ms) * 10000000); @@ -45,7 +48,7 @@ public class Internals { try { Thread.sleep(ms, ns); } catch (InterruptedException e) { return; } - args.ctx.engine.pushMsg(false, args.ctx.environment, func, null, arguments); + args.ctx.get(EventLoop.KEY).pushMsg(() -> func.call(new Context(args.ctx.environment), null, arguments), false); }); thread.start(); @@ -61,6 +64,8 @@ public class Internals { var delay = args.getDouble(1); var arguments = args.slice(2).args; + if (!args.ctx.hasNotNull(EventLoop.KEY)) throw EngineException.ofError("No event loop"); + var thread = new Thread(() -> { var ms = (long)delay; var ns = (int)((delay - ms) * 10000000); @@ -71,7 +76,7 @@ public class Internals { } catch (InterruptedException e) { return; } - args.ctx.engine.pushMsg(false, args.ctx.environment, func, null, arguments); + args.ctx.get(EventLoop.KEY).pushMsg(() -> func.call(new Context(args.ctx.environment), null, arguments), false); } }); thread.start(); diff --git a/src/java/me/topchetoeu/jscript/lib/PromiseLib.java b/src/java/me/topchetoeu/jscript/lib/PromiseLib.java index 1022f4d..5d75368 100644 --- a/src/java/me/topchetoeu/jscript/lib/PromiseLib.java +++ b/src/java/me/topchetoeu/jscript/lib/PromiseLib.java @@ -6,12 +6,14 @@ import java.util.List; import me.topchetoeu.jscript.common.ResultRunnable; import me.topchetoeu.jscript.core.Context; import me.topchetoeu.jscript.core.EventLoop; +import me.topchetoeu.jscript.core.Extensions; import me.topchetoeu.jscript.core.values.ArrayValue; import me.topchetoeu.jscript.core.values.FunctionValue; import me.topchetoeu.jscript.core.values.NativeFunction; import me.topchetoeu.jscript.core.values.ObjectValue; import me.topchetoeu.jscript.core.values.Values; import me.topchetoeu.jscript.core.exceptions.EngineException; +import me.topchetoeu.jscript.core.exceptions.InterruptException; import me.topchetoeu.jscript.utils.interop.Arguments; import me.topchetoeu.jscript.utils.interop.Expose; import me.topchetoeu.jscript.utils.interop.ExposeConstructor; @@ -24,14 +26,17 @@ public class PromiseLib { void onFulfil(Object val); void onReject(EngineException err); - default Handle defer(EventLoop loop) { + default Handle defer(Extensions loop) { var self = this; + return new Handle() { @Override public void onFulfil(Object val) { - loop.pushMsg(() -> self.onFulfil(val), true); + if (!loop.hasNotNull(EventLoop.KEY)) throw EngineException.ofError("No event loop"); + loop.get(EventLoop.KEY).pushMsg(() -> self.onFulfil(val), true); } @Override public void onReject(EngineException val) { - loop.pushMsg(() -> self.onReject(val), true); + if (!loop.hasNotNull(EventLoop.KEY)) throw EngineException.ofError("No event loop"); + loop.get(EventLoop.KEY).pushMsg(() -> self.onReject(val), true); } }; } @@ -48,7 +53,9 @@ public class PromiseLib { private Object val; private void resolveSynchronized(Context ctx, Object val, int newState) { - ctx.engine.pushMsg(() -> { + if (!ctx.hasNotNull(EventLoop.KEY)) throw EngineException.ofError("No event loop"); + + ctx.get(EventLoop.KEY).pushMsg(() -> { this.val = val; this.state = newState; @@ -118,6 +125,12 @@ public class PromiseLib { catch (EngineException e) { res.reject(ctx, e); } + catch (Exception e) { + if (e instanceof InterruptException) throw e; + else { + res.reject(ctx, EngineException.ofError("Native code failed with " + e.getMessage())); + } + } }, "Promisifier").start(); return res; @@ -144,7 +157,8 @@ public class PromiseLib { try { var then = Values.getMember(ctx, obj, "then"); - Values.call(ctx, then, obj, + + if (then instanceof FunctionValue) Values.call(ctx, then, obj, new NativeFunction(args -> { try { handle.onFulfil(args.get(0)); } catch (Exception e) { @@ -162,6 +176,7 @@ public class PromiseLib { return null; }) ); + else handle.onFulfil(obj); return; } @@ -325,7 +340,7 @@ public class PromiseLib { try { res.fulfill(args.ctx, onReject.call(args.ctx, null, err.value)); } catch (EngineException e) { res.reject(args.ctx, e); } } - }.defer(args.ctx.engine)); + }.defer(args.ctx)); return res; } @@ -354,7 +369,7 @@ public class PromiseLib { } catch (EngineException e) { res.reject(args.ctx, e); } } - }.defer(args.ctx.engine)); + }.defer(args.ctx)); return res; } diff --git a/src/java/me/topchetoeu/jscript/utils/JSCompiler.java b/src/java/me/topchetoeu/jscript/utils/JSCompiler.java new file mode 100644 index 0000000..f538ddb --- /dev/null +++ b/src/java/me/topchetoeu/jscript/utils/JSCompiler.java @@ -0,0 +1,34 @@ +package me.topchetoeu.jscript.utils; + +import me.topchetoeu.jscript.common.Filename; +import me.topchetoeu.jscript.common.FunctionBody; +import me.topchetoeu.jscript.compilation.CompileResult; +import me.topchetoeu.jscript.compilation.parsing.Parsing; +import me.topchetoeu.jscript.core.Compiler; +import me.topchetoeu.jscript.core.Extensions; +import me.topchetoeu.jscript.core.debug.DebugContext; + +public class JSCompiler implements Compiler { + public final Extensions ext; + + private void registerFunc(FunctionBody body, CompileResult res) { + var map = res.map(); + DebugContext.get(ext).onFunctionLoad(body, map); + + for (var i = 0; i < body.children.length; i++) { + registerFunc(body.children[i], res.children.get(i)); + } + } + + @Override public FunctionBody compile(Filename filename, String source) { + var res = Parsing.compile(filename, source); + var func = res.body(); + registerFunc(func, res); + + return func; + } + + public JSCompiler(Extensions ext) { + this.ext = ext; + } +} diff --git a/src/java/me/topchetoeu/jscript/utils/JScriptRepl.java b/src/java/me/topchetoeu/jscript/utils/JScriptRepl.java index 2394249..3a280fa 100644 --- a/src/java/me/topchetoeu/jscript/utils/JScriptRepl.java +++ b/src/java/me/topchetoeu/jscript/utils/JScriptRepl.java @@ -8,8 +8,11 @@ import java.nio.file.Path; import me.topchetoeu.jscript.common.Filename; import me.topchetoeu.jscript.common.Metadata; import me.topchetoeu.jscript.common.Reading; +import me.topchetoeu.jscript.core.Compiler; +import me.topchetoeu.jscript.core.Context; import me.topchetoeu.jscript.core.Engine; import me.topchetoeu.jscript.core.Environment; +import me.topchetoeu.jscript.core.EventLoop; import me.topchetoeu.jscript.core.debug.DebugContext; import me.topchetoeu.jscript.core.values.NativeFunction; import me.topchetoeu.jscript.core.values.Values; @@ -36,7 +39,6 @@ public class JScriptRepl { static Environment environment = new Environment(); static int j = 0; - static boolean exited = false; static String[] args; private static void reader() { @@ -74,25 +76,21 @@ public class JScriptRepl { } catch (IOException e) { System.out.println(e.toString()); - exited = true; + engine.thread().interrupt(); } catch (RuntimeException ex) { - if (!exited) { + if (ex instanceof InterruptException) return; + else { System.out.println("Internal error ocurred:"); ex.printStackTrace(); } } - if (exited) { - debugTask.interrupt(); - engineTask.interrupt(); - } } private static void initEnv() { environment = Internals.apply(environment); environment.global.define(false, new NativeFunction("exit", args -> { - exited = true; throw new InterruptException(); })); environment.global.define(false, new NativeFunction("go", args -> { @@ -105,26 +103,35 @@ public class JScriptRepl { throw new EngineException("Couldn't open do.js"); } })); + environment.global.define(false, new NativeFunction("log", args -> { + for (var el : args.args) { + Values.printValue(args.ctx, el); + } + + return null; + })); var fs = new RootFilesystem(PermissionsProvider.get(environment)); fs.protocols.put("temp", new MemoryFilesystem(Mode.READ_WRITE)); fs.protocols.put("file", new PhysicalFilesystem(".")); fs.protocols.put("std", STDFilesystem.ofStd(System.in, System.out, System.err)); - environment.add(PermissionsProvider.ENV_KEY, PermissionsManager.ALL_PERMS); - environment.add(Filesystem.ENV_KEY, fs); - environment.add(ModuleRepo.ENV_KEY, ModuleRepo.ofFilesystem(fs)); + environment.add(PermissionsProvider.KEY, PermissionsManager.ALL_PERMS); + environment.add(Filesystem.KEY, fs); + environment.add(ModuleRepo.KEY, ModuleRepo.ofFilesystem(fs)); + environment.add(Compiler.KEY, new JSCompiler(new Context(environment))); + environment.add(EventLoop.KEY, engine); } private static void initEngine() { - // var ctx = new DebugContext(); - // engine.add(DebugContext.ENV_KEY, ctx); + var ctx = new DebugContext(); + environment.add(DebugContext.KEY, ctx); // debugServer.targets.put("target", (ws, req) -> new SimpleDebugger(ws).attach(ctx)); engineTask = engine.start(); - // debugTask = debugServer.start(new InetSocketAddress("127.0.0.1", 9229), true); + debugTask = debugServer.start(new InetSocketAddress("127.0.0.1", 9229), true); } - public static void main(String args[]) { + public static void main(String args[]) throws InterruptedException { System.out.println(String.format("Running %s v%s by %s", Metadata.name(), Metadata.version(), Metadata.author())); JScriptRepl.args = args; @@ -136,5 +143,9 @@ public class JScriptRepl { reader.setDaemon(true); reader.setName("STD Reader"); reader.start(); + + engine.thread().join(); + debugTask.interrupt(); + engineTask.interrupt(); } } diff --git a/src/java/me/topchetoeu/jscript/utils/debug/DebugHandler.java b/src/java/me/topchetoeu/jscript/utils/debug/DebugHandler.java deleted file mode 100644 index 9615f62..0000000 --- a/src/java/me/topchetoeu/jscript/utils/debug/DebugHandler.java +++ /dev/null @@ -1,33 +0,0 @@ -package me.topchetoeu.jscript.utils.debug; - -import java.io.IOException; - -public interface DebugHandler { - void enable(V8Message msg) throws IOException; - void disable(V8Message msg) throws IOException; - - void setBreakpointByUrl(V8Message msg) throws IOException; - void removeBreakpoint(V8Message msg) throws IOException; - void continueToLocation(V8Message msg) throws IOException; - - void getScriptSource(V8Message msg) throws IOException; - void getPossibleBreakpoints(V8Message msg) throws IOException; - - void resume(V8Message msg) throws IOException; - void pause(V8Message msg) throws IOException; - - void stepInto(V8Message msg) throws IOException; - void stepOut(V8Message msg) throws IOException; - void stepOver(V8Message msg) throws IOException; - - void setPauseOnExceptions(V8Message msg) throws IOException; - - void evaluateOnCallFrame(V8Message msg) throws IOException; - - void getProperties(V8Message msg) throws IOException; - void releaseObjectGroup(V8Message msg) throws IOException; - void releaseObject(V8Message msg) throws IOException; - void callFunctionOn(V8Message msg) throws IOException; - - void runtimeEnable(V8Message msg) throws IOException; -} diff --git a/src/java/me/topchetoeu/jscript/utils/debug/Debugger.java b/src/java/me/topchetoeu/jscript/utils/debug/Debugger.java index 93dc922..202014b 100644 --- a/src/java/me/topchetoeu/jscript/utils/debug/Debugger.java +++ b/src/java/me/topchetoeu/jscript/utils/debug/Debugger.java @@ -1,7 +1,36 @@ package me.topchetoeu.jscript.utils.debug; -import me.topchetoeu.jscript.core.debug.DebugController; +import me.topchetoeu.jscript.core.debug.DebugHandler; +import java.io.IOException; -public interface Debugger extends DebugHandler, DebugController { +public interface Debugger extends DebugHandler { void close(); + + void enable(V8Message msg) throws IOException; + void disable(V8Message msg) throws IOException; + + void setBreakpointByUrl(V8Message msg) throws IOException; + void removeBreakpoint(V8Message msg) throws IOException; + void continueToLocation(V8Message msg) throws IOException; + + void getScriptSource(V8Message msg) throws IOException; + void getPossibleBreakpoints(V8Message msg) throws IOException; + + void resume(V8Message msg) throws IOException; + void pause(V8Message msg) throws IOException; + + void stepInto(V8Message msg) throws IOException; + void stepOut(V8Message msg) throws IOException; + void stepOver(V8Message msg) throws IOException; + + void setPauseOnExceptions(V8Message msg) throws IOException; + + void evaluateOnCallFrame(V8Message msg) throws IOException; + + void getProperties(V8Message msg) throws IOException; + void releaseObjectGroup(V8Message msg) throws IOException; + void releaseObject(V8Message msg) throws IOException; + void callFunctionOn(V8Message msg) throws IOException; + + void runtimeEnable(V8Message msg) throws IOException; } diff --git a/src/java/me/topchetoeu/jscript/utils/filesystem/File.java b/src/java/me/topchetoeu/jscript/utils/filesystem/File.java index 3017fc0..c1b89c6 100644 --- a/src/java/me/topchetoeu/jscript/utils/filesystem/File.java +++ b/src/java/me/topchetoeu/jscript/utils/filesystem/File.java @@ -15,24 +15,31 @@ public interface File { default byte[] readAll() { var parts = new LinkedList(); + var sizes = new LinkedList(); var buff = new byte[1024]; var size = 0; while (true) { var n = read(buff); - if (n == 0) break; + if (n < 0) break; + else if (n == 0) continue; parts.add(buff); + sizes.add(n); size += n; + buff = new byte[1024]; } buff = new byte[size]; var i = 0; + var j = 0; for (var part : parts) { - System.arraycopy(part, 0, buff, i, part.length); - i += part.length; + var currSize = sizes.get(j++); + + System.arraycopy(part, 0, buff, i, currSize); + i += currSize; } return buff; diff --git a/src/java/me/topchetoeu/jscript/utils/filesystem/Filesystem.java b/src/java/me/topchetoeu/jscript/utils/filesystem/Filesystem.java index 8035898..ab68a33 100644 --- a/src/java/me/topchetoeu/jscript/utils/filesystem/Filesystem.java +++ b/src/java/me/topchetoeu/jscript/utils/filesystem/Filesystem.java @@ -1,10 +1,10 @@ package me.topchetoeu.jscript.utils.filesystem; import me.topchetoeu.jscript.core.Extensions; -import me.topchetoeu.jscript.core.values.Symbol; +import me.topchetoeu.jscript.core.Key; public interface Filesystem { - public static final Symbol ENV_KEY = Symbol.get("Environment.fs"); + public static final Key KEY = new Key<>(); default String normalize(String... path) { return Paths.normalize(path); } default boolean create(String path, EntryType type) { throw new FilesystemException(ErrorReason.UNSUPPORTED).setAction(ActionType.CREATE); } @@ -13,6 +13,6 @@ public interface Filesystem { void close(); public static Filesystem get(Extensions exts) { - return exts.get(ENV_KEY); + return exts.get(KEY); } } \ No newline at end of file diff --git a/src/java/me/topchetoeu/jscript/utils/filesystem/MemoryFile.java b/src/java/me/topchetoeu/jscript/utils/filesystem/MemoryFile.java index 5dd88be..cb89d1d 100644 --- a/src/java/me/topchetoeu/jscript/utils/filesystem/MemoryFile.java +++ b/src/java/me/topchetoeu/jscript/utils/filesystem/MemoryFile.java @@ -6,6 +6,7 @@ class MemoryFile extends BaseFile { private int ptr; @Override protected int onRead(byte[] buff) { + if (ptr >= handle().length()) return -1; var res = handle().read(ptr, buff); ptr += res; return res; diff --git a/src/java/me/topchetoeu/jscript/utils/interop/NativeWrapperProvider.java b/src/java/me/topchetoeu/jscript/utils/interop/NativeWrapperProvider.java index fdee1a4..f4567fc 100644 --- a/src/java/me/topchetoeu/jscript/utils/interop/NativeWrapperProvider.java +++ b/src/java/me/topchetoeu/jscript/utils/interop/NativeWrapperProvider.java @@ -39,7 +39,7 @@ public class NativeWrapperProvider implements WrapperProvider { throw ((EngineException)e.getTargetException()).add(ctx, name, Location.INTERNAL); } else if (e.getTargetException() instanceof NullPointerException) { - e.printStackTrace(); + // e.getTargetException().printStackTrace(); throw EngineException.ofType("Unexpected value of 'undefined'.").add(ctx, name, Location.INTERNAL); } else if (e.getTargetException() instanceof InterruptException || e.getTargetException() instanceof InterruptedException) { @@ -172,7 +172,7 @@ public class NativeWrapperProvider implements WrapperProvider { if (props.contains(key) || nonProps.contains(key)) repeat = true; else { checkSignature(method, true, Environment.class); - obj.defineProperty(null, key, call(new Context(null, env), name, method, null, env), true, true, false); + obj.defineProperty(null, key, call(new Context(env), name, method, null, env), true, true, false); nonProps.add(key); } @@ -195,7 +195,7 @@ public class NativeWrapperProvider implements WrapperProvider { if (props.contains(key) || nonProps.contains(key)) repeat = true; else { try { - obj.defineProperty(null, key, Values.normalize(new Context(null, env), field.get(null)), true, true, false); + obj.defineProperty(null, key, Values.normalize(new Context(env), field.get(null)), true, true, false); nonProps.add(key); } catch (IllegalArgumentException | IllegalAccessException e) { } diff --git a/src/java/me/topchetoeu/jscript/compilation/mapping/SourceMap.java b/src/java/me/topchetoeu/jscript/utils/mapping/SourceMap.java similarity index 97% rename from src/java/me/topchetoeu/jscript/compilation/mapping/SourceMap.java rename to src/java/me/topchetoeu/jscript/utils/mapping/SourceMap.java index 6a8ad05..a7523b3 100644 --- a/src/java/me/topchetoeu/jscript/compilation/mapping/SourceMap.java +++ b/src/java/me/topchetoeu/jscript/utils/mapping/SourceMap.java @@ -1,4 +1,4 @@ -package me.topchetoeu.jscript.compilation.mapping; +package me.topchetoeu.jscript.utils.mapping; import java.util.ArrayList; import java.util.List; @@ -6,7 +6,6 @@ import java.util.TreeMap; import java.util.stream.Collectors; import me.topchetoeu.jscript.common.Location; -import me.topchetoeu.jscript.common.VLQ; import me.topchetoeu.jscript.common.json.JSON; public class SourceMap { diff --git a/src/java/me/topchetoeu/jscript/common/VLQ.java b/src/java/me/topchetoeu/jscript/utils/mapping/VLQ.java similarity index 98% rename from src/java/me/topchetoeu/jscript/common/VLQ.java rename to src/java/me/topchetoeu/jscript/utils/mapping/VLQ.java index 249d8fd..5f49aea 100644 --- a/src/java/me/topchetoeu/jscript/common/VLQ.java +++ b/src/java/me/topchetoeu/jscript/utils/mapping/VLQ.java @@ -1,4 +1,4 @@ -package me.topchetoeu.jscript.common; +package me.topchetoeu.jscript.utils.mapping; import java.util.ArrayList; import java.util.List; diff --git a/src/java/me/topchetoeu/jscript/utils/modules/ModuleRepo.java b/src/java/me/topchetoeu/jscript/utils/modules/ModuleRepo.java index 2941bf3..9cdc899 100644 --- a/src/java/me/topchetoeu/jscript/utils/modules/ModuleRepo.java +++ b/src/java/me/topchetoeu/jscript/utils/modules/ModuleRepo.java @@ -5,13 +5,13 @@ import java.util.HashMap; import me.topchetoeu.jscript.common.Filename; import me.topchetoeu.jscript.core.Context; import me.topchetoeu.jscript.core.Extensions; -import me.topchetoeu.jscript.core.values.Symbol; +import me.topchetoeu.jscript.core.Key; import me.topchetoeu.jscript.utils.filesystem.Filesystem; import me.topchetoeu.jscript.utils.filesystem.Mode; public interface ModuleRepo { - public static final Symbol ENV_KEY = Symbol.get("Environment.modules"); - public static final Symbol CWD = Symbol.get("Environment.moduleCwd"); + public static final Key KEY = new Key<>(); + public static final Key CWD = new Key<>(); public Module getModule(Context ctx, String cwd, String name); @@ -39,6 +39,6 @@ public interface ModuleRepo { return exts.init(CWD, "/"); } public static ModuleRepo get(Extensions exts) { - return exts.get(ENV_KEY); + return exts.get(KEY); } } diff --git a/src/java/me/topchetoeu/jscript/utils/modules/SourceModule.java b/src/java/me/topchetoeu/jscript/utils/modules/SourceModule.java index 1cab1b0..ddcac1d 100644 --- a/src/java/me/topchetoeu/jscript/utils/modules/SourceModule.java +++ b/src/java/me/topchetoeu/jscript/utils/modules/SourceModule.java @@ -11,7 +11,7 @@ public class SourceModule extends Module { @Override protected Object onLoad(Context ctx) { - var res = new Context(ctx.engine, env).compile(filename, source); + var res = new Context(env).compile(filename, source); return res.call(ctx); } diff --git a/src/java/me/topchetoeu/jscript/utils/permissions/PermissionsProvider.java b/src/java/me/topchetoeu/jscript/utils/permissions/PermissionsProvider.java index f2b51e9..78489ac 100644 --- a/src/java/me/topchetoeu/jscript/utils/permissions/PermissionsProvider.java +++ b/src/java/me/topchetoeu/jscript/utils/permissions/PermissionsProvider.java @@ -1,10 +1,10 @@ package me.topchetoeu.jscript.utils.permissions; import me.topchetoeu.jscript.core.Extensions; -import me.topchetoeu.jscript.core.values.Symbol; +import me.topchetoeu.jscript.core.Key; public interface PermissionsProvider { - public static final Symbol ENV_KEY = new Symbol("Environment.perms"); + public static final Key KEY = new Key<>(); public static final PermissionsProvider ALL_PERMS = (perm, value) -> true; boolean hasPermission(Permission perm, String value); @@ -22,7 +22,7 @@ public interface PermissionsProvider { public static PermissionsProvider get(Extensions exts) { return (perm, value) -> { - if (exts.hasNotNull(ENV_KEY)) return ((PermissionsProvider)exts.get(ENV_KEY)).hasPermission(perm); + if (exts.hasNotNull(KEY)) return exts.get(KEY).hasPermission(perm); else return true; }; }