diff --git a/src/java/me/topchetoeu/jscript/core/engine/scope/ScopeRecord.java b/src/java/me/topchetoeu/jscript/common/ScopeRecord.java similarity index 60% rename from src/java/me/topchetoeu/jscript/core/engine/scope/ScopeRecord.java rename to src/java/me/topchetoeu/jscript/common/ScopeRecord.java index ec14c33..e2cfcfc 100644 --- a/src/java/me/topchetoeu/jscript/core/engine/scope/ScopeRecord.java +++ b/src/java/me/topchetoeu/jscript/common/ScopeRecord.java @@ -1,4 +1,6 @@ -package me.topchetoeu.jscript.core.engine.scope; +package me.topchetoeu.jscript.common; + +import me.topchetoeu.jscript.core.scope.LocalScopeRecord; public interface ScopeRecord { public Object getKey(String name); diff --git a/src/java/me/topchetoeu/jscript/common/events/Awaitable.java b/src/java/me/topchetoeu/jscript/common/events/Awaitable.java deleted file mode 100644 index fa2ea05..0000000 --- a/src/java/me/topchetoeu/jscript/common/events/Awaitable.java +++ /dev/null @@ -1,27 +0,0 @@ -package me.topchetoeu.jscript.common.events; - -public interface Awaitable { - public static interface ResultHandler { - public void onResult(T data); - } - public static interface ErrorHandler { - public void onError(RuntimeException error); - } - - T await(); - - default void handle(ResultHandler onResult, ErrorHandler onError) { - var thread = new Thread(() -> { - try { - onResult.onResult(await()); - } - catch (RuntimeException e) { - onError.onError(e); - } - }, "Awaiter"); - thread.start(); - } - default void handle(ResultHandler onResult) { - handle(onResult, err -> {}); - } -} diff --git a/src/java/me/topchetoeu/jscript/common/events/DataNotifier.java b/src/java/me/topchetoeu/jscript/common/events/DataNotifier.java index 306caf2..b498b85 100644 --- a/src/java/me/topchetoeu/jscript/common/events/DataNotifier.java +++ b/src/java/me/topchetoeu/jscript/common/events/DataNotifier.java @@ -1,6 +1,6 @@ package me.topchetoeu.jscript.common.events; -public class DataNotifier implements Awaitable { +public class DataNotifier { private Notifier notifier = new Notifier(); private boolean isErr; private T val; diff --git a/src/java/me/topchetoeu/jscript/common/json/JSON.java b/src/java/me/topchetoeu/jscript/common/json/JSON.java index 5b6b083..e4078a1 100644 --- a/src/java/me/topchetoeu/jscript/common/json/JSON.java +++ b/src/java/me/topchetoeu/jscript/common/json/JSON.java @@ -5,16 +5,16 @@ import java.util.List; import java.util.stream.Collectors; import me.topchetoeu.jscript.common.Filename; -import me.topchetoeu.jscript.core.engine.Context; -import me.topchetoeu.jscript.core.engine.values.ArrayValue; -import me.topchetoeu.jscript.core.engine.values.ObjectValue; -import me.topchetoeu.jscript.core.engine.values.Values; +import me.topchetoeu.jscript.compilation.parsing.Operator; +import me.topchetoeu.jscript.compilation.parsing.ParseRes; +import me.topchetoeu.jscript.compilation.parsing.Parsing; +import me.topchetoeu.jscript.compilation.parsing.Token; +import me.topchetoeu.jscript.core.Context; +import me.topchetoeu.jscript.core.values.ArrayValue; +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.SyntaxException; -import me.topchetoeu.jscript.core.parsing.Operator; -import me.topchetoeu.jscript.core.parsing.ParseRes; -import me.topchetoeu.jscript.core.parsing.Parsing; -import me.topchetoeu.jscript.core.parsing.Token; public class JSON { public static Object toJs(JSONElement val) { diff --git a/src/java/me/topchetoeu/jscript/core/compilation/AssignableStatement.java b/src/java/me/topchetoeu/jscript/compilation/AssignableStatement.java similarity index 70% rename from src/java/me/topchetoeu/jscript/core/compilation/AssignableStatement.java rename to src/java/me/topchetoeu/jscript/compilation/AssignableStatement.java index 8e8c7c3..48284b4 100644 --- a/src/java/me/topchetoeu/jscript/core/compilation/AssignableStatement.java +++ b/src/java/me/topchetoeu/jscript/compilation/AssignableStatement.java @@ -1,7 +1,7 @@ -package me.topchetoeu.jscript.core.compilation; +package me.topchetoeu.jscript.compilation; import me.topchetoeu.jscript.common.Location; -import me.topchetoeu.jscript.core.engine.Operation; +import me.topchetoeu.jscript.core.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 new file mode 100644 index 0000000..d9852df --- /dev/null +++ b/src/java/me/topchetoeu/jscript/compilation/CompileResult.java @@ -0,0 +1,77 @@ +package me.topchetoeu.jscript.compilation; + +import java.util.List; +import java.util.LinkedList; +import java.util.Vector; + +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.core.scope.LocalScopeRecord; + +public class CompileResult { + public final Vector instructions = new Vector<>(); + public final List children = new LinkedList<>(); + public final FunctionMapBuilder map = FunctionMap.builder(); + public final LocalScopeRecord scope; + public int length = 0; + + public int temp() { + instructions.add(null); + return instructions.size() - 1; + } + + public CompileResult add(Instruction instr) { + instructions.add(instr); + return this; + } + public CompileResult set(int i, Instruction instr) { + instructions.set(i, instr); + return this; + } + public Instruction get(int i) { + return instructions.get(i); + } + public int size() { return instructions.size(); } + + public void setDebug(Location loc, BreakpointType type) { + map.setDebug(loc, type); + } + public void setLocation(int i, Location loc) { + map.setLocation(i, loc); + } + public void setLocationAndDebug(int i, Location loc, BreakpointType type) { + map.setLocationAndDebug(i, loc, type); + } + public void setDebug(BreakpointType type) { + setDebug(map.last(), type); + } + public void setLocation(Location type) { + setLocation(instructions.size() - 1, type); + } + public void setLocationAndDebug(Location loc, BreakpointType type) { + setLocationAndDebug(instructions.size() - 1, loc, type); + } + + public CompileResult addChild(CompileResult child) { + this.children.add(child); + return child; + } + + public FunctionBody body() { + var builtChildren = new FunctionBody[children.size()]; + + for (var i = 0; i < children.size(); i++) builtChildren[i] = children.get(i).body(); + + 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/core/compilation/CompoundStatement.java b/src/java/me/topchetoeu/jscript/compilation/CompoundStatement.java similarity index 63% rename from src/java/me/topchetoeu/jscript/core/compilation/CompoundStatement.java rename to src/java/me/topchetoeu/jscript/compilation/CompoundStatement.java index f8390c6..ef1f644 100644 --- a/src/java/me/topchetoeu/jscript/core/compilation/CompoundStatement.java +++ b/src/java/me/topchetoeu/jscript/compilation/CompoundStatement.java @@ -1,12 +1,11 @@ -package me.topchetoeu.jscript.core.compilation; +package me.topchetoeu.jscript.compilation; import java.util.List; import java.util.Vector; import me.topchetoeu.jscript.common.Location; -import me.topchetoeu.jscript.core.compilation.Instruction.BreakpointType; -import me.topchetoeu.jscript.core.compilation.values.FunctionStatement; -import me.topchetoeu.jscript.core.engine.scope.ScopeRecord; +import me.topchetoeu.jscript.compilation.Instruction.BreakpointType; +import me.topchetoeu.jscript.compilation.values.FunctionStatement; public class CompoundStatement extends Statement { public final Statement[] statements; @@ -22,16 +21,16 @@ public class CompoundStatement extends Statement { } @Override - public void declare(ScopeRecord varsScope) { - for (var stm : statements) stm.declare(varsScope); + public void declare(CompileResult target) { + for (var stm : statements) stm.declare(target); } @Override - public void compile(CompileTarget target, ScopeRecord scope, boolean pollute, BreakpointType type) { + public void compile(CompileResult target, boolean pollute, BreakpointType type) { List statements = new Vector(); if (separateFuncs) for (var stm : this.statements) { if (stm instanceof FunctionStatement && ((FunctionStatement)stm).statement) { - stm.compile(target, scope, false); + stm.compile(target, false); } else statements.add(stm); } @@ -42,12 +41,12 @@ public class CompoundStatement extends Statement { for (var i = 0; i < statements.size(); i++) { var stm = statements.get(i); - if (i != statements.size() - 1) stm.compile(target, scope, false, BreakpointType.STEP_OVER); - else stm.compile(target, scope, polluted = pollute, BreakpointType.STEP_OVER); + if (i != statements.size() - 1) stm.compile(target, false, BreakpointType.STEP_OVER); + else stm.compile(target, polluted = pollute, BreakpointType.STEP_OVER); } if (!polluted && pollute) { - target.add(Instruction.loadValue(loc(), null)); + target.add(Instruction.pushUndefined()); } } diff --git a/src/java/me/topchetoeu/jscript/compilation/FunctionBody.java b/src/java/me/topchetoeu/jscript/compilation/FunctionBody.java new file mode 100644 index 0000000..6334eed --- /dev/null +++ b/src/java/me/topchetoeu/jscript/compilation/FunctionBody.java @@ -0,0 +1,14 @@ +package me.topchetoeu.jscript.compilation; + +public class FunctionBody { + public final FunctionBody[] children; + public final Instruction[] instructions; + public final int localsN, argsN; + + public FunctionBody(int localsN, int argsN, Instruction[] instructions, FunctionBody[] children) { + this.children = children; + this.argsN = argsN; + this.localsN = localsN; + this.instructions = instructions; + } +} diff --git a/src/java/me/topchetoeu/jscript/compilation/Instruction.java b/src/java/me/topchetoeu/jscript/compilation/Instruction.java new file mode 100644 index 0000000..b076242 --- /dev/null +++ b/src/java/me/topchetoeu/jscript/compilation/Instruction.java @@ -0,0 +1,370 @@ +package me.topchetoeu.jscript.compilation; + +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 { + public static enum Type { + NOP(0), + RETURN(1), + THROW(2), + THROW_SYNTAX(3), + DELETE(4), + TRY_START(5), + TRY_END(6), + + CALL(7), + CALL_NEW(8), + JMP_IF(9), + JMP_IFN(10), + JMP(11), + + PUSH_UNDEFINED(12), + PUSH_NULL(13), + PUSH_BOOL(14), + PUSH_NUMBER(15), + PUSH_STRING(16), + + LOAD_VAR(17), + LOAD_MEMBER(18), + LOAD_GLOB(20), + + LOAD_FUNC(21), + LOAD_ARR(22), + LOAD_OBJ(23), + STORE_SELF_FUNC(24), + LOAD_REGEX(25), + + DUP(26), + + STORE_VAR(27), + STORE_MEMBER(28), + DISCARD(29), + + MAKE_VAR(30), + DEF_PROP(31), + KEYS(32), + + TYPEOF(33), + OPERATION(34); + + private static final HashMap types = new HashMap<>(); + public final int numeric; + + static { + for (var val : Type.values()) types.put(val.numeric, val); + } + + private Type(int numeric) { + this.numeric = numeric; + } + + public static Type fromNumeric(int i) { + return types.get(i); + } + } + public static enum BreakpointType { + NONE, + STEP_OVER, + STEP_IN; + + public boolean shouldStepIn() { + return this != NONE; + } + public boolean shouldStepOver() { + return this == STEP_OVER; + } + } + + public final Type type; + public final Object[] params; + + @SuppressWarnings("unchecked") + public T get(int i) { + if (i >= params.length || i < 0) return null; + return (T)params[i]; + } + @SuppressWarnings("unchecked") + public T get(int i, T defaultVal) { + if (i >= params.length || i < 0) return defaultVal; + return (T)params[i]; + } + public boolean match(Object ...args) { + if (args.length != params.length) return false; + for (int i = 0; i < args.length; i++) { + var a = params[i]; + var b = args[i]; + if (a == null || b == null) { + if (!(a == null && b == null)) return false; + } + if (!a.equals(b)) return false; + } + return true; + } + public boolean is(int i, Object arg) { + if (params.length <= i) return false; + return params[i].equals(arg); + } + + public void write(DataOutputStream writer) throws IOException { + var rawType = type.numeric; + + switch (type) { + case KEYS: + case PUSH_BOOL: + case STORE_MEMBER: rawType |= (boolean)get(0) ? 128 : 0; break; + case STORE_VAR: rawType |= (boolean)get(1) ? 128 : 0; break; + case TYPEOF: rawType |= params.length > 0 ? 128 : 0; break; + default: + } + + writer.writeByte(rawType); + + switch (type) { + case CALL: writer.writeInt(get(0)); break; + case CALL_NEW: writer.writeInt(get(0)); break; + case DUP: writer.writeInt(get(0)); break; + case JMP: writer.writeInt(get(0)); break; + case JMP_IF: writer.writeInt(get(0)); break; + case JMP_IFN: writer.writeInt(get(0)); break; + case LOAD_ARR: writer.writeInt(get(0)); break; + case LOAD_FUNC: { + writer.writeInt(params.length - 1); + + for (var i = 0; i < params.length; i++) { + writer.writeInt(get(i + 1)); + } + + writer.writeInt(get(0)); + break; + } + case LOAD_REGEX: writer.writeUTF(get(0)); break; + case LOAD_VAR: writer.writeInt(get(0)); break; + case MAKE_VAR: writer.writeUTF(get(0)); break; + case OPERATION: writer.writeByte(((Operation)get(0)).numeric); break; + case PUSH_NUMBER: writer.writeDouble(get(0)); break; + case PUSH_STRING: writer.writeUTF(get(0)); break; + case STORE_SELF_FUNC: writer.writeInt(get(0)); break; + case STORE_VAR: writer.writeInt(get(0)); break; + case THROW_SYNTAX: writer.writeUTF(get(0)); + case TRY_START: + writer.writeInt(get(0)); + writer.writeInt(get(1)); + writer.writeInt(get(2)); + break; + case TYPEOF: + if (params.length > 0) writer.writeUTF(get(0)); + break; + default: + } + } + + private Instruction(Type type, Object ...params) { + this.type = type; + this.params = params; + } + + public static Instruction read(DataInputStream stream) throws IOException { + var rawType = stream.readUnsignedByte(); + var type = Type.fromNumeric(rawType & 127); + var flag = (rawType & 128) != 0; + + switch (type) { + case CALL: return call(stream.readInt()); + case CALL_NEW: return callNew(stream.readInt()); + case DEF_PROP: return defProp(); + case DELETE: return delete(); + case DISCARD: return discard(); + case DUP: return dup(stream.readInt()); + case JMP: return jmp(stream.readInt()); + case JMP_IF: return jmpIf(stream.readInt()); + case JMP_IFN: return jmpIfNot(stream.readInt()); + case KEYS: return keys(flag); + case LOAD_ARR: return loadArr(stream.readInt()); + case LOAD_FUNC: { + var captures = new int[stream.readInt()]; + + for (var i = 0; i < captures.length; i++) { + captures[i] = stream.readInt(); + } + + return loadFunc(stream.readInt(), captures); + } + case LOAD_GLOB: return loadGlob(); + case LOAD_MEMBER: return loadMember(); + case LOAD_OBJ: return loadObj(); + case LOAD_REGEX: return loadRegex(stream.readUTF(), null); + case LOAD_VAR: return loadVar(stream.readInt()); + case MAKE_VAR: return makeVar(stream.readUTF()); + case OPERATION: return operation(Operation.fromNumeric(stream.readUnsignedByte())); + case PUSH_NULL: return pushNull(); + case PUSH_UNDEFINED: return pushUndefined(); + case PUSH_BOOL: return pushValue(flag); + case PUSH_NUMBER: return pushValue(stream.readDouble()); + case PUSH_STRING: return pushValue(stream.readUTF()); + case RETURN: return ret(); + case STORE_MEMBER: return storeMember(flag); + case STORE_SELF_FUNC: return storeSelfFunc(stream.readInt()); + case STORE_VAR: return storeVar(stream.readInt(), flag); + case THROW: return throwInstr(); + case THROW_SYNTAX: return throwSyntax(stream.readUTF()); + case TRY_END: return tryEnd(); + case TRY_START: return tryStart(stream.readInt(), stream.readInt(), stream.readInt()); + case TYPEOF: return flag ? typeof(stream.readUTF()) : typeof(); + case NOP: + if (flag) return null; + else return nop(); + default: return null; + } + } + + public static Instruction tryStart(int catchStart, int finallyStart, int end) { + return new Instruction(Type.TRY_START, catchStart, finallyStart, end); + } + public static Instruction tryEnd() { + return new Instruction(Type.TRY_END); + } + public static Instruction throwInstr() { + return new Instruction(Type.THROW); + } + public static Instruction throwSyntax(SyntaxException err) { + return new Instruction(Type.THROW_SYNTAX, err.getMessage()); + } + public static Instruction throwSyntax(String err) { + return new Instruction(Type.THROW_SYNTAX, err); + } + public static Instruction delete() { + return new Instruction(Type.DELETE); + } + public static Instruction ret() { + return new Instruction(Type.RETURN); + } + public static Instruction debug() { + return new Instruction(Type.NOP, "debug"); + } + + public static Instruction nop(Object ...params) { + return new Instruction(Type.NOP, params); + } + + public static Instruction call(int argn) { + return new Instruction(Type.CALL, argn); + } + public static Instruction callNew(int argn) { + return new Instruction(Type.CALL_NEW, argn); + } + public static Instruction jmp(int offset) { + return new Instruction(Type.JMP, offset); + } + public static Instruction jmpIf(int offset) { + return new Instruction(Type.JMP_IF, offset); + } + public static Instruction jmpIfNot(int offset) { + return new Instruction(Type.JMP_IFN, offset); + } + + public static Instruction pushUndefined() { + return new Instruction(Type.PUSH_UNDEFINED); + } + public static Instruction pushNull() { + return new Instruction(Type.PUSH_NULL); + } + public static Instruction pushValue(boolean val) { + return new Instruction(Type.PUSH_BOOL, val); + } + public static Instruction pushValue(double val) { + return new Instruction(Type.PUSH_NUMBER, val); + } + public static Instruction pushValue(String val) { + return new Instruction(Type.PUSH_STRING, val); + } + + public static Instruction makeVar(String name) { + return new Instruction(Type.MAKE_VAR, name); + } + public static Instruction loadVar(Object i) { + return new Instruction(Type.LOAD_VAR, i); + } + public static Instruction loadGlob() { + return new Instruction(Type.LOAD_GLOB); + } + public static Instruction loadMember() { + return new Instruction(Type.LOAD_MEMBER); + } + + public static Instruction loadRegex(String pattern, String flags) { + return new Instruction(Type.LOAD_REGEX, pattern, flags); + } + public static Instruction loadFunc(int id, int[] captures) { + var args = new Object[1 + captures.length]; + args[0] = id; + for (var i = 0; i < captures.length; i++) args[i + 1] = captures[i]; + return new Instruction(Type.LOAD_FUNC, args); + } + public static Instruction loadObj() { + return new Instruction(Type.LOAD_OBJ); + } + public static Instruction loadArr(int count) { + return new Instruction(Type.LOAD_ARR, count); + } + public static Instruction dup() { + return new Instruction(Type.DUP, 1); + } + public static Instruction dup(int count) { + return new Instruction(Type.DUP, count); + } + + public static Instruction storeSelfFunc(int i) { + return new Instruction(Type.STORE_SELF_FUNC, i); + } + public static Instruction storeVar(Object i) { + return new Instruction(Type.STORE_VAR, i, false); + } + public static Instruction storeVar(Object i, boolean keep) { + return new Instruction(Type.STORE_VAR, i, keep); + } + public static Instruction storeMember() { + return new Instruction(Type.STORE_MEMBER, false); + } + public static Instruction storeMember(boolean keep) { + return new Instruction(Type.STORE_MEMBER, keep); + } + public static Instruction discard() { + return new Instruction(Type.DISCARD); + } + + public static Instruction typeof() { + return new Instruction(Type.TYPEOF); + } + public static Instruction typeof(String varName) { + return new Instruction(Type.TYPEOF, varName); + } + + public static Instruction keys(boolean forInFormat) { + return new Instruction(Type.KEYS, forInFormat); + } + + public static Instruction defProp() { + return new Instruction(Type.DEF_PROP); + } + + public static Instruction operation(Operation op) { + return new Instruction(Type.OPERATION, op); + } + + @Override + public String toString() { + var res = type.toString(); + + for (int i = 0; i < params.length; i++) { + res += " " + params[i]; + } + + return res; + } +} diff --git a/src/java/me/topchetoeu/jscript/compilation/Statement.java b/src/java/me/topchetoeu/jscript/compilation/Statement.java new file mode 100644 index 0000000..d077d4a --- /dev/null +++ b/src/java/me/topchetoeu/jscript/compilation/Statement.java @@ -0,0 +1,27 @@ +package me.topchetoeu.jscript.compilation; + +import me.topchetoeu.jscript.common.Location; +import me.topchetoeu.jscript.compilation.Instruction.BreakpointType; + +public abstract class Statement { + private Location _loc; + + public boolean pure() { return false; } + public void declare(CompileResult target) { } + + public void compile(CompileResult target, boolean pollute, BreakpointType type) { + int start = target.size(); + compile(target, pollute); + if (target.size() != start) target.setLocationAndDebug(start, loc(), type); + } + public void compile(CompileResult target, boolean pollute) { + compile(target, pollute, BreakpointType.NONE); + } + + public Location loc() { return _loc; } + public void setLoc(Location loc) { _loc = loc; } + + protected Statement(Location loc) { + this._loc = loc; + } +} \ No newline at end of file diff --git a/src/java/me/topchetoeu/jscript/core/compilation/ThrowSyntaxStatement.java b/src/java/me/topchetoeu/jscript/compilation/ThrowSyntaxStatement.java similarity index 51% rename from src/java/me/topchetoeu/jscript/core/compilation/ThrowSyntaxStatement.java rename to src/java/me/topchetoeu/jscript/compilation/ThrowSyntaxStatement.java index 406b286..4e88f06 100644 --- a/src/java/me/topchetoeu/jscript/core/compilation/ThrowSyntaxStatement.java +++ b/src/java/me/topchetoeu/jscript/compilation/ThrowSyntaxStatement.java @@ -1,14 +1,13 @@ -package me.topchetoeu.jscript.core.compilation; +package me.topchetoeu.jscript.compilation; -import me.topchetoeu.jscript.core.engine.scope.ScopeRecord; import me.topchetoeu.jscript.core.exceptions.SyntaxException; public class ThrowSyntaxStatement extends Statement { public final String name; @Override - public void compile(CompileTarget target, ScopeRecord scope, boolean pollute) { - target.add(Instruction.throwSyntax(loc(), name)); + public void compile(CompileResult target, boolean pollute) { + target.add(Instruction.throwSyntax(name)); } public ThrowSyntaxStatement(SyntaxException e) { diff --git a/src/java/me/topchetoeu/jscript/core/compilation/VariableDeclareStatement.java b/src/java/me/topchetoeu/jscript/compilation/VariableDeclareStatement.java similarity index 58% rename from src/java/me/topchetoeu/jscript/core/compilation/VariableDeclareStatement.java rename to src/java/me/topchetoeu/jscript/compilation/VariableDeclareStatement.java index 72742b9..90e4ac6 100644 --- a/src/java/me/topchetoeu/jscript/core/compilation/VariableDeclareStatement.java +++ b/src/java/me/topchetoeu/jscript/compilation/VariableDeclareStatement.java @@ -1,11 +1,10 @@ -package me.topchetoeu.jscript.core.compilation; +package me.topchetoeu.jscript.compilation; import java.util.List; import me.topchetoeu.jscript.common.Location; -import me.topchetoeu.jscript.core.compilation.Instruction.BreakpointType; -import me.topchetoeu.jscript.core.compilation.values.FunctionStatement; -import me.topchetoeu.jscript.core.engine.scope.ScopeRecord; +import me.topchetoeu.jscript.compilation.Instruction.BreakpointType; +import me.topchetoeu.jscript.compilation.values.FunctionStatement; public class VariableDeclareStatement extends Statement { public static class Pair { @@ -23,26 +22,26 @@ public class VariableDeclareStatement extends Statement { public final List values; @Override - public void declare(ScopeRecord varsScope) { + public void declare(CompileResult target) { for (var key : values) { - varsScope.define(key.name); + target.scope.define(key.name); } } @Override - public void compile(CompileTarget target, ScopeRecord scope, boolean pollute) { + public void compile(CompileResult target, boolean pollute) { for (var entry : values) { if (entry.name == null) continue; - var key = scope.getKey(entry.name); + var key = target.scope.getKey(entry.name); - if (key instanceof String) target.add(Instruction.makeVar(entry.location, (String)key)); + if (key instanceof String) target.add(Instruction.makeVar((String)key)); if (entry.value != null) { - FunctionStatement.compileWithName(entry.value, target, scope, true, entry.name, BreakpointType.STEP_OVER); - target.add(Instruction.storeVar(entry.location, key)); + FunctionStatement.compileWithName(entry.value, target, true, entry.name, BreakpointType.STEP_OVER); + target.add(Instruction.storeVar(key)); } } - if (pollute) target.add(Instruction.loadValue(loc(), null)); + if (pollute) target.add(Instruction.pushUndefined()); } public VariableDeclareStatement(Location loc, List values) { diff --git a/src/java/me/topchetoeu/jscript/compilation/control/BreakStatement.java b/src/java/me/topchetoeu/jscript/compilation/control/BreakStatement.java new file mode 100644 index 0000000..85a76c7 --- /dev/null +++ b/src/java/me/topchetoeu/jscript/compilation/control/BreakStatement.java @@ -0,0 +1,21 @@ +package me.topchetoeu.jscript.compilation.control; + +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 { + public final String label; + + @Override + public void compile(CompileResult target, boolean pollute) { + target.add(Instruction.nop("break", label)); + if (pollute) target.add(Instruction.pushUndefined()); + } + + public BreakStatement(Location loc, String label) { + super(loc); + this.label = label; + } +} diff --git a/src/java/me/topchetoeu/jscript/compilation/control/ContinueStatement.java b/src/java/me/topchetoeu/jscript/compilation/control/ContinueStatement.java new file mode 100644 index 0000000..404eadd --- /dev/null +++ b/src/java/me/topchetoeu/jscript/compilation/control/ContinueStatement.java @@ -0,0 +1,21 @@ +package me.topchetoeu.jscript.compilation.control; + +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 { + public final String label; + + @Override + public void compile(CompileResult target, boolean pollute) { + target.add(Instruction.nop(loc(), "cont", label)); + if (pollute) target.add(Instruction.pushUndefined()); + } + + public ContinueStatement(Location loc, String label) { + super(loc); + this.label = label; + } +} diff --git a/src/java/me/topchetoeu/jscript/compilation/control/DebugStatement.java b/src/java/me/topchetoeu/jscript/compilation/control/DebugStatement.java new file mode 100644 index 0000000..84b763d --- /dev/null +++ b/src/java/me/topchetoeu/jscript/compilation/control/DebugStatement.java @@ -0,0 +1,18 @@ +package me.topchetoeu.jscript.compilation.control; + +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 { + @Override + public void compile(CompileResult target, boolean pollute) { + target.add(Instruction.debug()); + if (pollute) target.add(Instruction.pushUndefined()); + } + + public DebugStatement(Location loc) { + super(loc); + } +} diff --git a/src/java/me/topchetoeu/jscript/compilation/control/DeleteStatement.java b/src/java/me/topchetoeu/jscript/compilation/control/DeleteStatement.java new file mode 100644 index 0000000..fe21e2d --- /dev/null +++ b/src/java/me/topchetoeu/jscript/compilation/control/DeleteStatement.java @@ -0,0 +1,26 @@ +package me.topchetoeu.jscript.compilation.control; + +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 { + public final Statement key; + public final Statement value; + + @Override + public void compile(CompileResult target, boolean pollute) { + value.compile(target, true); + key.compile(target, true); + + target.add(Instruction.delete()); + if (pollute) target.add(Instruction.pushValue(true)); + } + + public DeleteStatement(Location loc, Statement key, Statement value) { + super(loc); + this.key = key; + this.value = value; + } +} diff --git a/src/java/me/topchetoeu/jscript/compilation/control/DoWhileStatement.java b/src/java/me/topchetoeu/jscript/compilation/control/DoWhileStatement.java new file mode 100644 index 0000000..28cc45b --- /dev/null +++ b/src/java/me/topchetoeu/jscript/compilation/control/DoWhileStatement.java @@ -0,0 +1,36 @@ +package me.topchetoeu.jscript.compilation.control; + +import me.topchetoeu.jscript.common.Location; +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; + public final String label; + + @Override + public void declare(CompileResult target) { + body.declare(target); + } + + @Override + public void compile(CompileResult target, boolean pollute) { + int start = target.size(); + body.compile(target, false, BreakpointType.STEP_OVER); + int mid = target.size(); + condition.compile(target, true, BreakpointType.STEP_OVER); + int end = target.size(); + + WhileStatement.replaceBreaks(target, label, start, mid - 1, mid, end + 1); + target.add(Instruction.jmpIf(start - end)); + } + + public DoWhileStatement(Location loc, String label, Statement condition, Statement body) { + super(loc); + this.label = label; + this.condition = condition; + this.body = body; + } +} diff --git a/src/java/me/topchetoeu/jscript/compilation/control/ForInStatement.java b/src/java/me/topchetoeu/jscript/compilation/control/ForInStatement.java new file mode 100644 index 0000000..188c1cc --- /dev/null +++ b/src/java/me/topchetoeu/jscript/compilation/control/ForInStatement.java @@ -0,0 +1,69 @@ +package me.topchetoeu.jscript.compilation.control; + +import me.topchetoeu.jscript.common.Location; +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; + public final boolean isDeclaration; + public final Statement varValue, object, body; + public final String label; + public final Location varLocation; + + @Override + public void declare(CompileResult target) { + body.declare(target); + if (isDeclaration) target.scope.define(varName); + } + + @Override + public void compile(CompileResult target, boolean pollute) { + var key = target.scope.getKey(varName); + + if (key instanceof String) target.add(Instruction.makeVar((String)key)); + + if (varValue != null) { + varValue.compile(target, true); + target.add(Instruction.storeVar(target.scope.getKey(varName))); + } + + object.compile(target, true, BreakpointType.STEP_OVER); + target.add(Instruction.keys(true)); + + int start = target.size(); + target.add(Instruction.dup()); + target.add(Instruction.pushUndefined()); + target.add(Instruction.operation(Operation.EQUALS)); + int mid = target.temp(); + + target.add(Instruction.pushValue("value")).setLocation(varLocation); + target.add(Instruction.loadMember()).setLocation(varLocation); + target.add(Instruction.storeVar(key)).setLocationAndDebug(object.loc(), BreakpointType.STEP_OVER); + + body.compile(target, false, BreakpointType.STEP_OVER); + + int end = target.size(); + + WhileStatement.replaceBreaks(target, label, mid + 1, end, start, end + 1); + + target.add(Instruction.jmp(start - end)); + target.add(Instruction.discard()); + target.set(mid, Instruction.jmpIf(end - mid + 1)); + if (pollute) target.add(Instruction.pushUndefined()); + } + + public ForInStatement(Location loc, Location varLocation, String label, boolean isDecl, String varName, Statement varValue, Statement object, Statement body) { + super(loc); + this.varLocation = varLocation; + this.label = label; + this.isDeclaration = isDecl; + this.varName = varName; + this.varValue = varValue; + this.object = object; + this.body = body; + } +} diff --git a/src/java/me/topchetoeu/jscript/compilation/control/ForStatement.java b/src/java/me/topchetoeu/jscript/compilation/control/ForStatement.java new file mode 100644 index 0000000..0012f96 --- /dev/null +++ b/src/java/me/topchetoeu/jscript/compilation/control/ForStatement.java @@ -0,0 +1,45 @@ +package me.topchetoeu.jscript.compilation.control; + +import me.topchetoeu.jscript.common.Location; +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; + public final String label; + + @Override + public void declare(CompileResult target) { + declaration.declare(target); + body.declare(target); + } + @Override + public void compile(CompileResult target, boolean pollute) { + declaration.compile(target, false, BreakpointType.STEP_OVER); + + int start = target.size(); + condition.compile(target, true, BreakpointType.STEP_OVER); + int mid = target.temp(); + body.compile(target, false, BreakpointType.STEP_OVER); + int beforeAssign = target.size(); + assignment.compile(target, false, BreakpointType.STEP_OVER); + int end = target.size(); + + WhileStatement.replaceBreaks(target, label, mid + 1, end, beforeAssign, end + 1); + + target.add(Instruction.jmp(start - end)); + target.set(mid, Instruction.jmpIfNot(end - mid + 1)); + if (pollute) target.add(Instruction.pushUndefined()); + } + + public ForStatement(Location loc, String label, Statement declaration, Statement condition, Statement assignment, Statement body) { + super(loc); + this.label = label; + this.declaration = declaration; + this.condition = condition; + this.assignment = assignment; + this.body = body; + } +} diff --git a/src/java/me/topchetoeu/jscript/compilation/control/IfStatement.java b/src/java/me/topchetoeu/jscript/compilation/control/IfStatement.java new file mode 100644 index 0000000..2eee62a --- /dev/null +++ b/src/java/me/topchetoeu/jscript/compilation/control/IfStatement.java @@ -0,0 +1,48 @@ +package me.topchetoeu.jscript.compilation.control; + +import me.topchetoeu.jscript.common.Location; +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; + + @Override + public void declare(CompileResult target) { + body.declare(target); + if (elseBody != null) elseBody.declare(target); + } + + @Override public void compile(CompileResult target, boolean pollute, BreakpointType breakpoint) { + condition.compile(target, true, breakpoint); + + if (elseBody == null) { + int i = target.temp(); + body.compile(target, pollute, breakpoint); + int endI = target.size(); + target.set(i, Instruction.jmpIfNot(endI - i)); + } + else { + int start = target.temp(); + body.compile(target, pollute, breakpoint); + int mid = target.temp(); + elseBody.compile(target, pollute, breakpoint); + int end = target.size(); + + target.set(start, Instruction.jmpIfNot(mid - start - 1)); + target.set(mid, Instruction.jmp(end - mid)); + } + } + @Override public void compile(CompileResult target, boolean pollute) { + compile(target, pollute, BreakpointType.STEP_IN); + } + + public IfStatement(Location loc, Statement condition, Statement body, Statement elseBody) { + super(loc); + this.condition = condition; + this.body = body; + this.elseBody = elseBody; + } +} diff --git a/src/java/me/topchetoeu/jscript/compilation/control/ReturnStatement.java b/src/java/me/topchetoeu/jscript/compilation/control/ReturnStatement.java new file mode 100644 index 0000000..5534c3e --- /dev/null +++ b/src/java/me/topchetoeu/jscript/compilation/control/ReturnStatement.java @@ -0,0 +1,22 @@ +package me.topchetoeu.jscript.compilation.control; + +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 { + public final Statement value; + + @Override + public void compile(CompileResult target, boolean pollute) { + if (value == null) target.add(Instruction.pushUndefined()); + else value.compile(target, true); + target.add(Instruction.ret()).setLocation(loc()); + } + + public ReturnStatement(Location loc, Statement value) { + super(loc); + this.value = value; + } +} diff --git a/src/java/me/topchetoeu/jscript/compilation/control/SwitchStatement.java b/src/java/me/topchetoeu/jscript/compilation/control/SwitchStatement.java new file mode 100644 index 0000000..9d0cf25 --- /dev/null +++ b/src/java/me/topchetoeu/jscript/compilation/control/SwitchStatement.java @@ -0,0 +1,83 @@ +package me.topchetoeu.jscript.compilation.control; + +import java.util.HashMap; + +import me.topchetoeu.jscript.common.Location; +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 { + public final Statement value; + public final int statementI; + + public SwitchCase(Statement value, int statementI) { + this.value = value; + this.statementI = statementI; + } + } + + public final Statement value; + public final SwitchCase[] cases; + public final Statement[] body; + public final int defaultI; + + @Override + public void declare(CompileResult target) { + for (var stm : body) stm.declare(target); + } + + @Override + public void compile(CompileResult target, boolean pollute) { + var caseToStatement = new HashMap(); + var statementToIndex = new HashMap(); + + value.compile(target, true, BreakpointType.STEP_OVER); + + for (var ccase : cases) { + target.add(Instruction.dup()); + ccase.value.compile(target, true); + target.add(Instruction.operation(Operation.EQUALS)); + caseToStatement.put(target.temp(), ccase.statementI); + } + + int start = target.temp(); + + for (var stm : body) { + statementToIndex.put(statementToIndex.size(), target.size()); + stm.compile(target, false, BreakpointType.STEP_OVER); + } + + int end = target.size(); + target.add(Instruction.discard()); + if (pollute) target.add(Instruction.pushUndefined()); + + if (defaultI < 0 || defaultI >= body.length) target.set(start, Instruction.jmp(end - start)); + else target.set(start, Instruction.jmp(statementToIndex.get(defaultI) - start)); + + for (int i = start; i < end; i++) { + var instr = target.get(i); + if (instr.type == Type.NOP && instr.is(0, "break") && instr.get(1) == null) { + target.set(i, Instruction.jmp(end - i)); + } + } + for (var el : caseToStatement.entrySet()) { + var i = statementToIndex.get(el.getValue()); + if (i == null) i = end; + target.set(el.getKey(), Instruction.jmpIf(i - el.getKey())); + } + + } + + public SwitchStatement(Location loc, Statement value, int defaultI, SwitchCase[] cases, Statement[] body) { + super(loc); + this.value = value; + this.defaultI = defaultI; + this.cases = cases; + this.body = body; + } +} diff --git a/src/java/me/topchetoeu/jscript/compilation/control/ThrowStatement.java b/src/java/me/topchetoeu/jscript/compilation/control/ThrowStatement.java new file mode 100644 index 0000000..253268b --- /dev/null +++ b/src/java/me/topchetoeu/jscript/compilation/control/ThrowStatement.java @@ -0,0 +1,21 @@ +package me.topchetoeu.jscript.compilation.control; + +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 { + public final Statement value; + + @Override + public void compile(CompileResult target, boolean pollute) { + value.compile(target, true); + target.add(Instruction.throwInstr()).setLocation(loc()); + } + + public ThrowStatement(Location loc, Statement value) { + super(loc); + this.value = value; + } +} diff --git a/src/java/me/topchetoeu/jscript/compilation/control/TryStatement.java b/src/java/me/topchetoeu/jscript/compilation/control/TryStatement.java new file mode 100644 index 0000000..2ca8eb7 --- /dev/null +++ b/src/java/me/topchetoeu/jscript/compilation/control/TryStatement.java @@ -0,0 +1,58 @@ +package me.topchetoeu.jscript.compilation.control; + +import me.topchetoeu.jscript.common.Location; +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; + public final Statement catchBody; + public final Statement finallyBody; + public final String name; + + @Override + public void declare(CompileResult target) { + tryBody.declare(target); + if (catchBody != null) catchBody.declare(target); + if (finallyBody != null) finallyBody.declare(target); + } + + @Override + public void compile(CompileResult target, boolean pollute, BreakpointType bpt) { + int replace = target.temp(); + + int start = replace + 1, catchStart = -1, finallyStart = -1; + + tryBody.compile(target, false); + target.add(Instruction.tryEnd()); + + if (catchBody != null) { + catchStart = target.size() - start; + target.scope.define(name, true); + catchBody.compile(target, false); + target.scope.undefine(); + target.add(Instruction.tryEnd()); + } + + if (finallyBody != null) { + finallyStart = target.size() - start; + finallyBody.compile(target, false); + target.add(Instruction.tryEnd()); + } + + target.set(replace, Instruction.tryStart(catchStart, finallyStart, target.size() - start)); + target.setLocationAndDebug(replace, loc(), BreakpointType.STEP_OVER); + + if (pollute) target.add(Instruction.pushUndefined()); + } + + public TryStatement(Location loc, Statement tryBody, Statement catchBody, Statement finallyBody, String name) { + super(loc); + this.tryBody = tryBody; + this.catchBody = catchBody; + this.finallyBody = finallyBody; + this.name = name; + } +} diff --git a/src/java/me/topchetoeu/jscript/compilation/control/WhileStatement.java b/src/java/me/topchetoeu/jscript/compilation/control/WhileStatement.java new file mode 100644 index 0000000..f7b3953 --- /dev/null +++ b/src/java/me/topchetoeu/jscript/compilation/control/WhileStatement.java @@ -0,0 +1,52 @@ +package me.topchetoeu.jscript.compilation.control; + +import me.topchetoeu.jscript.common.Location; +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; + public final String label; + + @Override + public void declare(CompileResult target) { + body.declare(target); + } + @Override + public void compile(CompileResult target, boolean pollute) { + int start = target.size(); + condition.compile(target, true); + int mid = target.temp(); + body.compile(target, false, BreakpointType.STEP_OVER); + + int end = target.size(); + + replaceBreaks(target, label, mid + 1, end, start, end + 1); + + target.add(Instruction.jmp(start - end)); + target.set(mid, Instruction.jmpIfNot(end - mid + 1)); + if (pollute) target.add(Instruction.pushUndefined()); + } + + public WhileStatement(Location loc, String label, Statement condition, Statement body) { + super(loc); + this.label = label; + this.condition = condition; + this.body = body; + } + + public static void replaceBreaks(CompileResult target, String label, int start, int end, int continuePoint, int breakPoint) { + for (int i = start; i < end; i++) { + var instr = target.get(i); + if (instr.type == Type.NOP && instr.is(0, "cont") && (instr.get(1) == null || instr.is(1, label))) { + target.set(i, Instruction.jmp(continuePoint - i)); + } + if (instr.type == Type.NOP && instr.is(0, "break") && (instr.get(1) == null || instr.is(1, label))) { + target.set(i, Instruction.jmp(breakPoint - i)); + } + } + } +} diff --git a/src/java/me/topchetoeu/jscript/compilation/mapping/ConvertType.java b/src/java/me/topchetoeu/jscript/compilation/mapping/ConvertType.java new file mode 100644 index 0000000..397f887 --- /dev/null +++ b/src/java/me/topchetoeu/jscript/compilation/mapping/ConvertType.java @@ -0,0 +1,8 @@ +package me.topchetoeu.jscript.compilation.mapping; + +public enum ConvertType { + Exact, + Lower, + Upper, + Both, +} diff --git a/src/java/me/topchetoeu/jscript/compilation/mapping/FunctionMap.java b/src/java/me/topchetoeu/jscript/compilation/mapping/FunctionMap.java new file mode 100644 index 0000000..21f4140 --- /dev/null +++ b/src/java/me/topchetoeu/jscript/compilation/mapping/FunctionMap.java @@ -0,0 +1,147 @@ +package me.topchetoeu.jscript.compilation.mapping; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.SortedSet; +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.core.scope.LocalScopeRecord; + +public class FunctionMap { + public static class FunctionMapBuilder { + private final TreeMap sourceMap = new TreeMap<>(); + private final HashMap breakpoints = new HashMap<>(); + + public Location toLocation(int pc) { + return sourceMap.headMap(pc, true).firstEntry().getValue(); + } + + public FunctionMapBuilder setDebug(Location loc, BreakpointType type) { + breakpoints.put(loc, type); + return this; + } + public FunctionMapBuilder setLocation(int i, Location loc) { + sourceMap.put(i, loc); + return this; + } + public FunctionMapBuilder setLocationAndDebug(int i, Location loc, BreakpointType type) { + setDebug(loc, type); + setLocation(i, loc); + return this; + } + + public Location first() { + return sourceMap.firstEntry().getValue(); + } + public Location last() { + return sourceMap.lastEntry().getValue(); + } + + public FunctionMap build(String[] localNames, String[] captureNames) { + return new FunctionMap(sourceMap, breakpoints, localNames, captureNames); + } + public FunctionMap build(LocalScopeRecord scope) { + return new FunctionMap(sourceMap, breakpoints, scope.locals(), scope.captures()); + } + public FunctionMap build() { + return new FunctionMap(sourceMap, breakpoints, new String[0], new String[0]); + } + + private FunctionMapBuilder() { } + } + + public static final FunctionMap EMPTY = new FunctionMap(); + + private final HashMap bps = new HashMap<>(); + private final TreeSet bpLocs = new TreeSet<>(); + + private final TreeMap pcToLoc = new TreeMap<>(); + private final HashMap locToPc = new HashMap<>(); + + public final String[] localNames, captureNames; + + 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(); + } + public Location toLocation(int pc) { + return toLocation(pc, false); + } + + public BreakpointType getBreakpoint(Location loc) { + return bps.getOrDefault(loc, BreakpointType.NONE); + } + public Location correctBreakpoint(Location loc) { + return bpLocs.ceiling(loc); + } + public SortedSet breakpoints() { + return Collections.unmodifiableSortedSet(bpLocs); + } + + public Location start() { + return pcToLoc.firstEntry().getValue(); + } + public Location end() { + return pcToLoc.lastEntry().getValue(); + } + + public Integer toProgramCounter(Location loc) { + return locToPc.get(loc); + } + + public FunctionMap apply(SourceMap map) { + var res = new FunctionMap(); + + for (var el : new ArrayList<>(pcToLoc.entrySet())) { + res.pcToLoc.put(el.getKey(), map.toCompiled(el.getValue())); + } + for (var el : new ArrayList<>(locToPc.entrySet())) { + var mapped = map.toOriginal(el.getKey()); + res.locToPc.put(mapped, el.getValue()); + } + + return res; + } + + public FunctionMap clone() { + var res = new FunctionMap(); + res.pcToLoc.putAll(this.pcToLoc); + res.locToPc.putAll(this.locToPc); + return res; + } + + public FunctionMap(Map map, Map breakpoints, String[] localNames, String[] captureNames) { + for (var el : map.entrySet()) { + var pc = el.getKey(); + var loc = el.getValue(); + + var a = pcToLoc.remove(pc); + var b = locToPc.remove(loc); + + if (b != null) pcToLoc.remove(b); + if (a != null) locToPc.remove(a); + } + for (var el : breakpoints.entrySet()) { + if (el.getValue() == null || el.getValue() == BreakpointType.NONE) continue; + bps.put(el.getKey(), el.getValue()); + bpLocs.add(el.getKey()); + } + + this.localNames = localNames; + this.captureNames = captureNames; + } + private FunctionMap() { + localNames = new String[0]; + captureNames = new String[0]; + } + + public static FunctionMapBuilder builder() { + return new FunctionMapBuilder(); + } +} \ No newline at end of file diff --git a/src/java/me/topchetoeu/jscript/utils/mapping/SourceMap.java b/src/java/me/topchetoeu/jscript/compilation/mapping/SourceMap.java similarity index 94% rename from src/java/me/topchetoeu/jscript/utils/mapping/SourceMap.java rename to src/java/me/topchetoeu/jscript/compilation/mapping/SourceMap.java index 6f9a53d..6a8ad05 100644 --- a/src/java/me/topchetoeu/jscript/utils/mapping/SourceMap.java +++ b/src/java/me/topchetoeu/jscript/compilation/mapping/SourceMap.java @@ -1,4 +1,4 @@ -package me.topchetoeu.jscript.utils.mapping; +package me.topchetoeu.jscript.compilation.mapping; import java.util.ArrayList; import java.util.List; @@ -32,11 +32,12 @@ public class SourceMap { for (var el : new ArrayList<>(origToComp.entrySet())) { var mapped = convert(el.getValue(), map.origToComp); - add(el.getKey(), mapped); + res.origToComp.put(el.getKey(), mapped); } for (var el : new ArrayList<>(compToOrig.entrySet())) { var mapped = convert(el.getKey(), map.compToOrig); - add(el.getValue(), mapped); + res.compToOrig.put(mapped, el.getValue()); + res.add(el.getValue(), mapped); } return res; diff --git a/src/java/me/topchetoeu/jscript/core/parsing/Operator.java b/src/java/me/topchetoeu/jscript/compilation/parsing/Operator.java similarity index 89% rename from src/java/me/topchetoeu/jscript/core/parsing/Operator.java rename to src/java/me/topchetoeu/jscript/compilation/parsing/Operator.java index 5178ef1..80ce38a 100644 --- a/src/java/me/topchetoeu/jscript/core/parsing/Operator.java +++ b/src/java/me/topchetoeu/jscript/compilation/parsing/Operator.java @@ -1,9 +1,9 @@ -package me.topchetoeu.jscript.core.parsing; +package me.topchetoeu.jscript.compilation.parsing; import java.util.HashMap; import java.util.Map; -import me.topchetoeu.jscript.core.engine.Operation; +import me.topchetoeu.jscript.core.Operation; public enum Operator { MULTIPLY("*", Operation.MULTIPLY, 13), @@ -55,7 +55,7 @@ public enum Operator { INCREASE("++"), DECREASE("--"); - public final String value; + public final String readable; public final Operation operation; public final int precedence; public final boolean reverse; @@ -63,7 +63,7 @@ public enum Operator { static { for (var el : Operator.values()) { - ops.put(el.value, el); + ops.put(el.readable, el); } } @@ -74,38 +74,38 @@ public enum Operator { } private Operator() { - this.value = null; + this.readable = null; this.operation = null; this.precedence = -1; this.reverse = false; } private Operator(String value) { - this. value = value; + this.readable = value; this.operation = null; this.precedence = -1; this.reverse = false; } private Operator(String value, int precedence) { - this. value = value; + this.readable = value; this.operation = null; this.precedence = precedence; this.reverse = false; } private Operator(String value, int precedence, boolean reverse) { - this. value = value; + this.readable = value; this.operation = null; this.precedence = precedence; this.reverse = reverse; } private Operator(String value, Operation funcName, int precedence) { - this. value = value; + this.readable = value; this.operation = funcName; this.precedence = precedence; this.reverse = false; } private Operator(String value, Operation funcName, int precedence, boolean reverse) { - this.value = value; + this.readable = value; this.operation = funcName; this.precedence = precedence; this.reverse = reverse; diff --git a/src/java/me/topchetoeu/jscript/core/parsing/ParseRes.java b/src/java/me/topchetoeu/jscript/compilation/parsing/ParseRes.java similarity index 96% rename from src/java/me/topchetoeu/jscript/core/parsing/ParseRes.java rename to src/java/me/topchetoeu/jscript/compilation/parsing/ParseRes.java index 8fc9a08..982c504 100644 --- a/src/java/me/topchetoeu/jscript/core/parsing/ParseRes.java +++ b/src/java/me/topchetoeu/jscript/compilation/parsing/ParseRes.java @@ -1,10 +1,10 @@ -package me.topchetoeu.jscript.core.parsing; +package me.topchetoeu.jscript.compilation.parsing; import java.util.List; import java.util.Map; import me.topchetoeu.jscript.common.Location; -import me.topchetoeu.jscript.core.parsing.Parsing.Parser; +import me.topchetoeu.jscript.compilation.parsing.Parsing.Parser; public class ParseRes { public static enum State { diff --git a/src/java/me/topchetoeu/jscript/core/parsing/Parsing.java b/src/java/me/topchetoeu/jscript/compilation/parsing/Parsing.java similarity index 96% rename from src/java/me/topchetoeu/jscript/core/parsing/Parsing.java rename to src/java/me/topchetoeu/jscript/compilation/parsing/Parsing.java index 68ad849..2c1c21c 100644 --- a/src/java/me/topchetoeu/jscript/core/parsing/Parsing.java +++ b/src/java/me/topchetoeu/jscript/compilation/parsing/Parsing.java @@ -1,4 +1,4 @@ -package me.topchetoeu.jscript.core.parsing; +package me.topchetoeu.jscript.compilation.parsing; import java.util.ArrayList; import java.util.Collection; @@ -6,21 +6,18 @@ import java.util.HashMap; import java.util.HashSet; import java.util.LinkedHashMap; import java.util.List; -import java.util.TreeSet; import me.topchetoeu.jscript.common.Filename; import me.topchetoeu.jscript.common.Location; -import me.topchetoeu.jscript.core.compilation.*; -import me.topchetoeu.jscript.core.compilation.VariableDeclareStatement.Pair; -import me.topchetoeu.jscript.core.compilation.control.*; -import me.topchetoeu.jscript.core.compilation.control.SwitchStatement.SwitchCase; -import me.topchetoeu.jscript.core.compilation.values.*; -import me.topchetoeu.jscript.core.engine.Environment; -import me.topchetoeu.jscript.core.engine.Operation; -import me.topchetoeu.jscript.core.engine.scope.LocalScopeRecord; -import me.topchetoeu.jscript.core.engine.values.Values; +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; -import me.topchetoeu.jscript.core.parsing.ParseRes.State; // TODO: this has to be rewritten public class Parsing { @@ -29,11 +26,11 @@ public class Parsing { } private static class ObjProp { - public final Object name; + public final String name; public final String access; public final FunctionStatement func; - public ObjProp(Object name, String access, FunctionStatement func) { + public ObjProp(String name, String access, FunctionStatement func) { this.name = name; this.access = access; this.func = func; @@ -579,9 +576,9 @@ public class Parsing { var loc = new Location(el.line, el.start, filename); switch (el.type) { case LITERAL: res.add(Token.identifier(el.line, el.start, el.value)); break; - case NUMBER: res.add(Token.number(el.line, el.start, parseNumber(loc, el.value))); break; - case STRING: res.add(Token.string(el.line, el.start, parseString(loc, el.value))); break; - case REGEX: res.add(Token.regex(el.line, el.start, parseRegex(loc, el.value))); break; + case NUMBER: res.add(Token.number(el.line, el.start, parseNumber(loc, el.value), el.value)); break; + case STRING: res.add(Token.string(el.line, el.start, parseString(loc, el.value), el.value)); break; + case REGEX: res.add(Token.regex(el.line, el.start, parseRegex(loc, el.value), el.value)); break; case OPERATOR: Operator op = Operator.parse(el.value); if (op == null) throw new SyntaxException(loc, String.format("Unrecognized operator '%s'.", el.value)); @@ -776,15 +773,18 @@ public class Parsing { return ParseRes.res(args, n); } - public static ParseRes parsePropName(Filename filename, List tokens, int i) { - var idRes = parseIdentifier(tokens, i); - if (idRes.isSuccess()) return ParseRes.res(idRes.result, 1); - var strRes = parseString(null, tokens, i); - if (strRes.isSuccess()) return ParseRes.res(strRes.result.value, 1); - var numRes = parseNumber(null, tokens, i); - if (numRes.isSuccess()) return ParseRes.res(numRes.result.value, 1); + public static ParseRes parsePropName(Filename filename, List tokens, int i) { + var loc = getLoc(filename, tokens, i); - return ParseRes.failed(); + try { + 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(); + } } public static ParseRes parseObjectProp(Filename filename, List tokens, int i) { var loc = getLoc(filename, tokens, i); @@ -820,9 +820,9 @@ public class Parsing { int n = 0; if (!isOperator(tokens, i + n++, Operator.BRACE_OPEN)) return ParseRes.failed(); - var values = new LinkedHashMap(); - var getters = new LinkedHashMap(); - var setters = new LinkedHashMap(); + var values = new LinkedHashMap(); + var getters = new LinkedHashMap(); + var setters = new LinkedHashMap(); if (isOperator(tokens, i + n, Operator.BRACE_CLOSE)) { n++; @@ -994,7 +994,7 @@ public class Parsing { var res = parseValue(filename, tokens, n + i, 14); if (res.isSuccess()) return ParseRes.res(new OperationStatement(loc, operation, res.result), n + res.n); - else return ParseRes.error(loc, String.format("Expected a value after the unary operator '%s'.", op.value), res); + else return ParseRes.error(loc, String.format("Expected a value after the unary operator '%s'.", op.readable), res); } public static ParseRes parsePrefixChange(Filename filename, List tokens, int i) { var loc = getLoc(filename, tokens, i); @@ -1079,10 +1079,10 @@ public class Parsing { return ParseRes.res(new ConstantStatement(loc, false), 1); } if (id.result.equals("undefined")) { - return ParseRes.res(new ConstantStatement(loc, null), 1); + return ParseRes.res(ConstantStatement.ofUndefined(loc), 1); } if (id.result.equals("null")) { - return ParseRes.res(new ConstantStatement(loc, Values.NULL), 1); + return ParseRes.res(ConstantStatement.ofNull(loc), 1); } if (id.result.equals("this")) { return ParseRes.res(new VariableIndexStatement(loc, 0), 1); @@ -1141,7 +1141,7 @@ public class Parsing { } var res = parseValue(filename, tokens, i + n, 2); - if (!res.isSuccess()) return ParseRes.error(loc, String.format("Expected value after assignment operator '%s'.", op.value), res); + if (!res.isSuccess()) return ParseRes.error(loc, String.format("Expected value after assignment operator '%s'.", op.readable), res); n += res.n; Operation operation = null; @@ -1279,7 +1279,7 @@ public class Parsing { if (op.isAssign()) return parseAssign(filename, tokens, i + n - 1, prev, precedence); var res = parseValue(filename, tokens, i + n, op.precedence + (op.reverse ? 0 : 1)); - if (!res.isSuccess()) return ParseRes.error(loc, String.format("Expected a value after the '%s' operator.", op.value), res); + if (!res.isSuccess()) return ParseRes.error(loc, String.format("Expected a value after the '%s' operator.", op.readable), res); n += res.n; if (op == Operator.LAZY_AND) { @@ -1875,30 +1875,32 @@ public class Parsing { return list.toArray(Statement[]::new); } - public static CompileTarget compile(Environment environment, Statement ...statements) { - var subscope = new LocalScopeRecord(); - var target = new CompileTarget(new HashMap<>(), new TreeSet<>()); + public static CompileResult compile(Statement ...statements) { + var target = new CompileResult(new LocalScopeRecord()); var stm = new CompoundStatement(null, true, statements); - subscope.define("this"); - subscope.define("arguments"); + target.scope.define("this"); + target.scope.define("arguments"); try { - stm.compile(target, subscope, true); + stm.compile(target, true); FunctionStatement.checkBreakAndCont(target, 0); } catch (SyntaxException e) { - target.target.clear(); - target.add(Instruction.throwSyntax(e.loc, e)); + target = new CompileResult(new LocalScopeRecord()); + + target.scope.define("this"); + target.scope.define("arguments"); + + target.add(Instruction.throwSyntax(e)).setLocation(stm.loc()); } - target.add(Instruction.ret(stm.loc())); - target.functions.put(0l, new FunctionBody(subscope.localsCount(), 0, target.array(), subscope.captures(), subscope.locals())); + target.add(Instruction.ret()).setLocation(stm.loc()); return target; } - public static CompileTarget compile(Environment environment, Filename filename, String raw) { - try { return compile(environment, parse(filename, raw)); } - catch (SyntaxException e) { return compile(environment, new ThrowSyntaxStatement(e)); } + public static CompileResult compile(Filename filename, String raw) { + try { return compile(parse(filename, raw)); } + catch (SyntaxException e) { return compile(new ThrowSyntaxStatement(e)); } } } diff --git a/src/java/me/topchetoeu/jscript/core/parsing/RawToken.java b/src/java/me/topchetoeu/jscript/compilation/parsing/RawToken.java similarity index 86% rename from src/java/me/topchetoeu/jscript/core/parsing/RawToken.java rename to src/java/me/topchetoeu/jscript/compilation/parsing/RawToken.java index 0724910..e300d6b 100644 --- a/src/java/me/topchetoeu/jscript/core/parsing/RawToken.java +++ b/src/java/me/topchetoeu/jscript/compilation/parsing/RawToken.java @@ -1,4 +1,4 @@ -package me.topchetoeu.jscript.core.parsing; +package me.topchetoeu.jscript.compilation.parsing; public class RawToken { public final String value; diff --git a/src/java/me/topchetoeu/jscript/core/parsing/TestRes.java b/src/java/me/topchetoeu/jscript/compilation/parsing/TestRes.java similarity index 92% rename from src/java/me/topchetoeu/jscript/core/parsing/TestRes.java rename to src/java/me/topchetoeu/jscript/compilation/parsing/TestRes.java index 862e009..c399a9e 100644 --- a/src/java/me/topchetoeu/jscript/core/parsing/TestRes.java +++ b/src/java/me/topchetoeu/jscript/compilation/parsing/TestRes.java @@ -1,7 +1,7 @@ -package me.topchetoeu.jscript.core.parsing; +package me.topchetoeu.jscript.compilation.parsing; import me.topchetoeu.jscript.common.Location; -import me.topchetoeu.jscript.core.parsing.ParseRes.State; +import me.topchetoeu.jscript.compilation.parsing.ParseRes.State; public class TestRes { public final State state; diff --git a/src/java/me/topchetoeu/jscript/core/parsing/Token.java b/src/java/me/topchetoeu/jscript/compilation/parsing/Token.java similarity index 62% rename from src/java/me/topchetoeu/jscript/core/parsing/Token.java rename to src/java/me/topchetoeu/jscript/compilation/parsing/Token.java index af099ea..a3f4f0a 100644 --- a/src/java/me/topchetoeu/jscript/core/parsing/Token.java +++ b/src/java/me/topchetoeu/jscript/compilation/parsing/Token.java @@ -1,21 +1,24 @@ -package me.topchetoeu.jscript.core.parsing; +package me.topchetoeu.jscript.compilation.parsing; public class Token { public final Object value; + public final String rawValue; public final boolean isString; public final boolean isRegex; public final int line; public final int start; - private Token(int line, int start, Object value, boolean isString, boolean isRegex) { + private Token(int line, int start, Object value, String rawValue, boolean isString, boolean isRegex) { this.value = value; + this.rawValue = rawValue; this.line = line; this.start = start; this.isString = isString; this.isRegex = isRegex; } - private Token(int line, int start, Object value) { + private Token(int line, int start, Object value, String rawValue) { this.value = value; + this.rawValue = rawValue; this.line = line; this.start = start; this.isString = false; @@ -37,19 +40,19 @@ public class Token { public String identifier() { return (String)value; } public Operator operator() { return (Operator)value; } - public static Token regex(int line, int start, String val) { - return new Token(line, start, val, false, true); + public static Token regex(int line, int start, String val, String rawValue) { + return new Token(line, start, val, rawValue, false, true); } - public static Token string(int line, int start, String val) { - return new Token(line, start, val, true, false); + public static Token string(int line, int start, String val, String rawValue) { + return new Token(line, start, val, rawValue, true, false); } - public static Token number(int line, int start, double val) { - return new Token(line, start, val); + public static Token number(int line, int start, double val, String rawValue) { + return new Token(line, start, val, rawValue); } public static Token identifier(int line, int start, String val) { - return new Token(line, start, val); + return new Token(line, start, val, val); } public static Token operator(int line, int start, Operator val) { - return new Token(line, start, val); + return new Token(line, start, val, val.readable); } } \ No newline at end of file diff --git a/src/java/me/topchetoeu/jscript/core/parsing/TokenType.java b/src/java/me/topchetoeu/jscript/compilation/parsing/TokenType.java similarity index 61% rename from src/java/me/topchetoeu/jscript/core/parsing/TokenType.java rename to src/java/me/topchetoeu/jscript/compilation/parsing/TokenType.java index db7d067..a34e821 100644 --- a/src/java/me/topchetoeu/jscript/core/parsing/TokenType.java +++ b/src/java/me/topchetoeu/jscript/compilation/parsing/TokenType.java @@ -1,4 +1,4 @@ -package me.topchetoeu.jscript.core.parsing; +package me.topchetoeu.jscript.compilation.parsing; enum TokenType { REGEX, diff --git a/src/java/me/topchetoeu/jscript/compilation/values/ArrayStatement.java b/src/java/me/topchetoeu/jscript/compilation/values/ArrayStatement.java new file mode 100644 index 0000000..bc36644 --- /dev/null +++ b/src/java/me/topchetoeu/jscript/compilation/values/ArrayStatement.java @@ -0,0 +1,40 @@ +package me.topchetoeu.jscript.compilation.values; + +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 { + public final Statement[] statements; + + @Override public boolean pure() { + for (var stm : statements) { + if (!stm.pure()) return false; + } + + return true; + } + + @Override + public void compile(CompileResult target, boolean pollute) { + target.add(Instruction.loadArr(statements.length)); + + for (var i = 0; i < statements.length; i++) { + var el = statements[i]; + if (el != null) { + target.add(Instruction.dup()); + target.add(Instruction.pushValue(i)); + el.compile(target, true); + target.add(Instruction.storeMember()); + } + } + + if (!pollute) target.add(Instruction.discard()); + } + + public ArrayStatement(Location loc, Statement[] statements) { + super(loc); + this.statements = statements; + } +} diff --git a/src/java/me/topchetoeu/jscript/compilation/values/CallStatement.java b/src/java/me/topchetoeu/jscript/compilation/values/CallStatement.java new file mode 100644 index 0000000..38d44d6 --- /dev/null +++ b/src/java/me/topchetoeu/jscript/compilation/values/CallStatement.java @@ -0,0 +1,43 @@ +package me.topchetoeu.jscript.compilation.values; + +import me.topchetoeu.jscript.common.Location; +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; + public final Statement[] args; + public final boolean isNew; + + @Override + public void compile(CompileResult target, boolean pollute, BreakpointType type) { + if (isNew) func.compile(target, true); + else if (func instanceof IndexStatement) { + ((IndexStatement)func).compile(target, true, true); + } + else { + target.add(Instruction.pushUndefined()); + func.compile(target, true); + } + + 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 (!pollute) target.add(Instruction.discard()); + } + @Override + public void compile(CompileResult target, boolean pollute) { + compile(target, pollute, BreakpointType.STEP_IN); + } + + public CallStatement(Location loc, boolean isNew, Statement func, Statement ...args) { + super(loc); + this.isNew = isNew; + this.func = func; + this.args = args; + } +} diff --git a/src/java/me/topchetoeu/jscript/compilation/values/ChangeStatement.java b/src/java/me/topchetoeu/jscript/compilation/values/ChangeStatement.java new file mode 100644 index 0000000..91fc07b --- /dev/null +++ b/src/java/me/topchetoeu/jscript/compilation/values/ChangeStatement.java @@ -0,0 +1,31 @@ +package me.topchetoeu.jscript.compilation.values; + +import me.topchetoeu.jscript.common.Location; +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; + public final double addAmount; + public final boolean postfix; + + @Override + public void compile(CompileResult target, boolean pollute) { + value.toAssign(new ConstantStatement(loc(), -addAmount), Operation.SUBTRACT).compile(target, true); + if (!pollute) target.add(Instruction.discard()); + else if (postfix) { + target.add(Instruction.pushValue(addAmount)); + target.add(Instruction.operation(Operation.SUBTRACT)); + } + } + + public ChangeStatement(Location loc, AssignableStatement value, double addAmount, boolean postfix) { + super(loc); + this.value = value; + this.addAmount = addAmount; + this.postfix = postfix; + } +} diff --git a/src/java/me/topchetoeu/jscript/compilation/values/ConstantStatement.java b/src/java/me/topchetoeu/jscript/compilation/values/ConstantStatement.java new file mode 100644 index 0000000..3470329 --- /dev/null +++ b/src/java/me/topchetoeu/jscript/compilation/values/ConstantStatement.java @@ -0,0 +1,47 @@ +package me.topchetoeu.jscript.compilation.values; + +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 { + public final Object value; + public final boolean isNull; + + @Override public boolean pure() { return true; } + + @Override + public void compile(CompileResult target, boolean pollute) { + if (pollute) { + if (isNull) target.add(Instruction.pushNull()); + else if (value instanceof Double) target.add(Instruction.pushValue((Double)value)); + else if (value instanceof String) target.add(Instruction.pushValue((String)value)); + else if (value instanceof Boolean) target.add(Instruction.pushValue((Boolean)value)); + else target.add(Instruction.pushUndefined()); + } + } + + private ConstantStatement(Location loc, Object val, boolean isNull) { + super(loc); + this.value = val; + this.isNull = isNull; + } + + public ConstantStatement(Location loc, boolean val) { + this(loc, val, false); + } + public ConstantStatement(Location loc, String val) { + this(loc, val, false); + } + public ConstantStatement(Location loc, double val) { + this(loc, val, false); + } + + public static ConstantStatement ofUndefined(Location loc) { + return new ConstantStatement(loc, null, false); + } + public static ConstantStatement ofNull(Location loc) { + return new ConstantStatement(loc, null, true); + } +} diff --git a/src/java/me/topchetoeu/jscript/compilation/values/DiscardStatement.java b/src/java/me/topchetoeu/jscript/compilation/values/DiscardStatement.java new file mode 100644 index 0000000..3e9650c --- /dev/null +++ b/src/java/me/topchetoeu/jscript/compilation/values/DiscardStatement.java @@ -0,0 +1,23 @@ +package me.topchetoeu.jscript.compilation.values; + +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 { + public final Statement value; + + @Override public boolean pure() { return value.pure(); } + + @Override + public void compile(CompileResult target, boolean pollute) { + value.compile(target, false); + if (pollute) target.add(Instruction.pushUndefined()); + } + + public DiscardStatement(Location loc, Statement val) { + super(loc); + this.value = val; + } +} diff --git a/src/java/me/topchetoeu/jscript/compilation/values/FunctionStatement.java b/src/java/me/topchetoeu/jscript/compilation/values/FunctionStatement.java new file mode 100644 index 0000000..e084c5e --- /dev/null +++ b/src/java/me/topchetoeu/jscript/compilation/values/FunctionStatement.java @@ -0,0 +1,127 @@ +package me.topchetoeu.jscript.compilation.values; + +import me.topchetoeu.jscript.common.Location; +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 { + public final CompoundStatement body; + public final String varName; + public final String[] args; + public final boolean statement; + public final Location end; + + @Override public boolean pure() { return varName == null && statement; } + + @Override + public void declare(CompileResult target) { + if (varName != null && statement) target.scope.define(varName); + } + + public static void checkBreakAndCont(CompileResult target, int start) { + for (int i = start; i < target.size(); i++) { + if (target.get(i).type == Type.NOP) { + if (target.get(i).is(0, "break") ) { + throw new SyntaxException(target.map.toLocation(i), "Break was placed outside a loop."); + } + if (target.get(i).is(0, "cont")) { + throw new SyntaxException(target.map.toLocation(i), "Continue was placed outside a loop."); + } + } + } + } + + private CompileResult compileBody(CompileResult target, boolean pollute, BreakpointType bp) { + for (var i = 0; i < args.length; i++) { + for (var j = 0; j < i; j++) { + if (args[i].equals(args[j])) { + throw new SyntaxException(loc(), "Duplicate parameter '" + args[i] + "'."); + } + } + } + + var subtarget = new CompileResult(target.scope.child()); + + subtarget.scope.define("this"); + var argsVar = subtarget.scope.define("arguments"); + + if (args.length > 0) { + for (var i = 0; i < args.length; i++) { + subtarget.add(Instruction.loadVar(argsVar)); + subtarget.add(Instruction.pushValue(i)); + subtarget.add(Instruction.loadMember()); + subtarget.add(Instruction.storeVar(subtarget.scope.define(args[i]))); + } + } + + if (!statement && this.varName != null) { + subtarget.add(Instruction.storeSelfFunc((int)subtarget.scope.define(this.varName))).setLocationAndDebug(loc(), bp); + } + + body.declare(subtarget); + body.compile(subtarget, false); + subtarget.length = args.length; + subtarget.add(Instruction.ret()).setLocation(end); + checkBreakAndCont(subtarget, 0); + + if (pollute) target.add(Instruction.loadFunc(target.children.size(), subtarget.scope.getCaptures())); + return target.addChild(subtarget); + } + + public void compile(CompileResult target, boolean pollute, String name, BreakpointType bp) { + if (this.varName != null) name = this.varName; + + var hasVar = this.varName != null && statement; + var hasName = name != null; + + compileBody(target, pollute || hasVar || hasName, bp); + + if (hasName) { + if (pollute || hasVar) target.add(Instruction.dup()); + target.add(Instruction.pushValue("name")); + target.add(Instruction.pushValue(name)); + target.add(Instruction.storeMember()); + } + + if (hasVar) { + var key = target.scope.getKey(this.varName); + + if (key instanceof String) target.add(Instruction.makeVar((String)key)); + target.add(Instruction.storeVar(target.scope.getKey(this.varName), false)); + } + } + public void compile(CompileResult target, boolean pollute, String name) { + compile(target, pollute, name, BreakpointType.NONE); + } + @Override public void compile(CompileResult target, boolean pollute, BreakpointType bp) { + compile(target, pollute, (String)null, bp); + } + @Override public void compile(CompileResult target, boolean pollute) { + compile(target, pollute, (String)null, BreakpointType.NONE); + } + + public FunctionStatement(Location loc, Location end, String varName, String[] args, boolean statement, CompoundStatement body) { + super(loc); + + this.end = end; + this.varName = varName; + this.statement = statement; + + this.args = args; + this.body = body; + } + + public static void compileWithName(Statement stm, CompileResult target, boolean pollute, String name) { + if (stm instanceof FunctionStatement) ((FunctionStatement)stm).compile(target, pollute, name); + else stm.compile(target, pollute); + } + public static void compileWithName(Statement stm, CompileResult target, boolean pollute, String name, BreakpointType bp) { + if (stm instanceof FunctionStatement) ((FunctionStatement)stm).compile(target, pollute, name, bp); + else stm.compile(target, pollute, bp); + } +} diff --git a/src/java/me/topchetoeu/jscript/compilation/values/GlobalThisStatement.java b/src/java/me/topchetoeu/jscript/compilation/values/GlobalThisStatement.java new file mode 100644 index 0000000..1e9b2b4 --- /dev/null +++ b/src/java/me/topchetoeu/jscript/compilation/values/GlobalThisStatement.java @@ -0,0 +1,19 @@ +package me.topchetoeu.jscript.compilation.values; + +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 { + @Override public boolean pure() { return true; } + + @Override + public void compile(CompileResult target, boolean pollute) { + if (pollute) target.add(Instruction.loadGlob()); + } + + public GlobalThisStatement(Location loc) { + super(loc); + } +} diff --git a/src/java/me/topchetoeu/jscript/compilation/values/IndexAssignStatement.java b/src/java/me/topchetoeu/jscript/compilation/values/IndexAssignStatement.java new file mode 100644 index 0000000..4e9b92f --- /dev/null +++ b/src/java/me/topchetoeu/jscript/compilation/values/IndexAssignStatement.java @@ -0,0 +1,45 @@ +package me.topchetoeu.jscript.compilation.values; + +import me.topchetoeu.jscript.common.Location; +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; + public final Statement index; + public final Statement value; + public final Operation operation; + + @Override + public void compile(CompileResult target, boolean pollute) { + if (operation != null) { + object.compile(target, true); + index.compile(target, true); + target.add(Instruction.dup(2)); + + target.add(Instruction.loadMember()); + value.compile(target, true); + target.add(Instruction.operation(operation)); + + target.add(Instruction.storeMember(pollute)).setLocationAndDebug(loc(), BreakpointType.STEP_IN); + } + else { + object.compile(target, true); + index.compile(target, true); + value.compile(target, true); + + target.add(Instruction.storeMember(pollute)).setLocationAndDebug(loc(), BreakpointType.STEP_IN);; + } + } + + public IndexAssignStatement(Location loc, Statement object, Statement index, Statement value, Operation operation) { + super(loc); + this.object = object; + this.index = index; + this.value = value; + this.operation = operation; + } +} diff --git a/src/java/me/topchetoeu/jscript/compilation/values/IndexStatement.java b/src/java/me/topchetoeu/jscript/compilation/values/IndexStatement.java new file mode 100644 index 0000000..f7d2a31 --- /dev/null +++ b/src/java/me/topchetoeu/jscript/compilation/values/IndexStatement.java @@ -0,0 +1,37 @@ +package me.topchetoeu.jscript.compilation.values; + +import me.topchetoeu.jscript.common.Location; +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; + public final Statement index; + + @Override + public Statement toAssign(Statement val, Operation operation) { + return new IndexAssignStatement(loc(), object, index, val, operation); + } + public void compile(CompileResult target, boolean dupObj, boolean pollute) { + object.compile(target, true); + if (dupObj) target.add(Instruction.dup()); + + index.compile(target, true); + target.add(Instruction.loadMember()).setLocationAndDebug(loc(), BreakpointType.STEP_IN); + if (!pollute) target.add(Instruction.discard()); + } + @Override + public void compile(CompileResult target, boolean pollute) { + compile(target, false, pollute); + } + + public IndexStatement(Location loc, Statement object, Statement index) { + super(loc); + this.object = object; + this.index = index; + } +} diff --git a/src/java/me/topchetoeu/jscript/compilation/values/LazyAndStatement.java b/src/java/me/topchetoeu/jscript/compilation/values/LazyAndStatement.java new file mode 100644 index 0000000..8cf8813 --- /dev/null +++ b/src/java/me/topchetoeu/jscript/compilation/values/LazyAndStatement.java @@ -0,0 +1,28 @@ +package me.topchetoeu.jscript.compilation.values; + +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 { + public final Statement first, second; + + @Override public boolean pure() { return first.pure() && second.pure(); } + + @Override + public void compile(CompileResult target, boolean pollute) { + first.compile(target, true); + if (pollute) target.add(Instruction.dup()); + int start = target.temp(); + if (pollute) target.add(Instruction.discard()); + second.compile(target, pollute); + target.set(start, Instruction.jmpIfNot(target.size() - start)); + } + + public LazyAndStatement(Location loc, Statement first, Statement second) { + super(loc); + this.first = first; + this.second = second; + } +} diff --git a/src/java/me/topchetoeu/jscript/compilation/values/LazyOrStatement.java b/src/java/me/topchetoeu/jscript/compilation/values/LazyOrStatement.java new file mode 100644 index 0000000..7307edb --- /dev/null +++ b/src/java/me/topchetoeu/jscript/compilation/values/LazyOrStatement.java @@ -0,0 +1,28 @@ +package me.topchetoeu.jscript.compilation.values; + +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 { + public final Statement first, second; + + @Override public boolean pure() { return first.pure() && second.pure(); } + + @Override + public void compile(CompileResult target, boolean pollute) { + first.compile(target, true); + if (pollute) target.add(Instruction.dup()); + int start = target.temp(); + if (pollute) target.add(Instruction.discard()); + second.compile(target, pollute); + target.set(start, Instruction.jmpIf(target.size() - start)); + } + + public LazyOrStatement(Location loc, Statement first, Statement second) { + super(loc); + this.first = first; + this.second = second; + } +} diff --git a/src/java/me/topchetoeu/jscript/compilation/values/ObjectStatement.java b/src/java/me/topchetoeu/jscript/compilation/values/ObjectStatement.java new file mode 100644 index 0000000..1c46766 --- /dev/null +++ b/src/java/me/topchetoeu/jscript/compilation/values/ObjectStatement.java @@ -0,0 +1,61 @@ +package me.topchetoeu.jscript.compilation.values; + +import java.util.ArrayList; +import java.util.Map; + +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 { + public final Map map; + public final Map getters; + public final Map setters; + + @Override public boolean pure() { + for (var el : map.values()) { + if (!el.pure()) return false; + } + + return true; + } + + @Override + public void compile(CompileResult target, boolean pollute) { + target.add(Instruction.loadObj()); + + for (var el : map.entrySet()) { + target.add(Instruction.dup()); + target.add(Instruction.pushValue(el.getKey())); + var val = el.getValue(); + FunctionStatement.compileWithName(val, target, true, el.getKey().toString()); + target.add(Instruction.storeMember()); + } + + var keys = new ArrayList(); + keys.addAll(getters.keySet()); + keys.addAll(setters.keySet()); + + for (var key : keys) { + target.add(Instruction.pushValue((String)key)); + + if (getters.containsKey(key)) getters.get(key).compile(target, true); + else target.add(Instruction.pushUndefined()); + + if (setters.containsKey(key)) setters.get(key).compile(target, true); + else target.add(Instruction.pushUndefined()); + + target.add(Instruction.defProp()); + } + + if (!pollute) target.add(Instruction.discard()); + } + + public ObjectStatement(Location loc, Map map, Map getters, Map setters) { + super(loc); + this.map = map; + this.getters = getters; + this.setters = setters; + } +} diff --git a/src/java/me/topchetoeu/jscript/compilation/values/OperationStatement.java b/src/java/me/topchetoeu/jscript/compilation/values/OperationStatement.java new file mode 100644 index 0000000..7e90a5e --- /dev/null +++ b/src/java/me/topchetoeu/jscript/compilation/values/OperationStatement.java @@ -0,0 +1,36 @@ +package me.topchetoeu.jscript.compilation.values; + +import me.topchetoeu.jscript.common.Location; +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; + public final Operation operation; + + @Override public boolean pure() { + for (var el : args) { + if (!el.pure()) return false; + } + + return true; + } + + @Override + public void compile(CompileResult target, boolean pollute) { + for (var arg : args) { + arg.compile(target, true); + } + + if (pollute) target.add(Instruction.operation(operation)); + else target.add(Instruction.discard()); + } + + public OperationStatement(Location loc, Operation operation, Statement ...args) { + super(loc); + this.operation = operation; + this.args = args; + } +} diff --git a/src/java/me/topchetoeu/jscript/compilation/values/RegexStatement.java b/src/java/me/topchetoeu/jscript/compilation/values/RegexStatement.java new file mode 100644 index 0000000..b8b4bf2 --- /dev/null +++ b/src/java/me/topchetoeu/jscript/compilation/values/RegexStatement.java @@ -0,0 +1,25 @@ +package me.topchetoeu.jscript.compilation.values; + +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 { + public final String pattern, flags; + + // Not really pure, since a function is called, but can be ignored. + @Override public boolean pure() { return true; } + + @Override + public void compile(CompileResult target, boolean pollute) { + target.add(Instruction.loadRegex(pattern, flags)); + if (!pollute) target.add(Instruction.discard()); + } + + public RegexStatement(Location loc, String pattern, String flags) { + super(loc); + this.pattern = pattern; + this.flags = flags; + } +} diff --git a/src/java/me/topchetoeu/jscript/core/compilation/values/TypeofStatement.java b/src/java/me/topchetoeu/jscript/compilation/values/TypeofStatement.java similarity index 50% rename from src/java/me/topchetoeu/jscript/core/compilation/values/TypeofStatement.java rename to src/java/me/topchetoeu/jscript/compilation/values/TypeofStatement.java index 4cd33c0..1abbf20 100644 --- a/src/java/me/topchetoeu/jscript/core/compilation/values/TypeofStatement.java +++ b/src/java/me/topchetoeu/jscript/compilation/values/TypeofStatement.java @@ -1,10 +1,9 @@ -package me.topchetoeu.jscript.core.compilation.values; +package me.topchetoeu.jscript.compilation.values; import me.topchetoeu.jscript.common.Location; -import me.topchetoeu.jscript.core.compilation.CompileTarget; -import me.topchetoeu.jscript.core.compilation.Instruction; -import me.topchetoeu.jscript.core.compilation.Statement; -import me.topchetoeu.jscript.core.engine.scope.ScopeRecord; +import me.topchetoeu.jscript.compilation.CompileResult; +import me.topchetoeu.jscript.compilation.Instruction; +import me.topchetoeu.jscript.compilation.Statement; public class TypeofStatement extends Statement { public final Statement value; @@ -14,16 +13,16 @@ public class TypeofStatement extends Statement { @Override public boolean pure() { return true; } @Override - public void compile(CompileTarget target, ScopeRecord scope, boolean pollute) { + public void compile(CompileResult target, boolean pollute) { if (value instanceof VariableStatement) { - var i = scope.getKey(((VariableStatement)value).name); + var i = target.scope.getKey(((VariableStatement)value).name); if (i instanceof String) { - target.add(Instruction.typeof(loc(), (String)i)); + target.add(Instruction.typeof((String)i)); return; } } - value.compile(target, scope, pollute); - target.add(Instruction.typeof(loc())); + value.compile(target, pollute); + target.add(Instruction.typeof()); } public TypeofStatement(Location loc, Statement value) { diff --git a/src/java/me/topchetoeu/jscript/compilation/values/VariableAssignStatement.java b/src/java/me/topchetoeu/jscript/compilation/values/VariableAssignStatement.java new file mode 100644 index 0000000..6445990 --- /dev/null +++ b/src/java/me/topchetoeu/jscript/compilation/values/VariableAssignStatement.java @@ -0,0 +1,37 @@ +package me.topchetoeu.jscript.compilation.values; + +import me.topchetoeu.jscript.common.Location; +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; + public final Statement value; + public final Operation operation; + + @Override public boolean pure() { return false; } + + @Override + public void compile(CompileResult target, boolean pollute) { + var i = target.scope.getKey(name); + if (operation != null) { + target.add(Instruction.loadVar(i)); + FunctionStatement.compileWithName(value, target, true, name); + target.add(Instruction.operation(operation)); + target.add(Instruction.storeVar(i, pollute)); + } + else { + FunctionStatement.compileWithName(value, target, true, name); + target.add(Instruction.storeVar(i, pollute)); + } + } + + public VariableAssignStatement(Location loc, String name, Statement val, Operation operation) { + super(loc); + this.name = name; + this.value = val; + this.operation = operation; + } +} diff --git a/src/java/me/topchetoeu/jscript/compilation/values/VariableIndexStatement.java b/src/java/me/topchetoeu/jscript/compilation/values/VariableIndexStatement.java new file mode 100644 index 0000000..0c8dbb4 --- /dev/null +++ b/src/java/me/topchetoeu/jscript/compilation/values/VariableIndexStatement.java @@ -0,0 +1,22 @@ +package me.topchetoeu.jscript.compilation.values; + +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 { + public final int index; + + @Override public boolean pure() { return true; } + + @Override + public void compile(CompileResult target, boolean pollute) { + if (pollute) target.add(Instruction.loadVar(index)); + } + + public VariableIndexStatement(Location loc, int i) { + super(loc); + this.index = i; + } +} diff --git a/src/java/me/topchetoeu/jscript/compilation/values/VariableStatement.java b/src/java/me/topchetoeu/jscript/compilation/values/VariableStatement.java new file mode 100644 index 0000000..d251f9a --- /dev/null +++ b/src/java/me/topchetoeu/jscript/compilation/values/VariableStatement.java @@ -0,0 +1,31 @@ +package me.topchetoeu.jscript.compilation.values; + +import me.topchetoeu.jscript.common.Location; +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; + + @Override public boolean pure() { return false; } + + @Override + public Statement toAssign(Statement val, Operation operation) { + return new VariableAssignStatement(loc(), name, val, operation); + } + + @Override + public void compile(CompileResult target, boolean pollute) { + var i = target.scope.getKey(name); + target.add(Instruction.loadVar(i)); + if (!pollute) target.add(Instruction.discard()); + } + + public VariableStatement(Location loc, String name) { + super(loc); + this.name = name; + } +} diff --git a/src/java/me/topchetoeu/jscript/core/Compiler.java b/src/java/me/topchetoeu/jscript/core/Compiler.java new file mode 100644 index 0000000..c929a28 --- /dev/null +++ b/src/java/me/topchetoeu/jscript/core/Compiler.java @@ -0,0 +1,8 @@ +package me.topchetoeu.jscript.core; + +import me.topchetoeu.jscript.common.Filename; +import me.topchetoeu.jscript.compilation.FunctionBody; + +public interface Compiler { + public FunctionBody compile(Filename filename, String source); +} diff --git a/src/java/me/topchetoeu/jscript/core/engine/Context.java b/src/java/me/topchetoeu/jscript/core/Context.java similarity index 53% rename from src/java/me/topchetoeu/jscript/core/engine/Context.java rename to src/java/me/topchetoeu/jscript/core/Context.java index 59604d3..16f31a6 100644 --- a/src/java/me/topchetoeu/jscript/core/engine/Context.java +++ b/src/java/me/topchetoeu/jscript/core/Context.java @@ -1,32 +1,23 @@ -package me.topchetoeu.jscript.core.engine; +package me.topchetoeu.jscript.core; -import java.util.ArrayList; -import java.util.Arrays; import java.util.Iterator; import java.util.List; -import java.util.TreeSet; -import java.util.stream.Collectors; import java.util.stream.Stream; import java.util.stream.StreamSupport; import me.topchetoeu.jscript.common.Filename; -import me.topchetoeu.jscript.common.Location; -import me.topchetoeu.jscript.core.engine.debug.DebugContext; -import me.topchetoeu.jscript.core.engine.frame.CodeFrame; -import me.topchetoeu.jscript.core.engine.values.ArrayValue; -import me.topchetoeu.jscript.core.engine.values.FunctionValue; -import me.topchetoeu.jscript.core.engine.values.Symbol; -import me.topchetoeu.jscript.core.engine.values.Values; +import me.topchetoeu.jscript.core.debug.DebugContext; +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.utils.mapping.SourceMap; public class Context implements Extensions { public static final Context NULL = new Context(null); public final Context parent; public final Environment environment; - public final CodeFrame frame; + public final Frame frame; public final Engine engine; public final int stackSize; @@ -67,43 +58,39 @@ public class Context implements Extensions { var env = environment; var result = Environment.compileFunc(this).call(this, null, raw, filename.toString(), new EnvironmentLib(env)); - var function = (FunctionValue)Values.getMember(this, result, "function"); - if (!DebugContext.enabled(this)) return function; + 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]; + // 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])); + // for (var i = 0; i < maps.length; i++) maps[i] = SourceMap.parse(Values.toString(this, (String)rawMapChain[i])); - var map = SourceMap.chain(maps); + // 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; - } - - DebugContext.get(this).onSource(filename, raw, breakpoints, map); - - return function; + // if (map != null) { + // var newBreakpoints = new TreeSet(); + // for (var bp : breakpoints) { + // bp = map.toCompiled(bp); + // if (bp != null) newBreakpoints.add(bp); + // } + // breakpoints = newBreakpoints; + // } } - public Context pushFrame(CodeFrame frame) { + public Context pushFrame(Frame frame) { var res = new Context(this, frame.function.environment, frame, engine, stackSize + 1); return res; } - public Iterable frames() { + public Iterable frames() { var self = this; - return () -> new Iterator() { + return () -> new Iterator() { private Context curr = self; private void update() { @@ -114,7 +101,7 @@ public class Context implements Extensions { update(); return curr != null; } - @Override public CodeFrame next() { + @Override public Frame next() { update(); var res = curr.frame; curr = curr.parent; @@ -122,30 +109,9 @@ public class Context implements Extensions { } }; } - public List stackTrace() { - var res = new ArrayList(); - for (var el : frames()) { - var name = el.function.name; - Location loc = null; - for (var j = el.codePtr; j >= 0 && loc == null; j--) loc = el.function.body[j].location; - if (loc == null) loc = el.function.loc(); - - var trace = ""; - - if (loc != null) trace += "at " + loc.toString() + " "; - if (name != null && !name.equals("")) trace += "in " + name + " "; - - trace = trace.trim(); - - if (!trace.equals("")) res.add(trace); - } - - return res; - } - - private Context(Context parent, Environment environment, CodeFrame frame, Engine engine, int stackSize) { + private Context(Context parent, Environment environment, Frame frame, Engine engine, int stackSize) { this.parent = parent; this.environment = environment; this.frame = frame; diff --git a/src/java/me/topchetoeu/jscript/core/engine/Engine.java b/src/java/me/topchetoeu/jscript/core/Engine.java similarity index 64% rename from src/java/me/topchetoeu/jscript/core/engine/Engine.java rename to src/java/me/topchetoeu/jscript/core/Engine.java index a5250aa..59d493e 100644 --- a/src/java/me/topchetoeu/jscript/core/engine/Engine.java +++ b/src/java/me/topchetoeu/jscript/core/Engine.java @@ -1,15 +1,15 @@ -package me.topchetoeu.jscript.core.engine; +package me.topchetoeu.jscript.core; import java.util.HashMap; import me.topchetoeu.jscript.common.Filename; -import me.topchetoeu.jscript.common.events.Awaitable; -import me.topchetoeu.jscript.core.compilation.FunctionBody; -import me.topchetoeu.jscript.core.engine.values.FunctionValue; -import me.topchetoeu.jscript.core.engine.values.Symbol; +import me.topchetoeu.jscript.common.events.DataNotifier; +import me.topchetoeu.jscript.compilation.FunctionBody; +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 static final HashMap functions = new HashMap<>(); private final Environment env = new Environment(); @@ -40,12 +40,12 @@ public class Engine extends EventLoop implements Extensions { return res; } - public Awaitable pushMsg(boolean micro, Environment env, FunctionValue func, Object thisArg, Object ...args) { + public DataNotifier pushMsg(boolean micro, Environment env, FunctionValue func, Object thisArg, Object ...args) { return pushMsg(() -> { return func.call(new Context(this, env), thisArg, args); }, micro); } - public Awaitable pushMsg(boolean micro, Environment env, Filename filename, String raw, Object thisArg, Object ...args) { + 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); diff --git a/src/java/me/topchetoeu/jscript/core/engine/Environment.java b/src/java/me/topchetoeu/jscript/core/Environment.java similarity index 67% rename from src/java/me/topchetoeu/jscript/core/engine/Environment.java rename to src/java/me/topchetoeu/jscript/core/Environment.java index 894ae12..eca0741 100644 --- a/src/java/me/topchetoeu/jscript/core/engine/Environment.java +++ b/src/java/me/topchetoeu/jscript/core/Environment.java @@ -1,20 +1,12 @@ -package me.topchetoeu.jscript.core.engine; +package me.topchetoeu.jscript.core; import java.util.HashMap; -import java.util.stream.Collectors; -import me.topchetoeu.jscript.common.Filename; -import me.topchetoeu.jscript.common.Location; -import me.topchetoeu.jscript.core.engine.debug.DebugContext; -import me.topchetoeu.jscript.core.engine.scope.GlobalScope; -import me.topchetoeu.jscript.core.engine.values.ArrayValue; -import me.topchetoeu.jscript.core.engine.values.FunctionValue; -import me.topchetoeu.jscript.core.engine.values.NativeFunction; -import me.topchetoeu.jscript.core.engine.values.ObjectValue; -import me.topchetoeu.jscript.core.engine.values.Symbol; -import me.topchetoeu.jscript.core.engine.values.Values; +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.exceptions.EngineException; -import me.topchetoeu.jscript.core.parsing.Parsing; import me.topchetoeu.jscript.utils.interop.NativeWrapperProvider; @SuppressWarnings("unchecked") @@ -22,7 +14,6 @@ public class Environment implements Extensions { public static final HashMap symbols = new HashMap<>(); - public static final Symbol WRAPPERS = Symbol.get("Environment.wrappers"); public static final Symbol COMPILE_FUNC = Symbol.get("Environment.compile"); public static final Symbol REGEX_CONSTR = Symbol.get("Environment.regexConstructor"); @@ -69,30 +60,23 @@ public class Environment implements Extensions { 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 env = Values.wrapper(Values.getMember(args.ctx, args.get(2), Symbol.get("env")), Environment.class); - var isDebug = DebugContext.enabled(args.ctx); - var res = new ObjectValue(); + // var source = args.getString(0); + // var filename = args.getString(1); - var target = Parsing.compile(env, Filename.parse(filename), source); - Engine.functions.putAll(target.functions); - Engine.functions.remove(0l); + // var target = Parsing.compile(Filename.parse(filename), source); + // var res = new ObjectValue(); - res.defineProperty(args.ctx, "function", target.func(env)); - res.defineProperty(args.ctx, "mapChain", new ArrayValue()); + // res.defineProperty(args.ctx, "function", target.body()); + // res.defineProperty(args.ctx, "map", target.map()); - if (isDebug) res.defineProperty( - args.ctx, "breakpoints", - ArrayValue.of(args.ctx, target.breakpoints.stream().map(Location::toString).collect(Collectors.toList())) - ); + // return res; - 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 -> { - throw EngineException.ofError("Regular expressions not supported.").setCtx(args.ctx.environment, args.ctx.engine); + throw EngineException.ofError("Regular expressions not supported.").setCtx(args.ctx); })); } diff --git a/src/java/me/topchetoeu/jscript/core/engine/EventLoop.java b/src/java/me/topchetoeu/jscript/core/EventLoop.java similarity index 88% rename from src/java/me/topchetoeu/jscript/core/engine/EventLoop.java rename to src/java/me/topchetoeu/jscript/core/EventLoop.java index dfc5334..4d9b7f1 100644 --- a/src/java/me/topchetoeu/jscript/core/engine/EventLoop.java +++ b/src/java/me/topchetoeu/jscript/core/EventLoop.java @@ -1,9 +1,8 @@ -package me.topchetoeu.jscript.core.engine; +package me.topchetoeu.jscript.core; import java.util.concurrent.PriorityBlockingQueue; import me.topchetoeu.jscript.common.ResultRunnable; -import me.topchetoeu.jscript.common.events.Awaitable; import me.topchetoeu.jscript.common.events.DataNotifier; import me.topchetoeu.jscript.core.exceptions.InterruptException; @@ -28,12 +27,12 @@ public class EventLoop { private Thread thread; @SuppressWarnings("unchecked") - public Awaitable pushMsg(ResultRunnable runnable, boolean micro) { + public DataNotifier pushMsg(ResultRunnable runnable, boolean micro) { var msg = new Task(runnable, micro); tasks.add(msg); - return (Awaitable)msg.notifier; + return (DataNotifier)msg.notifier; } - public Awaitable pushMsg(Runnable runnable, boolean micro) { + public DataNotifier pushMsg(Runnable runnable, boolean micro) { return pushMsg(() -> { runnable.run(); return null; }, micro); } diff --git a/src/java/me/topchetoeu/jscript/core/engine/Extensions.java b/src/java/me/topchetoeu/jscript/core/Extensions.java similarity index 87% rename from src/java/me/topchetoeu/jscript/core/engine/Extensions.java rename to src/java/me/topchetoeu/jscript/core/Extensions.java index 9dd8b69..682ecca 100644 --- a/src/java/me/topchetoeu/jscript/core/engine/Extensions.java +++ b/src/java/me/topchetoeu/jscript/core/Extensions.java @@ -1,6 +1,6 @@ -package me.topchetoeu.jscript.core.engine; +package me.topchetoeu.jscript.core; -import me.topchetoeu.jscript.core.engine.values.Symbol; +import me.topchetoeu.jscript.core.values.Symbol; public interface Extensions { T get(Symbol key); diff --git a/src/java/me/topchetoeu/jscript/core/engine/frame/CodeFrame.java b/src/java/me/topchetoeu/jscript/core/Frame.java similarity index 88% rename from src/java/me/topchetoeu/jscript/core/engine/frame/CodeFrame.java rename to src/java/me/topchetoeu/jscript/core/Frame.java index 0f82537..e8483cc 100644 --- a/src/java/me/topchetoeu/jscript/core/engine/frame/CodeFrame.java +++ b/src/java/me/topchetoeu/jscript/core/Frame.java @@ -1,23 +1,21 @@ -package me.topchetoeu.jscript.core.engine.frame; +package me.topchetoeu.jscript.core; import java.util.List; import java.util.Stack; -import me.topchetoeu.jscript.common.Location; -import me.topchetoeu.jscript.core.compilation.Instruction; -import me.topchetoeu.jscript.core.engine.Context; -import me.topchetoeu.jscript.core.engine.debug.DebugContext; -import me.topchetoeu.jscript.core.engine.scope.LocalScope; -import me.topchetoeu.jscript.core.engine.scope.ValueVariable; -import me.topchetoeu.jscript.core.engine.values.ArrayValue; -import me.topchetoeu.jscript.core.engine.values.CodeFunction; -import me.topchetoeu.jscript.core.engine.values.ObjectValue; -import me.topchetoeu.jscript.core.engine.values.ScopeValue; -import me.topchetoeu.jscript.core.engine.values.Values; +import me.topchetoeu.jscript.compilation.Instruction; +import me.topchetoeu.jscript.core.debug.DebugContext; +import me.topchetoeu.jscript.core.scope.LocalScope; +import me.topchetoeu.jscript.core.scope.ValueVariable; +import me.topchetoeu.jscript.core.values.ArrayValue; +import me.topchetoeu.jscript.core.values.CodeFunction; +import me.topchetoeu.jscript.core.values.ObjectValue; +import me.topchetoeu.jscript.core.values.ScopeValue; +import me.topchetoeu.jscript.core.values.Values; import me.topchetoeu.jscript.core.exceptions.EngineException; import me.topchetoeu.jscript.core.exceptions.InterruptException; -public class CodeFrame { +public class Frame { public static enum TryState { TRY, CATCH, @@ -101,54 +99,6 @@ public class CodeFrame { public int stackPtr = 0; public int codePtr = 0; public boolean jumpFlag = false, popTryFlag = false; - private Location prevLoc = null; - - public ObjectValue getLocalScope(boolean props) { - var names = new String[scope.locals.length]; - - for (int i = 0; i < scope.locals.length; i++) { - var name = "local_" + (i - 2); - - if (i == 0) name = "this"; - else if (i == 1) name = "arguments"; - else if (i < function.localNames.length) name = function.localNames[i]; - - names[i] = name; - } - - return new ScopeValue(scope.locals, names); - } - public ObjectValue getCaptureScope(boolean props) { - var names = new String[scope.captures.length]; - - for (int i = 0; i < scope.captures.length; i++) { - var name = "capture_" + (i - 2); - if (i < function.captureNames.length) name = function.captureNames[i]; - names[i] = name; - } - - return new ScopeValue(scope.captures, names); - } - public ObjectValue getValStackScope() { - return new ObjectValue() { - @Override - protected Object getField(Context ctx, Object key) { - var i = (int)Values.toNumber(ctx, key); - if (i < 0 || i >= stackPtr) return null; - else return stack[i]; - } - @Override - protected boolean hasField(Context ctx, Object key) { - return true; - } - @Override - public List keys(boolean includeNonEnumerable) { - var res = super.keys(includeNonEnumerable); - for (var i = 0; i < stackPtr; i++) res.add(i); - return res; - } - }; - } public void addTry(int start, int end, int catchStart, int finallyStart) { var err = tryStack.empty() ? null : tryStack.peek().error; @@ -194,7 +144,7 @@ public class CodeFrame { if (value != Values.NO_RETURN) push(value); Instruction instr = null; - if (codePtr >= 0 && codePtr < function.body.length) instr = function.body[codePtr]; + if (codePtr >= 0 && codePtr < function.body.instructions.length) instr = function.body.instructions[codePtr]; if (returnValue == Values.NO_RETURN && error == null) { try { @@ -204,14 +154,12 @@ public class CodeFrame { else { DebugContext.get(ctx).onInstruction(ctx, this, instr, Values.NO_RETURN, null, false); - if (instr.location != null) prevLoc = instr.location; - try { this.jumpFlag = this.popTryFlag = false; - returnValue = Runners.exec(ctx, instr, this); + returnValue = InstructionRunner.exec(ctx, instr, this); } catch (EngineException e) { - error = e.add(ctx, function.name, prevLoc); + error = e.add(ctx, function.name, DebugContext.get(ctx).getMap(function).toLocation(codePtr, true)); } } } @@ -315,9 +263,58 @@ public class CodeFrame { DebugContext.get(ctx.parent).onFramePop(ctx.parent, this); } - public CodeFrame(Context ctx, Object thisArg, Object[] args, CodeFunction func) { + public ObjectValue getLocalScope() { + var names = new String[scope.locals.length]; + var map = DebugContext.get(ctx).getMapOrEmpty(function); + + for (int i = 0; i < scope.locals.length; i++) { + var name = "local_" + (i - 2); + + if (i == 0) name = "this"; + else if (i == 1) name = "arguments"; + else if (i < map.localNames.length) name = map.localNames[i]; + + names[i] = name; + } + + return new ScopeValue(scope.locals, names); + } + public ObjectValue getCaptureScope() { + var names = new String[scope.captures.length]; + var map = DebugContext.get(ctx).getMapOrEmpty(function); + + for (int i = 0; i < scope.captures.length; i++) { + var name = "capture_" + (i - 2); + if (i < map.captureNames.length) name = map.captureNames[i]; + names[i] = name; + } + + return new ScopeValue(scope.captures, names); + } + public ObjectValue getValStackScope() { + return new ObjectValue() { + @Override + protected Object getField(Context ctx, Object key) { + var i = (int)Values.toNumber(ctx, key); + if (i < 0 || i >= stackPtr) return null; + else return stack[i]; + } + @Override + protected boolean hasField(Context ctx, Object key) { + return true; + } + @Override + public List keys(boolean includeNonEnumerable) { + var res = super.keys(includeNonEnumerable); + for (var i = 0; i < stackPtr; i++) res.add(i); + return res; + } + }; + } + + public Frame(Context ctx, Object thisArg, Object[] args, CodeFunction func) { this.args = args.clone(); - this.scope = new LocalScope(func.localsN, func.captures); + this.scope = new LocalScope(func.body.localsN, func.captures); this.scope.get(0).set(null, thisArg); var argsObj = new ArrayValue(); for (var i = 0; i < args.length; i++) { diff --git a/src/java/me/topchetoeu/jscript/core/engine/frame/Runners.java b/src/java/me/topchetoeu/jscript/core/InstructionRunner.java similarity index 63% rename from src/java/me/topchetoeu/jscript/core/engine/frame/Runners.java rename to src/java/me/topchetoeu/jscript/core/InstructionRunner.java index 513a3f8..55bde56 100644 --- a/src/java/me/topchetoeu/jscript/core/engine/frame/Runners.java +++ b/src/java/me/topchetoeu/jscript/core/InstructionRunner.java @@ -1,33 +1,29 @@ -package me.topchetoeu.jscript.core.engine.frame; +package me.topchetoeu.jscript.core; import java.util.Collections; -import me.topchetoeu.jscript.core.compilation.Instruction; -import me.topchetoeu.jscript.core.engine.Context; -import me.topchetoeu.jscript.core.engine.Engine; -import me.topchetoeu.jscript.core.engine.Environment; -import me.topchetoeu.jscript.core.engine.Operation; -import me.topchetoeu.jscript.core.engine.scope.ValueVariable; -import me.topchetoeu.jscript.core.engine.values.ArrayValue; -import me.topchetoeu.jscript.core.engine.values.CodeFunction; -import me.topchetoeu.jscript.core.engine.values.FunctionValue; -import me.topchetoeu.jscript.core.engine.values.ObjectValue; -import me.topchetoeu.jscript.core.engine.values.Symbol; -import me.topchetoeu.jscript.core.engine.values.Values; +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; +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.core.exceptions.EngineException; -public class Runners { - public static Object execReturn(Context ctx, Instruction instr, CodeFrame frame) { +public class InstructionRunner { + private static Object execReturn(Context ctx, Instruction instr, Frame frame) { return frame.pop(); } - public static Object execThrow(Context ctx, Instruction instr, CodeFrame frame) { + private static Object execThrow(Context ctx, Instruction instr, Frame frame) { throw new EngineException(frame.pop()); } - public static Object execThrowSyntax(Context ctx, Instruction instr, CodeFrame frame) { + private static Object execThrowSyntax(Context ctx, Instruction instr, Frame frame) { throw EngineException.ofSyntax((String)instr.get(0)); } - public static Object execCall(Context ctx, Instruction instr, CodeFrame frame) { + private static Object execCall(Context ctx, Instruction instr, Frame frame) { var callArgs = frame.take(instr.get(0)); var func = frame.pop(); var thisArg = frame.pop(); @@ -37,7 +33,7 @@ public class Runners { frame.codePtr++; return Values.NO_RETURN; } - public static Object execCallNew(Context ctx, Instruction instr, CodeFrame frame) { + private static Object execCallNew(Context ctx, Instruction instr, Frame frame) { var callArgs = frame.take(instr.get(0)); var funcObj = frame.pop(); @@ -47,13 +43,13 @@ public class Runners { return Values.NO_RETURN; } - public static Object execMakeVar(Context ctx, Instruction instr, CodeFrame frame) { + private static Object execMakeVar(Context ctx, Instruction instr, Frame frame) { var name = (String)instr.get(0); ctx.environment.global.define(name); frame.codePtr++; return Values.NO_RETURN; } - public static Object execDefProp(Context ctx, Instruction instr, CodeFrame frame) { + private static Object execDefProp(Context ctx, Instruction instr, Frame frame) { var setter = frame.pop(); var getter = frame.pop(); var name = frame.pop(); @@ -62,28 +58,13 @@ public class Runners { if (getter != null && !(getter instanceof FunctionValue)) throw EngineException.ofType("Getter must be a function or undefined."); if (setter != null && !(setter instanceof FunctionValue)) throw EngineException.ofType("Setter must be a function or undefined."); if (!(obj instanceof ObjectValue)) throw EngineException.ofType("Property apply target must be an object."); - Values.object(obj).defineProperty(ctx, name, Values.function(getter), Values.function(setter), false, false); + ((ObjectValue)obj).defineProperty(ctx, name, (FunctionValue)getter, (FunctionValue)setter, false, false); frame.push(obj); frame.codePtr++; return Values.NO_RETURN; } - public static Object execInstanceof(Context ctx, Instruction instr, CodeFrame frame) { - var type = frame.pop(); - var obj = frame.pop(); - - if (!Values.isPrimitive(type)) { - var proto = Values.getMember(ctx, type, "prototype"); - frame.push(Values.isInstanceOf(ctx, obj, proto)); - } - else { - frame.push(false); - } - - frame.codePtr++; - return Values.NO_RETURN; - } - public static Object execKeys(Context ctx, Instruction instr, CodeFrame frame) { + private static Object execKeys(Context ctx, Instruction instr, Frame frame) { var val = frame.pop(); var members = Values.getMembers(ctx, val, false, false); @@ -102,7 +83,7 @@ public class Runners { return Values.NO_RETURN; } - public static Object execTryStart(Context ctx, Instruction instr, CodeFrame frame) { + private static Object execTryStart(Context ctx, Instruction instr, Frame frame) { int start = frame.codePtr + 1; int catchStart = (int)instr.get(0); int finallyStart = (int)instr.get(1); @@ -113,12 +94,12 @@ public class Runners { frame.codePtr++; return Values.NO_RETURN; } - public static Object execTryEnd(Context ctx, Instruction instr, CodeFrame frame) { + private static Object execTryEnd(Context ctx, Instruction instr, Frame frame) { frame.popTryFlag = true; return Values.NO_RETURN; } - public static Object execDup(Context ctx, Instruction instr, CodeFrame frame) { + private static Object execDup(Context ctx, Instruction instr, Frame frame) { int count = instr.get(0); for (var i = 0; i < count; i++) { @@ -128,17 +109,17 @@ public class Runners { frame.codePtr++; return Values.NO_RETURN; } - public static Object execLoadUndefined(Context ctx, Instruction instr, CodeFrame frame) { - frame.push(null); + private static Object execLoadValue(Context ctx, Instruction instr, Frame frame) { + switch (instr.type) { + case PUSH_UNDEFINED: frame.push(null); break; + case PUSH_NULL: frame.push(Values.NULL); break; + default: frame.push(instr.get(0)); break; + } + frame.codePtr++; return Values.NO_RETURN; } - public static Object execLoadValue(Context ctx, Instruction instr, CodeFrame frame) { - frame.push(instr.get(0)); - frame.codePtr++; - return Values.NO_RETURN; - } - public static Object execLoadVar(Context ctx, Instruction instr, CodeFrame frame) { + private static Object execLoadVar(Context ctx, Instruction instr, Frame frame) { var i = instr.get(0); if (i instanceof String) frame.push(ctx.environment.global.get(ctx, (String)i)); @@ -147,39 +128,39 @@ public class Runners { frame.codePtr++; return Values.NO_RETURN; } - public static Object execLoadObj(Context ctx, Instruction instr, CodeFrame frame) { + private static Object execLoadObj(Context ctx, Instruction instr, Frame frame) { frame.push(new ObjectValue()); frame.codePtr++; return Values.NO_RETURN; } - public static Object execLoadGlob(Context ctx, Instruction instr, CodeFrame frame) { + private static Object execLoadGlob(Context ctx, Instruction instr, Frame frame) { frame.push(ctx.environment.global.obj); frame.codePtr++; return Values.NO_RETURN; } - public static Object execLoadArr(Context ctx, Instruction instr, CodeFrame frame) { + private static Object execLoadArr(Context ctx, Instruction instr, Frame frame) { var res = new ArrayValue(); res.setSize(instr.get(0)); frame.push(res); frame.codePtr++; return Values.NO_RETURN; } - public static Object execLoadFunc(Context ctx, Instruction instr, CodeFrame frame) { - long id = (Long)instr.get(0); + private static Object execLoadFunc(Context ctx, Instruction instr, Frame frame) { + int id = instr.get(0); var captures = new ValueVariable[instr.params.length - 1]; for (var i = 1; i < instr.params.length; i++) { captures[i - 1] = frame.scope.get(instr.get(i)); } - var func = new CodeFunction(ctx.environment, "", Engine.functions.get(id), captures); + var func = new CodeFunction(ctx.environment, "", frame.function.body.children[id], captures); frame.push(func); frame.codePtr++; return Values.NO_RETURN; } - public static Object execLoadMember(Context ctx, Instruction instr, CodeFrame frame) { + private static Object execLoadMember(Context ctx, Instruction instr, Frame frame) { var key = frame.pop(); var obj = frame.pop(); @@ -192,11 +173,7 @@ public class Runners { frame.codePtr++; return Values.NO_RETURN; } - public static Object execLoadKeyMember(Context ctx, Instruction instr, CodeFrame frame) { - frame.push(instr.get(0)); - return execLoadMember(ctx, instr, frame); - } - public static Object execLoadRegEx(Context ctx, Instruction instr, CodeFrame frame) { + private static Object execLoadRegEx(Context ctx, Instruction instr, Frame frame) { if (ctx.hasNotNull(Environment.REGEX_CONSTR)) { frame.push(Values.callNew(ctx, ctx.get(Environment.REGEX_CONSTR), instr.get(0), instr.get(1))); } @@ -207,12 +184,12 @@ public class Runners { return Values.NO_RETURN; } - public static Object execDiscard(Context ctx, Instruction instr, CodeFrame frame) { + private static Object execDiscard(Context ctx, Instruction instr, Frame frame) { frame.pop(); frame.codePtr++; return Values.NO_RETURN; } - public static Object execStoreMember(Context ctx, Instruction instr, CodeFrame frame) { + private static Object execStoreMember(Context ctx, Instruction instr, Frame frame) { var val = frame.pop(); var key = frame.pop(); var obj = frame.pop(); @@ -222,7 +199,7 @@ public class Runners { frame.codePtr++; return Values.NO_RETURN; } - public static Object execStoreVar(Context ctx, Instruction instr, CodeFrame frame) { + private static Object execStoreVar(Context ctx, Instruction instr, Frame frame) { var val = (boolean)instr.get(1) ? frame.peek() : frame.pop(); var i = instr.get(0); @@ -232,18 +209,18 @@ public class Runners { frame.codePtr++; return Values.NO_RETURN; } - public static Object execStoreSelfFunc(Context ctx, Instruction instr, CodeFrame frame) { + private static Object execStoreSelfFunc(Context ctx, Instruction instr, Frame frame) { frame.scope.locals[(int)instr.get(0)].set(ctx, frame.function); frame.codePtr++; return Values.NO_RETURN; } - public static Object execJmp(Context ctx, Instruction instr, CodeFrame frame) { + private static Object execJmp(Context ctx, Instruction instr, Frame frame) { frame.codePtr += (int)instr.get(0); frame.jumpFlag = true; return Values.NO_RETURN; } - public static Object execJmpIf(Context ctx, Instruction instr, CodeFrame frame) { + private static Object execJmpIf(Context ctx, Instruction instr, Frame frame) { if (Values.toBoolean(frame.pop())) { frame.codePtr += (int)instr.get(0); frame.jumpFlag = true; @@ -251,7 +228,7 @@ public class Runners { else frame.codePtr ++; return Values.NO_RETURN; } - public static Object execJmpIfNot(Context ctx, Instruction instr, CodeFrame frame) { + private static Object execJmpIfNot(Context ctx, Instruction instr, Frame frame) { if (Values.not(frame.pop())) { frame.codePtr += (int)instr.get(0); frame.jumpFlag = true; @@ -260,15 +237,7 @@ public class Runners { return Values.NO_RETURN; } - public static Object execIn(Context ctx, Instruction instr, CodeFrame frame) { - var obj = frame.pop(); - var index = frame.pop(); - - frame.push(Values.hasMember(ctx, obj, index, false)); - frame.codePtr++; - return Values.NO_RETURN; - } - public static Object execTypeof(Context ctx, Instruction instr, CodeFrame frame) { + private static Object execTypeof(Context ctx, Instruction instr, Frame frame) { String name = instr.get(0); Object obj; @@ -285,12 +254,12 @@ public class Runners { frame.codePtr++; return Values.NO_RETURN; } - public static Object execNop(Context ctx, Instruction instr, CodeFrame frame) { + private static Object execNop(Context ctx, Instruction instr, Frame frame) { frame.codePtr++; return Values.NO_RETURN; } - public static Object execDelete(Context ctx, Instruction instr, CodeFrame frame) { + private static Object execDelete(Context ctx, Instruction instr, Frame frame) { var key = frame.pop(); var val = frame.pop(); @@ -299,7 +268,7 @@ public class Runners { return Values.NO_RETURN; } - public static Object execOperation(Context ctx, Instruction instr, CodeFrame frame) { + private static Object execOperation(Context ctx, Instruction instr, Frame frame) { Operation op = instr.get(0); var args = new Object[op.operands]; @@ -310,7 +279,7 @@ public class Runners { return Values.NO_RETURN; } - public static Object exec(Context ctx, Instruction instr, CodeFrame frame) { + public static Object exec(Context ctx, Instruction instr, Frame frame) { switch (instr.type) { case NOP: return execNop(ctx, instr, frame); case RETURN: return execReturn(ctx, instr, frame); @@ -322,13 +291,17 @@ public class Runners { case TRY_END: return execTryEnd(ctx, instr, frame); case DUP: return execDup(ctx, instr, frame); - case LOAD_VALUE: return execLoadValue(ctx, instr, frame); + case PUSH_UNDEFINED: + case PUSH_NULL: + case PUSH_STRING: + case PUSH_NUMBER: + case PUSH_BOOL: + return execLoadValue(ctx, instr, frame); case LOAD_VAR: return execLoadVar(ctx, instr, frame); case LOAD_OBJ: return execLoadObj(ctx, instr, frame); case LOAD_ARR: return execLoadArr(ctx, instr, frame); case LOAD_FUNC: return execLoadFunc(ctx, instr, frame); case LOAD_MEMBER: return execLoadMember(ctx, instr, frame); - case LOAD_VAL_MEMBER: return execLoadKeyMember(ctx, instr, frame); case LOAD_REGEX: return execLoadRegEx(ctx, instr, frame); case LOAD_GLOB: return execLoadGlob(ctx, instr, frame); diff --git a/src/java/me/topchetoeu/jscript/core/Key.java b/src/java/me/topchetoeu/jscript/core/Key.java new file mode 100644 index 0000000..14ed55a --- /dev/null +++ b/src/java/me/topchetoeu/jscript/core/Key.java @@ -0,0 +1,5 @@ +package me.topchetoeu.jscript.core; + +public class Key { + +} diff --git a/src/java/me/topchetoeu/jscript/core/Operation.java b/src/java/me/topchetoeu/jscript/core/Operation.java new file mode 100644 index 0000000..6853ef5 --- /dev/null +++ b/src/java/me/topchetoeu/jscript/core/Operation.java @@ -0,0 +1,54 @@ +package me.topchetoeu.jscript.core; + +import java.util.HashMap; + +public enum Operation { + INSTANCEOF(1, 2), + IN(2, 2), + + MULTIPLY(3, 2), + DIVIDE(4, 2), + MODULO(5, 2), + ADD(6, 2), + SUBTRACT(7, 2), + + USHIFT_RIGHT(8, 2), + SHIFT_RIGHT(9, 2), + SHIFT_LEFT(10, 2), + + GREATER(11, 2), + LESS(12, 2), + GREATER_EQUALS(13, 2), + LESS_EQUALS(14, 2), + LOOSE_EQUALS(15, 2), + LOOSE_NOT_EQUALS(16, 2), + EQUALS(17, 2), + NOT_EQUALS(18, 2), + + AND(19, 2), + OR(20, 2), + XOR(21, 2), + + NEG(23, 1), + POS(24, 1), + NOT(25, 1), + INVERSE(26, 1); + + private static final HashMap operations = new HashMap<>(); + + static { + for (var val : Operation.values()) operations.put(val.numeric, val); + } + + public final int numeric; + public final int operands; + + private Operation(int numeric, int n) { + this.numeric = numeric; + this.operands = n; + } + + public static Operation fromNumeric(int i) { + return operations.get(i); + } +} diff --git a/src/java/me/topchetoeu/jscript/core/engine/WrapperProvider.java b/src/java/me/topchetoeu/jscript/core/WrapperProvider.java similarity index 58% rename from src/java/me/topchetoeu/jscript/core/engine/WrapperProvider.java rename to src/java/me/topchetoeu/jscript/core/WrapperProvider.java index ea30e5a..f777bbd 100644 --- a/src/java/me/topchetoeu/jscript/core/engine/WrapperProvider.java +++ b/src/java/me/topchetoeu/jscript/core/WrapperProvider.java @@ -1,7 +1,7 @@ -package me.topchetoeu.jscript.core.engine; +package me.topchetoeu.jscript.core; -import me.topchetoeu.jscript.core.engine.values.FunctionValue; -import me.topchetoeu.jscript.core.engine.values.ObjectValue; +import me.topchetoeu.jscript.core.values.FunctionValue; +import me.topchetoeu.jscript.core.values.ObjectValue; public interface WrapperProvider { public ObjectValue getProto(Class obj); diff --git a/src/java/me/topchetoeu/jscript/core/compilation/CalculateResult.java b/src/java/me/topchetoeu/jscript/core/compilation/CalculateResult.java deleted file mode 100644 index 696dbc9..0000000 --- a/src/java/me/topchetoeu/jscript/core/compilation/CalculateResult.java +++ /dev/null @@ -1,21 +0,0 @@ -package me.topchetoeu.jscript.core.compilation; - -import me.topchetoeu.jscript.core.engine.values.Values; - -public final class CalculateResult { - public final boolean exists; - public final Object value; - - public final boolean isTruthy() { - return exists && Values.toBoolean(value); - } - - public CalculateResult(Object value) { - this.exists = true; - this.value = value; - } - public CalculateResult() { - this.exists = false; - this.value = null; - } -} \ No newline at end of file diff --git a/src/java/me/topchetoeu/jscript/core/compilation/CompileTarget.java b/src/java/me/topchetoeu/jscript/core/compilation/CompileTarget.java deleted file mode 100644 index 61d40c6..0000000 --- a/src/java/me/topchetoeu/jscript/core/compilation/CompileTarget.java +++ /dev/null @@ -1,66 +0,0 @@ -package me.topchetoeu.jscript.core.compilation; - -import java.util.HashMap; -import java.util.Map; -import java.util.TreeSet; -import java.util.Vector; - -import me.topchetoeu.jscript.common.Location; -import me.topchetoeu.jscript.core.compilation.Instruction.BreakpointType; -import me.topchetoeu.jscript.core.engine.Environment; -import me.topchetoeu.jscript.core.engine.values.CodeFunction; - -public class CompileTarget { - public final Vector target = new Vector<>(); - public final Map functions; - public final TreeSet breakpoints; - private final HashMap bpToInstr = new HashMap<>(); - - public Instruction add(Instruction instr) { - target.add(instr); - return instr; - } - public Instruction set(int i, Instruction instr) { - return target.set(i, instr); - } - public void setDebug(int i, BreakpointType type) { - var instr = target.get(i); - instr.breakpoint = type; - - if (type == BreakpointType.NONE) { - breakpoints.remove(target.get(i).location); - bpToInstr.remove(instr.location, instr); - } - else { - breakpoints.add(target.get(i).location); - - var old = bpToInstr.put(instr.location, instr); - if (old != null) old.breakpoint = BreakpointType.NONE; - } - } - public void setDebug(BreakpointType type) { - setDebug(target.size() - 1, type); - } - public Instruction get(int i) { - return target.get(i); - } - public int size() { return target.size(); } - public Location lastLoc(Location fallback) { - if (target.size() == 0) return fallback; - else return target.get(target.size() - 1).location; - } - - public Instruction[] array() { return target.toArray(Instruction[]::new); } - - public FunctionBody body() { - return functions.get(0l); - } - public CodeFunction func(Environment env) { - return new CodeFunction(env, "", body()); - } - - public CompileTarget(Map functions, TreeSet breakpoints) { - this.functions = functions; - this.breakpoints = breakpoints; - } -} diff --git a/src/java/me/topchetoeu/jscript/core/compilation/FunctionBody.java b/src/java/me/topchetoeu/jscript/core/compilation/FunctionBody.java deleted file mode 100644 index 8e5aa4c..0000000 --- a/src/java/me/topchetoeu/jscript/core/compilation/FunctionBody.java +++ /dev/null @@ -1,29 +0,0 @@ -package me.topchetoeu.jscript.core.compilation; - -public class FunctionBody { - public final Instruction[] instructions; - public final String[] captureNames, localNames; - public final int localsN, argsN; - - public FunctionBody(int localsN, int argsN, Instruction[] instructions, String[] captureNames, String[] localNames) { - this.argsN = argsN; - this.localsN = localsN; - this.instructions = instructions; - this.captureNames = captureNames; - this.localNames = localNames; - } - public FunctionBody(int localsN, int argsN, Instruction[] instructions) { - this.argsN = argsN; - this.localsN = localsN; - this.instructions = instructions; - this.captureNames = new String[0]; - this.localNames = new String[0]; - } - public FunctionBody(Instruction... instructions) { - this.argsN = 0; - this.localsN = 2; - this.instructions = instructions; - this.captureNames = new String[0]; - this.localNames = new String[0]; - } -} diff --git a/src/java/me/topchetoeu/jscript/core/compilation/Instruction.java b/src/java/me/topchetoeu/jscript/core/compilation/Instruction.java deleted file mode 100644 index 7eff032..0000000 --- a/src/java/me/topchetoeu/jscript/core/compilation/Instruction.java +++ /dev/null @@ -1,256 +0,0 @@ -package me.topchetoeu.jscript.core.compilation; - -import me.topchetoeu.jscript.common.Location; -import me.topchetoeu.jscript.core.engine.Operation; -import me.topchetoeu.jscript.core.exceptions.SyntaxException; - -public class Instruction { - public static enum Type { - RETURN, - THROW, - THROW_SYNTAX, - DELETE, - TRY_START, - TRY_END, - NOP, - - CALL, - CALL_NEW, - JMP_IF, - JMP_IFN, - JMP, - - LOAD_VALUE, - - LOAD_VAR, - LOAD_MEMBER, - LOAD_VAL_MEMBER, - LOAD_GLOB, - - LOAD_FUNC, - LOAD_ARR, - LOAD_OBJ, - STORE_SELF_FUNC, - LOAD_REGEX, - - DUP, - - STORE_VAR, - STORE_MEMBER, - DISCARD, - - MAKE_VAR, - DEF_PROP, - KEYS, - - TYPEOF, - OPERATION; - } - public static enum BreakpointType { - NONE, - STEP_OVER, - STEP_IN; - - public boolean shouldStepIn() { - return this != NONE; - } - public boolean shouldStepOver() { - return this == STEP_OVER; - } - } - - public final Type type; - public final Object[] params; - public Location location; - public BreakpointType breakpoint = BreakpointType.NONE; - - public Instruction setDbgData(Instruction other) { - this.location = other.location; - this.breakpoint = other.breakpoint; - return this; - } - - public Instruction locate(Location loc) { - this.location = loc; - return this; - } - - @SuppressWarnings("unchecked") - public T get(int i) { - if (i >= params.length || i < 0) return null; - return (T)params[i]; - } - @SuppressWarnings("unchecked") - public T get(int i, T defaultVal) { - if (i >= params.length || i < 0) return defaultVal; - return (T)params[i]; - } - public boolean match(Object ...args) { - if (args.length != params.length) return false; - for (int i = 0; i < args.length; i++) { - var a = params[i]; - var b = args[i]; - if (a == null || b == null) { - if (!(a == null && b == null)) return false; - } - if (!a.equals(b)) return false; - } - return true; - } - public boolean is(int i, Object arg) { - if (params.length <= i) return false; - return params[i].equals(arg); - } - - private Instruction(Location location, Type type, Object ...params) { - this.location = location; - this.type = type; - this.params = params; - } - - public static Instruction tryStart(Location loc, int catchStart, int finallyStart, int end) { - return new Instruction(loc, Type.TRY_START, catchStart, finallyStart, end); - } - public static Instruction tryEnd(Location loc) { - return new Instruction(loc, Type.TRY_END); - } - public static Instruction throwInstr(Location loc) { - return new Instruction(loc, Type.THROW); - } - public static Instruction throwSyntax(Location loc, SyntaxException err) { - return new Instruction(loc, Type.THROW_SYNTAX, err.getMessage()); - } - public static Instruction throwSyntax(Location loc, String err) { - return new Instruction(loc, Type.THROW_SYNTAX, err); - } - public static Instruction delete(Location loc) { - return new Instruction(loc, Type.DELETE); - } - public static Instruction ret(Location loc) { - return new Instruction(loc, Type.RETURN); - } - public static Instruction debug(Location loc) { - return new Instruction(loc, Type.NOP, "debug"); - } - - public static Instruction nop(Location loc, Object ...params) { - for (var param : params) { - if (param instanceof String) continue; - if (param instanceof Boolean) continue; - if (param instanceof Double) continue; - if (param instanceof Integer) continue; - if (param == null) continue; - - throw new RuntimeException("NOP params may contain only strings, booleans, doubles, integers and nulls."); - } - return new Instruction(loc, Type.NOP, params); - } - - public static Instruction call(Location loc, int argn) { - return new Instruction(loc, Type.CALL, argn); - } - public static Instruction callNew(Location loc, int argn) { - return new Instruction(loc, Type.CALL_NEW, argn); - } - public static Instruction jmp(Location loc, int offset) { - return new Instruction(loc, Type.JMP, offset); - } - public static Instruction jmpIf(Location loc, int offset) { - return new Instruction(loc, Type.JMP_IF, offset); - } - public static Instruction jmpIfNot(Location loc, int offset) { - return new Instruction(loc, Type.JMP_IFN, offset); - } - - public static Instruction loadValue(Location loc, Object val) { - return new Instruction(loc, Type.LOAD_VALUE, val); - } - - public static Instruction makeVar(Location loc, String name) { - return new Instruction(loc, Type.MAKE_VAR, name); - } - public static Instruction loadVar(Location loc, Object i) { - return new Instruction(loc, Type.LOAD_VAR, i); - } - public static Instruction loadGlob(Location loc) { - return new Instruction(loc, Type.LOAD_GLOB); - } - public static Instruction loadMember(Location loc) { - return new Instruction(loc, Type.LOAD_MEMBER); - } - public static Instruction loadMember(Location loc, Object key) { - if (key instanceof Number) key = ((Number)key).doubleValue(); - return new Instruction(loc, Type.LOAD_VAL_MEMBER, key); - } - - public static Instruction loadRegex(Location loc, String pattern, String flags) { - return new Instruction(loc, Type.LOAD_REGEX, pattern, flags); - } - public static Instruction loadFunc(Location loc, long id, int[] captures) { - var args = new Object[1 + captures.length]; - args[0] = id; - for (var i = 0; i < captures.length; i++) args[i + 1] = captures[i]; - return new Instruction(loc, Type.LOAD_FUNC, args); - } - public static Instruction loadObj(Location loc) { - return new Instruction(loc, Type.LOAD_OBJ); - } - public static Instruction loadArr(Location loc, int count) { - return new Instruction(loc, Type.LOAD_ARR, count); - } - public static Instruction dup(Location loc) { - return new Instruction(loc, Type.DUP, 1); - } - public static Instruction dup(Location loc, int count) { - return new Instruction(loc, Type.DUP, count); - } - - public static Instruction storeSelfFunc(Location loc, int i) { - return new Instruction(loc, Type.STORE_SELF_FUNC, i); - } - public static Instruction storeVar(Location loc, Object i) { - return new Instruction(loc, Type.STORE_VAR, i, false); - } - public static Instruction storeVar(Location loc, Object i, boolean keep) { - return new Instruction(loc, Type.STORE_VAR, i, keep); - } - public static Instruction storeMember(Location loc) { - return new Instruction(loc, Type.STORE_MEMBER, false); - } - public static Instruction storeMember(Location loc, boolean keep) { - return new Instruction(loc, Type.STORE_MEMBER, keep); - } - public static Instruction discard(Location loc) { - return new Instruction(loc, Type.DISCARD); - } - - public static Instruction typeof(Location loc) { - return new Instruction(loc, Type.TYPEOF); - } - public static Instruction typeof(Location loc, Object varName) { - return new Instruction(loc, Type.TYPEOF, varName); - } - - public static Instruction keys(Location loc, boolean forInFormat) { - return new Instruction(loc, Type.KEYS, forInFormat); - } - - public static Instruction defProp(Location loc) { - return new Instruction(loc, Type.DEF_PROP); - } - - public static Instruction operation(Location loc, Operation op) { - return new Instruction(loc, Type.OPERATION, op); - } - - @Override - public String toString() { - var res = type.toString(); - - for (int i = 0; i < params.length; i++) { - res += " " + params[i]; - } - - return res; - } -} diff --git a/src/java/me/topchetoeu/jscript/core/compilation/Statement.java b/src/java/me/topchetoeu/jscript/core/compilation/Statement.java deleted file mode 100644 index 7bebffc..0000000 --- a/src/java/me/topchetoeu/jscript/core/compilation/Statement.java +++ /dev/null @@ -1,32 +0,0 @@ -package me.topchetoeu.jscript.core.compilation; - -import me.topchetoeu.jscript.common.Location; -import me.topchetoeu.jscript.core.compilation.Instruction.BreakpointType; -import me.topchetoeu.jscript.core.engine.scope.ScopeRecord; - -public abstract class Statement { - private Location _loc; - - public boolean pure() { return false; } - public void declare(ScopeRecord varsScope) { } - - public void compile(CompileTarget target, ScopeRecord scope, boolean pollute, BreakpointType type) { - int start = target.size(); - compile(target, scope, pollute); - - if (target.size() != start) { - target.get(start).locate(loc()); - target.setDebug(start, type); - } - } - public void compile(CompileTarget target, ScopeRecord scope, boolean pollute) { - compile(target, scope, pollute, BreakpointType.NONE); - } - - public Location loc() { return _loc; } - public void setLoc(Location loc) { _loc = loc; } - - protected Statement(Location loc) { - this._loc = loc; - } -} \ No newline at end of file diff --git a/src/java/me/topchetoeu/jscript/core/compilation/control/BreakStatement.java b/src/java/me/topchetoeu/jscript/core/compilation/control/BreakStatement.java deleted file mode 100644 index 2d16aa8..0000000 --- a/src/java/me/topchetoeu/jscript/core/compilation/control/BreakStatement.java +++ /dev/null @@ -1,22 +0,0 @@ -package me.topchetoeu.jscript.core.compilation.control; - -import me.topchetoeu.jscript.common.Location; -import me.topchetoeu.jscript.core.compilation.CompileTarget; -import me.topchetoeu.jscript.core.compilation.Instruction; -import me.topchetoeu.jscript.core.compilation.Statement; -import me.topchetoeu.jscript.core.engine.scope.ScopeRecord; - -public class BreakStatement extends Statement { - public final String label; - - @Override - public void compile(CompileTarget target, ScopeRecord scope, boolean pollute) { - target.add(Instruction.nop(loc(), "break", label)); - if (pollute) target.add(Instruction.loadValue(loc(), null)); - } - - public BreakStatement(Location loc, String label) { - super(loc); - this.label = label; - } -} diff --git a/src/java/me/topchetoeu/jscript/core/compilation/control/ContinueStatement.java b/src/java/me/topchetoeu/jscript/core/compilation/control/ContinueStatement.java deleted file mode 100644 index 31afc53..0000000 --- a/src/java/me/topchetoeu/jscript/core/compilation/control/ContinueStatement.java +++ /dev/null @@ -1,22 +0,0 @@ -package me.topchetoeu.jscript.core.compilation.control; - -import me.topchetoeu.jscript.common.Location; -import me.topchetoeu.jscript.core.compilation.CompileTarget; -import me.topchetoeu.jscript.core.compilation.Instruction; -import me.topchetoeu.jscript.core.compilation.Statement; -import me.topchetoeu.jscript.core.engine.scope.ScopeRecord; - -public class ContinueStatement extends Statement { - public final String label; - - @Override - public void compile(CompileTarget target, ScopeRecord scope, boolean pollute) { - target.add(Instruction.nop(loc(), "cont", label)); - if (pollute) target.add(Instruction.loadValue(loc(), null)); - } - - public ContinueStatement(Location loc, String label) { - super(loc); - this.label = label; - } -} diff --git a/src/java/me/topchetoeu/jscript/core/compilation/control/DebugStatement.java b/src/java/me/topchetoeu/jscript/core/compilation/control/DebugStatement.java deleted file mode 100644 index ad4d785..0000000 --- a/src/java/me/topchetoeu/jscript/core/compilation/control/DebugStatement.java +++ /dev/null @@ -1,19 +0,0 @@ -package me.topchetoeu.jscript.core.compilation.control; - -import me.topchetoeu.jscript.common.Location; -import me.topchetoeu.jscript.core.compilation.CompileTarget; -import me.topchetoeu.jscript.core.compilation.Instruction; -import me.topchetoeu.jscript.core.compilation.Statement; -import me.topchetoeu.jscript.core.engine.scope.ScopeRecord; - -public class DebugStatement extends Statement { - @Override - public void compile(CompileTarget target, ScopeRecord scope, boolean pollute) { - target.add(Instruction.debug(loc())); - if (pollute) target.add(Instruction.loadValue(loc(), null)); - } - - public DebugStatement(Location loc) { - super(loc); - } -} diff --git a/src/java/me/topchetoeu/jscript/core/compilation/control/DeleteStatement.java b/src/java/me/topchetoeu/jscript/core/compilation/control/DeleteStatement.java deleted file mode 100644 index 116c167..0000000 --- a/src/java/me/topchetoeu/jscript/core/compilation/control/DeleteStatement.java +++ /dev/null @@ -1,27 +0,0 @@ -package me.topchetoeu.jscript.core.compilation.control; - -import me.topchetoeu.jscript.common.Location; -import me.topchetoeu.jscript.core.compilation.CompileTarget; -import me.topchetoeu.jscript.core.compilation.Instruction; -import me.topchetoeu.jscript.core.compilation.Statement; -import me.topchetoeu.jscript.core.engine.scope.ScopeRecord; - -public class DeleteStatement extends Statement { - public final Statement key; - public final Statement value; - - @Override - public void compile(CompileTarget target, ScopeRecord scope, boolean pollute) { - value.compile(target, scope, true); - key.compile(target, scope, true); - - target.add(Instruction.delete(loc())); - if (pollute) target.add(Instruction.loadValue(loc(), true)); - } - - public DeleteStatement(Location loc, Statement key, Statement value) { - super(loc); - this.key = key; - this.value = value; - } -} diff --git a/src/java/me/topchetoeu/jscript/core/compilation/control/DoWhileStatement.java b/src/java/me/topchetoeu/jscript/core/compilation/control/DoWhileStatement.java deleted file mode 100644 index 1cd76c6..0000000 --- a/src/java/me/topchetoeu/jscript/core/compilation/control/DoWhileStatement.java +++ /dev/null @@ -1,37 +0,0 @@ -package me.topchetoeu.jscript.core.compilation.control; - -import me.topchetoeu.jscript.common.Location; -import me.topchetoeu.jscript.core.compilation.CompileTarget; -import me.topchetoeu.jscript.core.compilation.Instruction; -import me.topchetoeu.jscript.core.compilation.Statement; -import me.topchetoeu.jscript.core.compilation.Instruction.BreakpointType; -import me.topchetoeu.jscript.core.engine.scope.ScopeRecord; - -public class DoWhileStatement extends Statement { - public final Statement condition, body; - public final String label; - - @Override - public void declare(ScopeRecord globScope) { - body.declare(globScope); - } - - @Override - public void compile(CompileTarget target, ScopeRecord scope, boolean pollute) { - int start = target.size(); - body.compile(target, scope, false, BreakpointType.STEP_OVER); - int mid = target.size(); - condition.compile(target, scope, true, BreakpointType.STEP_OVER); - int end = target.size(); - - WhileStatement.replaceBreaks(target, label, start, mid - 1, mid, end + 1); - target.add(Instruction.jmpIf(loc(), start - end)); - } - - public DoWhileStatement(Location loc, String label, Statement condition, Statement body) { - super(loc); - this.label = label; - this.condition = condition; - this.body = body; - } -} diff --git a/src/java/me/topchetoeu/jscript/core/compilation/control/ForInStatement.java b/src/java/me/topchetoeu/jscript/core/compilation/control/ForInStatement.java deleted file mode 100644 index 80bdd82..0000000 --- a/src/java/me/topchetoeu/jscript/core/compilation/control/ForInStatement.java +++ /dev/null @@ -1,73 +0,0 @@ -package me.topchetoeu.jscript.core.compilation.control; - -import me.topchetoeu.jscript.common.Location; -import me.topchetoeu.jscript.core.compilation.CompileTarget; -import me.topchetoeu.jscript.core.compilation.Instruction; -import me.topchetoeu.jscript.core.compilation.Statement; -import me.topchetoeu.jscript.core.compilation.Instruction.BreakpointType; -import me.topchetoeu.jscript.core.engine.Operation; -import me.topchetoeu.jscript.core.engine.scope.ScopeRecord; - -public class ForInStatement extends Statement { - public final String varName; - public final boolean isDeclaration; - public final Statement varValue, object, body; - public final String label; - public final Location varLocation; - - @Override - public void declare(ScopeRecord globScope) { - body.declare(globScope); - if (isDeclaration) globScope.define(varName); - } - - @Override - public void compile(CompileTarget target, ScopeRecord scope, boolean pollute) { - var key = scope.getKey(varName); - - int first = target.size(); - if (key instanceof String) target.add(Instruction.makeVar(loc(), (String)key)); - - if (varValue != null) { - varValue.compile(target, scope, true); - target.add(Instruction.storeVar(loc(), scope.getKey(varName))); - } - - object.compile(target, scope, true, BreakpointType.STEP_OVER); - target.add(Instruction.keys(loc(), true)); - - int start = target.size(); - target.add(Instruction.dup(loc())); - target.add(Instruction.loadValue(loc(), null)); - target.add(Instruction.operation(loc(), Operation.EQUALS)); - int mid = target.size(); - target.add(Instruction.nop(loc())); - - target.add(Instruction.loadMember(varLocation, "value")); - target.add(Instruction.storeVar(object.loc(), key)); - target.setDebug(BreakpointType.STEP_OVER); - - body.compile(target, scope, false, BreakpointType.STEP_OVER); - - int end = target.size(); - - WhileStatement.replaceBreaks(target, label, mid + 1, end, start, end + 1); - - target.add(Instruction.jmp(loc(), start - end)); - target.add(Instruction.discard(loc())); - target.set(mid, Instruction.jmpIf(loc(), end - mid + 1)); - if (pollute) target.add(Instruction.loadValue(loc(), null)); - target.get(first).locate(loc()); - } - - public ForInStatement(Location loc, Location varLocation, String label, boolean isDecl, String varName, Statement varValue, Statement object, Statement body) { - super(loc); - this.varLocation = varLocation; - this.label = label; - this.isDeclaration = isDecl; - this.varName = varName; - this.varValue = varValue; - this.object = object; - this.body = body; - } -} diff --git a/src/java/me/topchetoeu/jscript/core/compilation/control/ForStatement.java b/src/java/me/topchetoeu/jscript/core/compilation/control/ForStatement.java deleted file mode 100644 index 56981c3..0000000 --- a/src/java/me/topchetoeu/jscript/core/compilation/control/ForStatement.java +++ /dev/null @@ -1,47 +0,0 @@ -package me.topchetoeu.jscript.core.compilation.control; - -import me.topchetoeu.jscript.common.Location; -import me.topchetoeu.jscript.core.compilation.CompileTarget; -import me.topchetoeu.jscript.core.compilation.Instruction; -import me.topchetoeu.jscript.core.compilation.Statement; -import me.topchetoeu.jscript.core.compilation.Instruction.BreakpointType; -import me.topchetoeu.jscript.core.engine.scope.ScopeRecord; - -public class ForStatement extends Statement { - public final Statement declaration, assignment, condition, body; - public final String label; - - @Override - public void declare(ScopeRecord globScope) { - declaration.declare(globScope); - body.declare(globScope); - } - @Override - public void compile(CompileTarget target, ScopeRecord scope, boolean pollute) { - declaration.compile(target, scope, false, BreakpointType.STEP_OVER); - - int start = target.size(); - condition.compile(target, scope, true, BreakpointType.STEP_OVER); - int mid = target.size(); - target.add(Instruction.nop(null)); - body.compile(target, scope, false, BreakpointType.STEP_OVER); - int beforeAssign = target.size(); - assignment.compile(target, scope, false, BreakpointType.STEP_OVER); - int end = target.size(); - - WhileStatement.replaceBreaks(target, label, mid + 1, end, beforeAssign, end + 1); - - target.add(Instruction.jmp(loc(), start - end)); - target.set(mid, Instruction.jmpIfNot(loc(), end - mid + 1)); - if (pollute) target.add(Instruction.loadValue(loc(), null)); - } - - public ForStatement(Location loc, String label, Statement declaration, Statement condition, Statement assignment, Statement body) { - super(loc); - this.label = label; - this.declaration = declaration; - this.condition = condition; - this.assignment = assignment; - this.body = body; - } -} diff --git a/src/java/me/topchetoeu/jscript/core/compilation/control/IfStatement.java b/src/java/me/topchetoeu/jscript/core/compilation/control/IfStatement.java deleted file mode 100644 index b5342c6..0000000 --- a/src/java/me/topchetoeu/jscript/core/compilation/control/IfStatement.java +++ /dev/null @@ -1,52 +0,0 @@ -package me.topchetoeu.jscript.core.compilation.control; - -import me.topchetoeu.jscript.common.Location; -import me.topchetoeu.jscript.core.compilation.CompileTarget; -import me.topchetoeu.jscript.core.compilation.Instruction; -import me.topchetoeu.jscript.core.compilation.Statement; -import me.topchetoeu.jscript.core.compilation.Instruction.BreakpointType; -import me.topchetoeu.jscript.core.engine.scope.ScopeRecord; - -public class IfStatement extends Statement { - public final Statement condition, body, elseBody; - - @Override - public void declare(ScopeRecord globScope) { - body.declare(globScope); - if (elseBody != null) elseBody.declare(globScope); - } - - @Override public void compile(CompileTarget target, ScopeRecord scope, boolean pollute, BreakpointType breakpoint) { - condition.compile(target, scope, true, breakpoint); - - if (elseBody == null) { - int i = target.size(); - target.add(Instruction.nop(null)); - body.compile(target, scope, pollute, breakpoint); - int endI = target.size(); - target.set(i, Instruction.jmpIfNot(loc(), endI - i)); - } - else { - int start = target.size(); - target.add(Instruction.nop(null)); - body.compile(target, scope, pollute, breakpoint); - target.add(Instruction.nop(null)); - int mid = target.size(); - elseBody.compile(target, scope, pollute, breakpoint); - int end = target.size(); - - target.set(start, Instruction.jmpIfNot(loc(), mid - start)); - target.set(mid - 1, Instruction.jmp(loc(), end - mid + 1)); - } - } - @Override public void compile(CompileTarget target, ScopeRecord scope, boolean pollute) { - compile(target, scope, pollute, BreakpointType.STEP_IN); - } - - public IfStatement(Location loc, Statement condition, Statement body, Statement elseBody) { - super(loc); - this.condition = condition; - this.body = body; - this.elseBody = elseBody; - } -} diff --git a/src/java/me/topchetoeu/jscript/core/compilation/control/ReturnStatement.java b/src/java/me/topchetoeu/jscript/core/compilation/control/ReturnStatement.java deleted file mode 100644 index d47e544..0000000 --- a/src/java/me/topchetoeu/jscript/core/compilation/control/ReturnStatement.java +++ /dev/null @@ -1,23 +0,0 @@ -package me.topchetoeu.jscript.core.compilation.control; - -import me.topchetoeu.jscript.common.Location; -import me.topchetoeu.jscript.core.compilation.CompileTarget; -import me.topchetoeu.jscript.core.compilation.Instruction; -import me.topchetoeu.jscript.core.compilation.Statement; -import me.topchetoeu.jscript.core.engine.scope.ScopeRecord; - -public class ReturnStatement extends Statement { - public final Statement value; - - @Override - public void compile(CompileTarget target, ScopeRecord scope, boolean pollute) { - if (value == null) target.add(Instruction.loadValue(loc(), null)); - else value.compile(target, scope, true); - target.add(Instruction.ret(loc())); - } - - public ReturnStatement(Location loc, Statement value) { - super(loc); - this.value = value; - } -} diff --git a/src/java/me/topchetoeu/jscript/core/compilation/control/SwitchStatement.java b/src/java/me/topchetoeu/jscript/core/compilation/control/SwitchStatement.java deleted file mode 100644 index 682132a..0000000 --- a/src/java/me/topchetoeu/jscript/core/compilation/control/SwitchStatement.java +++ /dev/null @@ -1,87 +0,0 @@ -package me.topchetoeu.jscript.core.compilation.control; - -import java.util.HashMap; - -import me.topchetoeu.jscript.common.Location; -import me.topchetoeu.jscript.core.compilation.CompileTarget; -import me.topchetoeu.jscript.core.compilation.Instruction; -import me.topchetoeu.jscript.core.compilation.Statement; -import me.topchetoeu.jscript.core.compilation.Instruction.BreakpointType; -import me.topchetoeu.jscript.core.compilation.Instruction.Type; -import me.topchetoeu.jscript.core.engine.Operation; -import me.topchetoeu.jscript.core.engine.scope.ScopeRecord; - -public class SwitchStatement extends Statement { - public static class SwitchCase { - public final Statement value; - public final int statementI; - - public SwitchCase(Statement value, int statementI) { - this.value = value; - this.statementI = statementI; - } - } - - public final Statement value; - public final SwitchCase[] cases; - public final Statement[] body; - public final int defaultI; - - @Override - public void declare(ScopeRecord varsScope) { - for (var stm : body) stm.declare(varsScope); - } - - @Override - public void compile(CompileTarget target, ScopeRecord scope, boolean pollute) { - var caseToStatement = new HashMap(); - var statementToIndex = new HashMap(); - - value.compile(target, scope, true, BreakpointType.STEP_OVER); - - for (var ccase : cases) { - target.add(Instruction.dup(loc())); - ccase.value.compile(target, scope, true); - target.add(Instruction.operation(loc(), Operation.EQUALS)); - caseToStatement.put(target.size(), ccase.statementI); - target.add(Instruction.nop(null)); - } - - int start = target.size(); - - target.add(Instruction.nop(null)); - - for (var stm : body) { - statementToIndex.put(statementToIndex.size(), target.size()); - stm.compile(target, scope, false, BreakpointType.STEP_OVER); - } - - int end = target.size(); - target.add(Instruction.discard(loc())); - if (pollute) target.add(Instruction.loadValue(loc(), null)); - - if (defaultI < 0 || defaultI >= body.length) target.set(start, Instruction.jmp(loc(), end - start)); - else target.set(start, Instruction.jmp(loc(), statementToIndex.get(defaultI) - start)); - - for (int i = start; i < end; i++) { - var instr = target.get(i); - if (instr.type == Type.NOP && instr.is(0, "break") && instr.get(1) == null) { - target.set(i, Instruction.jmp(loc(), end - i).locate(instr.location)); - } - } - for (var el : caseToStatement.entrySet()) { - var i = statementToIndex.get(el.getValue()); - if (i == null) i = end; - target.set(el.getKey(), Instruction.jmpIf(loc(), i - el.getKey())); - } - - } - - public SwitchStatement(Location loc, Statement value, int defaultI, SwitchCase[] cases, Statement[] body) { - super(loc); - this.value = value; - this.defaultI = defaultI; - this.cases = cases; - this.body = body; - } -} diff --git a/src/java/me/topchetoeu/jscript/core/compilation/control/ThrowStatement.java b/src/java/me/topchetoeu/jscript/core/compilation/control/ThrowStatement.java deleted file mode 100644 index 5a70b47..0000000 --- a/src/java/me/topchetoeu/jscript/core/compilation/control/ThrowStatement.java +++ /dev/null @@ -1,22 +0,0 @@ -package me.topchetoeu.jscript.core.compilation.control; - -import me.topchetoeu.jscript.common.Location; -import me.topchetoeu.jscript.core.compilation.CompileTarget; -import me.topchetoeu.jscript.core.compilation.Instruction; -import me.topchetoeu.jscript.core.compilation.Statement; -import me.topchetoeu.jscript.core.engine.scope.ScopeRecord; - -public class ThrowStatement extends Statement { - public final Statement value; - - @Override - public void compile(CompileTarget target, ScopeRecord scope, boolean pollute) { - value.compile(target, scope, true); - target.add(Instruction.throwInstr(loc())); - } - - public ThrowStatement(Location loc, Statement value) { - super(loc); - this.value = value; - } -} diff --git a/src/java/me/topchetoeu/jscript/core/compilation/control/TryStatement.java b/src/java/me/topchetoeu/jscript/core/compilation/control/TryStatement.java deleted file mode 100644 index f6fe1b4..0000000 --- a/src/java/me/topchetoeu/jscript/core/compilation/control/TryStatement.java +++ /dev/null @@ -1,61 +0,0 @@ -package me.topchetoeu.jscript.core.compilation.control; - -import me.topchetoeu.jscript.common.Location; -import me.topchetoeu.jscript.core.compilation.CompileTarget; -import me.topchetoeu.jscript.core.compilation.Instruction; -import me.topchetoeu.jscript.core.compilation.Statement; -import me.topchetoeu.jscript.core.compilation.Instruction.BreakpointType; -import me.topchetoeu.jscript.core.engine.scope.GlobalScope; -import me.topchetoeu.jscript.core.engine.scope.LocalScopeRecord; -import me.topchetoeu.jscript.core.engine.scope.ScopeRecord; - -public class TryStatement extends Statement { - public final Statement tryBody; - public final Statement catchBody; - public final Statement finallyBody; - public final String name; - - @Override - public void declare(ScopeRecord globScope) { - tryBody.declare(globScope); - if (catchBody != null) catchBody.declare(globScope); - if (finallyBody != null) finallyBody.declare(globScope); - } - - @Override - public void compile(CompileTarget target, ScopeRecord scope, boolean pollute, BreakpointType bpt) { - target.add(Instruction.nop(null)); - - int start = target.size(), catchStart = -1, finallyStart = -1; - - tryBody.compile(target, scope, false); - target.add(Instruction.tryEnd(loc())); - - if (catchBody != null) { - catchStart = target.size() - start; - var local = scope instanceof GlobalScope ? scope.child() : (LocalScopeRecord)scope; - local.define(name, true); - catchBody.compile(target, scope, false); - local.undefine(); - target.add(Instruction.tryEnd(loc())); - } - - if (finallyBody != null) { - finallyStart = target.size() - start; - finallyBody.compile(target, scope, false); - target.add(Instruction.tryEnd(loc())); - } - - target.set(start - 1, Instruction.tryStart(loc(), catchStart, finallyStart, target.size() - start)); - target.setDebug(start - 1, BreakpointType.STEP_OVER); - if (pollute) target.add(Instruction.loadValue(loc(), null)); - } - - public TryStatement(Location loc, Statement tryBody, Statement catchBody, Statement finallyBody, String name) { - super(loc); - this.tryBody = tryBody; - this.catchBody = catchBody; - this.finallyBody = finallyBody; - this.name = name; - } -} diff --git a/src/java/me/topchetoeu/jscript/core/compilation/control/WhileStatement.java b/src/java/me/topchetoeu/jscript/core/compilation/control/WhileStatement.java deleted file mode 100644 index 2d2e37d..0000000 --- a/src/java/me/topchetoeu/jscript/core/compilation/control/WhileStatement.java +++ /dev/null @@ -1,54 +0,0 @@ -package me.topchetoeu.jscript.core.compilation.control; - -import me.topchetoeu.jscript.common.Location; -import me.topchetoeu.jscript.core.compilation.CompileTarget; -import me.topchetoeu.jscript.core.compilation.Instruction; -import me.topchetoeu.jscript.core.compilation.Statement; -import me.topchetoeu.jscript.core.compilation.Instruction.BreakpointType; -import me.topchetoeu.jscript.core.compilation.Instruction.Type; -import me.topchetoeu.jscript.core.engine.scope.ScopeRecord; - -public class WhileStatement extends Statement { - public final Statement condition, body; - public final String label; - - @Override - public void declare(ScopeRecord globScope) { - body.declare(globScope); - } - @Override - public void compile(CompileTarget target, ScopeRecord scope, boolean pollute) { - int start = target.size(); - condition.compile(target, scope, true); - int mid = target.size(); - target.add(Instruction.nop(null)); - body.compile(target, scope, false, BreakpointType.STEP_OVER); - - int end = target.size(); - - replaceBreaks(target, label, mid + 1, end, start, end + 1); - - target.add(Instruction.jmp(loc(), start - end)); - target.set(mid, Instruction.jmpIfNot(loc(), end - mid + 1)); - if (pollute) target.add(Instruction.loadValue(loc(), null)); - } - - public WhileStatement(Location loc, String label, Statement condition, Statement body) { - super(loc); - this.label = label; - this.condition = condition; - this.body = body; - } - - public static void replaceBreaks(CompileTarget target, String label, int start, int end, int continuePoint, int breakPoint) { - for (int i = start; i < end; i++) { - var instr = target.get(i); - if (instr.type == Type.NOP && instr.is(0, "cont") && (instr.get(1) == null || instr.is(1, label))) { - target.set(i, Instruction.jmp(instr.location, continuePoint - i).setDbgData(target.get(i))); - } - if (instr.type == Type.NOP && instr.is(0, "break") && (instr.get(1) == null || instr.is(1, label))) { - target.set(i, Instruction.jmp(instr.location, breakPoint - i).setDbgData(target.get(i))); - } - } - } -} diff --git a/src/java/me/topchetoeu/jscript/core/compilation/values/ArrayStatement.java b/src/java/me/topchetoeu/jscript/core/compilation/values/ArrayStatement.java deleted file mode 100644 index 9b544bd..0000000 --- a/src/java/me/topchetoeu/jscript/core/compilation/values/ArrayStatement.java +++ /dev/null @@ -1,41 +0,0 @@ -package me.topchetoeu.jscript.core.compilation.values; - -import me.topchetoeu.jscript.common.Location; -import me.topchetoeu.jscript.core.compilation.CompileTarget; -import me.topchetoeu.jscript.core.compilation.Instruction; -import me.topchetoeu.jscript.core.compilation.Statement; -import me.topchetoeu.jscript.core.engine.scope.ScopeRecord; - -public class ArrayStatement extends Statement { - public final Statement[] statements; - - @Override public boolean pure() { - for (var stm : statements) { - if (!stm.pure()) return false; - } - - return true; - } - - @Override - public void compile(CompileTarget target, ScopeRecord scope, boolean pollute) { - target.add(Instruction.loadArr(loc(), statements.length)); - - for (var i = 0; i < statements.length; i++) { - var el = statements[i]; - if (el != null) { - target.add(Instruction.dup(loc())); - target.add(Instruction.loadValue(loc(), i)); - el.compile(target, scope, true); - target.add(Instruction.storeMember(loc())); - } - } - - if (!pollute) target.add(Instruction.discard(loc())); - } - - public ArrayStatement(Location loc, Statement[] statements) { - super(loc); - this.statements = statements; - } -} diff --git a/src/java/me/topchetoeu/jscript/core/compilation/values/CallStatement.java b/src/java/me/topchetoeu/jscript/core/compilation/values/CallStatement.java deleted file mode 100644 index f1927f3..0000000 --- a/src/java/me/topchetoeu/jscript/core/compilation/values/CallStatement.java +++ /dev/null @@ -1,51 +0,0 @@ -package me.topchetoeu.jscript.core.compilation.values; - -import me.topchetoeu.jscript.common.Location; -import me.topchetoeu.jscript.core.compilation.CompileTarget; -import me.topchetoeu.jscript.core.compilation.Instruction; -import me.topchetoeu.jscript.core.compilation.Statement; -import me.topchetoeu.jscript.core.compilation.Instruction.BreakpointType; -import me.topchetoeu.jscript.core.engine.scope.ScopeRecord; - -public class CallStatement extends Statement { - public final Statement func; - public final Statement[] args; - public final boolean isNew; - - @Override - public void compile(CompileTarget target, ScopeRecord scope, boolean pollute, BreakpointType type) { - if (isNew) func.compile(target, scope, true); - else if (func instanceof IndexStatement) { - ((IndexStatement)func).compile(target, scope, true, true); - } - else { - target.add(Instruction.loadValue(loc(), null)); - func.compile(target, scope, true); - } - - for (var arg : args) arg.compile(target, scope, true); - - if (isNew) target.add(Instruction.callNew(loc(), args.length)); - else target.add(Instruction.call(loc(), args.length)); - target.setDebug(type); - - if (!pollute) target.add(Instruction.discard(loc())); - } - @Override - public void compile(CompileTarget target, ScopeRecord scope, boolean pollute) { - compile(target, scope, pollute, BreakpointType.STEP_IN); - } - - public CallStatement(Location loc, boolean isNew, Statement func, Statement ...args) { - super(loc); - this.isNew = isNew; - this.func = func; - this.args = args; - } - public CallStatement(Location loc, boolean isNew, Statement obj, Object key, Statement ...args) { - super(loc); - this.isNew = isNew; - this.func = new IndexStatement(loc, obj, new ConstantStatement(loc, key)); - this.args = args; - } -} diff --git a/src/java/me/topchetoeu/jscript/core/compilation/values/ChangeStatement.java b/src/java/me/topchetoeu/jscript/core/compilation/values/ChangeStatement.java deleted file mode 100644 index 81ee374..0000000 --- a/src/java/me/topchetoeu/jscript/core/compilation/values/ChangeStatement.java +++ /dev/null @@ -1,32 +0,0 @@ -package me.topchetoeu.jscript.core.compilation.values; - -import me.topchetoeu.jscript.common.Location; -import me.topchetoeu.jscript.core.compilation.AssignableStatement; -import me.topchetoeu.jscript.core.compilation.CompileTarget; -import me.topchetoeu.jscript.core.compilation.Instruction; -import me.topchetoeu.jscript.core.compilation.Statement; -import me.topchetoeu.jscript.core.engine.Operation; -import me.topchetoeu.jscript.core.engine.scope.ScopeRecord; - -public class ChangeStatement extends Statement { - public final AssignableStatement value; - public final double addAmount; - public final boolean postfix; - - @Override - public void compile(CompileTarget target, ScopeRecord scope, boolean pollute) { - value.toAssign(new ConstantStatement(loc(), -addAmount), Operation.SUBTRACT).compile(target, scope, true); - if (!pollute) target.add(Instruction.discard(loc())); - else if (postfix) { - target.add(Instruction.loadValue(loc(), addAmount)); - target.add(Instruction.operation(loc(), Operation.SUBTRACT)); - } - } - - public ChangeStatement(Location loc, AssignableStatement value, double addAmount, boolean postfix) { - super(loc); - this.value = value; - this.addAmount = addAmount; - this.postfix = postfix; - } -} diff --git a/src/java/me/topchetoeu/jscript/core/compilation/values/ConstantStatement.java b/src/java/me/topchetoeu/jscript/core/compilation/values/ConstantStatement.java deleted file mode 100644 index 66fd073..0000000 --- a/src/java/me/topchetoeu/jscript/core/compilation/values/ConstantStatement.java +++ /dev/null @@ -1,23 +0,0 @@ -package me.topchetoeu.jscript.core.compilation.values; - -import me.topchetoeu.jscript.common.Location; -import me.topchetoeu.jscript.core.compilation.CompileTarget; -import me.topchetoeu.jscript.core.compilation.Instruction; -import me.topchetoeu.jscript.core.compilation.Statement; -import me.topchetoeu.jscript.core.engine.scope.ScopeRecord; - -public class ConstantStatement extends Statement { - public final Object value; - - @Override public boolean pure() { return true; } - - @Override - public void compile(CompileTarget target, ScopeRecord scope, boolean pollute) { - if (pollute) target.add(Instruction.loadValue(loc(), value)); - } - - public ConstantStatement(Location loc, Object val) { - super(loc); - this.value = val; - } -} diff --git a/src/java/me/topchetoeu/jscript/core/compilation/values/DiscardStatement.java b/src/java/me/topchetoeu/jscript/core/compilation/values/DiscardStatement.java deleted file mode 100644 index df62a71..0000000 --- a/src/java/me/topchetoeu/jscript/core/compilation/values/DiscardStatement.java +++ /dev/null @@ -1,24 +0,0 @@ -package me.topchetoeu.jscript.core.compilation.values; - -import me.topchetoeu.jscript.common.Location; -import me.topchetoeu.jscript.core.compilation.CompileTarget; -import me.topchetoeu.jscript.core.compilation.Instruction; -import me.topchetoeu.jscript.core.compilation.Statement; -import me.topchetoeu.jscript.core.engine.scope.ScopeRecord; - -public class DiscardStatement extends Statement { - public final Statement value; - - @Override public boolean pure() { return value.pure(); } - - @Override - public void compile(CompileTarget target, ScopeRecord scope, boolean pollute) { - value.compile(target, scope, false); - if (pollute) target.add(Instruction.loadValue(loc(), null)); - } - - public DiscardStatement(Location loc, Statement val) { - super(loc); - this.value = val; - } -} diff --git a/src/java/me/topchetoeu/jscript/core/compilation/values/FunctionStatement.java b/src/java/me/topchetoeu/jscript/core/compilation/values/FunctionStatement.java deleted file mode 100644 index dae7cc6..0000000 --- a/src/java/me/topchetoeu/jscript/core/compilation/values/FunctionStatement.java +++ /dev/null @@ -1,139 +0,0 @@ -package me.topchetoeu.jscript.core.compilation.values; - -import java.util.Random; - -import me.topchetoeu.jscript.common.Location; -import me.topchetoeu.jscript.core.compilation.CompileTarget; -import me.topchetoeu.jscript.core.compilation.CompoundStatement; -import me.topchetoeu.jscript.core.compilation.FunctionBody; -import me.topchetoeu.jscript.core.compilation.Instruction; -import me.topchetoeu.jscript.core.compilation.Statement; -import me.topchetoeu.jscript.core.compilation.Instruction.BreakpointType; -import me.topchetoeu.jscript.core.compilation.Instruction.Type; -import me.topchetoeu.jscript.core.engine.scope.ScopeRecord; -import me.topchetoeu.jscript.core.exceptions.SyntaxException; - -public class FunctionStatement extends Statement { - public final CompoundStatement body; - public final String varName; - public final String[] args; - public final boolean statement; - public final Location end; - - private static Random rand = new Random(); - - @Override public boolean pure() { return varName == null && statement; } - - @Override - public void declare(ScopeRecord scope) { - if (varName != null && statement) scope.define(varName); - } - - public static void checkBreakAndCont(CompileTarget target, int start) { - for (int i = start; i < target.size(); i++) { - if (target.get(i).type == Type.NOP) { - if (target.get(i).is(0, "break") ) { - throw new SyntaxException(target.get(i).location, "Break was placed outside a loop."); - } - if (target.get(i).is(0, "cont")) { - throw new SyntaxException(target.get(i).location, "Continue was placed outside a loop."); - } - } - } - } - - private long compileBody(CompileTarget target, ScopeRecord scope, boolean polute, BreakpointType bp) { - for (var i = 0; i < args.length; i++) { - for (var j = 0; j < i; j++) { - if (args[i].equals(args[j])) { - throw new SyntaxException(loc(), "Duplicate parameter '" + args[i] + "'."); - } - } - } - - var id = rand.nextLong(); - var subscope = scope.child(); - var subtarget = new CompileTarget(target.functions, target.breakpoints); - - subscope.define("this"); - var argsVar = subscope.define("arguments"); - - if (args.length > 0) { - for (var i = 0; i < args.length; i++) { - subtarget.add(Instruction.loadVar(loc(), argsVar)); - subtarget.add(Instruction.loadMember(loc(), i)); - subtarget.add(Instruction.storeVar(loc(), subscope.define(args[i]))); - } - } - - if (!statement && this.varName != null) { - subtarget.add(Instruction.storeSelfFunc(loc(), (int)subscope.define(this.varName))); - subtarget.setDebug(bp); - } - - body.declare(subscope); - body.compile(subtarget, subscope, false); - subtarget.add(Instruction.ret(end)); - checkBreakAndCont(subtarget, 0); - - if (polute) target.add(Instruction.loadFunc(loc(), id, subscope.getCaptures())); - target.functions.put(id, new FunctionBody( - subscope.localsCount(), args.length, - subtarget.array(), subscope.captures(), subscope.locals() - )); - - return id; - } - - public void compile(CompileTarget target, ScopeRecord scope, boolean pollute, String name, BreakpointType bp) { - if (this.varName != null) name = this.varName; - - var hasVar = this.varName != null && statement; - var hasName = name != null; - - compileBody(target, scope, pollute || hasVar || hasName, bp); - - if (hasName) { - if (pollute || hasVar) target.add(Instruction.dup(loc())); - target.add(Instruction.loadValue(loc(), "name")); - target.add(Instruction.loadValue(loc(), name)); - target.add(Instruction.storeMember(loc())); - } - - if (hasVar) { - var key = scope.getKey(this.varName); - - if (key instanceof String) target.add(Instruction.makeVar(loc(), (String)key)); - target.add(Instruction.storeVar(loc(), scope.getKey(this.varName), false)); - } - } - public void compile(CompileTarget target, ScopeRecord scope, boolean pollute, String name) { - compile(target, scope, pollute, name, BreakpointType.NONE); - } - @Override public void compile(CompileTarget target, ScopeRecord scope, boolean pollute, BreakpointType bp) { - compile(target, scope, pollute, (String)null, bp); - } - @Override public void compile(CompileTarget target, ScopeRecord scope, boolean pollute) { - compile(target, scope, pollute, (String)null, BreakpointType.NONE); - } - - public FunctionStatement(Location loc, Location end, String varName, String[] args, boolean statement, CompoundStatement body) { - super(loc); - - this.end = end; - this.varName = varName; - this.statement = statement; - - this.args = args; - this.body = body; - } - - public static void compileWithName(Statement stm, CompileTarget target, ScopeRecord scope, boolean pollute, String name) { - if (stm instanceof FunctionStatement) ((FunctionStatement)stm).compile(target, scope, pollute, name); - else stm.compile(target, scope, pollute); - } - public static void compileWithName(Statement stm, CompileTarget target, ScopeRecord scope, boolean pollute, String name, BreakpointType bp) { - if (stm instanceof FunctionStatement) ((FunctionStatement)stm).compile(target, scope, pollute, name, bp); - else stm.compile(target, scope, pollute, bp); - } -} diff --git a/src/java/me/topchetoeu/jscript/core/compilation/values/GlobalThisStatement.java b/src/java/me/topchetoeu/jscript/core/compilation/values/GlobalThisStatement.java deleted file mode 100644 index 4241479..0000000 --- a/src/java/me/topchetoeu/jscript/core/compilation/values/GlobalThisStatement.java +++ /dev/null @@ -1,20 +0,0 @@ -package me.topchetoeu.jscript.core.compilation.values; - -import me.topchetoeu.jscript.common.Location; -import me.topchetoeu.jscript.core.compilation.CompileTarget; -import me.topchetoeu.jscript.core.compilation.Instruction; -import me.topchetoeu.jscript.core.compilation.Statement; -import me.topchetoeu.jscript.core.engine.scope.ScopeRecord; - -public class GlobalThisStatement extends Statement { - @Override public boolean pure() { return true; } - - @Override - public void compile(CompileTarget target, ScopeRecord scope, boolean pollute) { - if (pollute) target.add(Instruction.loadGlob(loc())); - } - - public GlobalThisStatement(Location loc) { - super(loc); - } -} diff --git a/src/java/me/topchetoeu/jscript/core/compilation/values/IndexAssignStatement.java b/src/java/me/topchetoeu/jscript/core/compilation/values/IndexAssignStatement.java deleted file mode 100644 index 15f6a3d..0000000 --- a/src/java/me/topchetoeu/jscript/core/compilation/values/IndexAssignStatement.java +++ /dev/null @@ -1,48 +0,0 @@ -package me.topchetoeu.jscript.core.compilation.values; - -import me.topchetoeu.jscript.common.Location; -import me.topchetoeu.jscript.core.compilation.CompileTarget; -import me.topchetoeu.jscript.core.compilation.Instruction; -import me.topchetoeu.jscript.core.compilation.Statement; -import me.topchetoeu.jscript.core.compilation.Instruction.BreakpointType; -import me.topchetoeu.jscript.core.engine.Operation; -import me.topchetoeu.jscript.core.engine.scope.ScopeRecord; - -public class IndexAssignStatement extends Statement { - public final Statement object; - public final Statement index; - public final Statement value; - public final Operation operation; - - @Override - public void compile(CompileTarget target, ScopeRecord scope, boolean pollute) { - if (operation != null) { - object.compile(target, scope, true); - index.compile(target, scope, true); - target.add(Instruction.dup(loc(), 2)); - - target.add(Instruction.loadMember(loc())); - value.compile(target, scope, true); - target.add(Instruction.operation(loc(), operation)); - - target.add(Instruction.storeMember(loc(), pollute)); - target.setDebug(BreakpointType.STEP_IN); - } - else { - object.compile(target, scope, true); - index.compile(target, scope, true); - value.compile(target, scope, true); - - target.add(Instruction.storeMember(loc(), pollute)); - target.setDebug(BreakpointType.STEP_IN); - } - } - - public IndexAssignStatement(Location loc, Statement object, Statement index, Statement value, Operation operation) { - super(loc); - this.object = object; - this.index = index; - this.value = value; - this.operation = operation; - } -} diff --git a/src/java/me/topchetoeu/jscript/core/compilation/values/IndexStatement.java b/src/java/me/topchetoeu/jscript/core/compilation/values/IndexStatement.java deleted file mode 100644 index 8d38f1f..0000000 --- a/src/java/me/topchetoeu/jscript/core/compilation/values/IndexStatement.java +++ /dev/null @@ -1,49 +0,0 @@ -package me.topchetoeu.jscript.core.compilation.values; - -import me.topchetoeu.jscript.common.Location; -import me.topchetoeu.jscript.core.compilation.AssignableStatement; -import me.topchetoeu.jscript.core.compilation.CompileTarget; -import me.topchetoeu.jscript.core.compilation.Instruction; -import me.topchetoeu.jscript.core.compilation.Statement; -import me.topchetoeu.jscript.core.compilation.Instruction.BreakpointType; -import me.topchetoeu.jscript.core.engine.Operation; -import me.topchetoeu.jscript.core.engine.scope.ScopeRecord; - -public class IndexStatement extends AssignableStatement { - public final Statement object; - public final Statement index; - - @Override - public Statement toAssign(Statement val, Operation operation) { - return new IndexAssignStatement(loc(), object, index, val, operation); - } - public void compile(CompileTarget target, ScopeRecord scope, boolean dupObj, boolean pollute) { - object.compile(target, scope, true); - if (dupObj) target.add(Instruction.dup(loc())); - if (index instanceof ConstantStatement) { - target.add(Instruction.loadMember(loc(), ((ConstantStatement)index).value)); - target.setDebug(BreakpointType.STEP_IN); - return; - } - - index.compile(target, scope, true); - target.add(Instruction.loadMember(loc())); - target.setDebug(BreakpointType.STEP_IN); - if (!pollute) target.add(Instruction.discard(loc())); - } - @Override - public void compile(CompileTarget target, ScopeRecord scope, boolean pollute) { - compile(target, scope, false, pollute); - } - - public IndexStatement(Location loc, Statement object, Statement index) { - super(loc); - this.object = object; - this.index = index; - } - public IndexStatement(Location loc, Statement object, Object index) { - super(loc); - this.object = object; - this.index = new ConstantStatement(loc, index); - } -} diff --git a/src/java/me/topchetoeu/jscript/core/compilation/values/LazyAndStatement.java b/src/java/me/topchetoeu/jscript/core/compilation/values/LazyAndStatement.java deleted file mode 100644 index d5d83a2..0000000 --- a/src/java/me/topchetoeu/jscript/core/compilation/values/LazyAndStatement.java +++ /dev/null @@ -1,39 +0,0 @@ -package me.topchetoeu.jscript.core.compilation.values; - -import me.topchetoeu.jscript.common.Location; -import me.topchetoeu.jscript.core.compilation.CompileTarget; -import me.topchetoeu.jscript.core.compilation.Instruction; -import me.topchetoeu.jscript.core.compilation.Statement; -import me.topchetoeu.jscript.core.engine.scope.ScopeRecord; -import me.topchetoeu.jscript.core.engine.values.Values; - -public class LazyAndStatement extends Statement { - public final Statement first, second; - - @Override public boolean pure() { return first.pure() && second.pure(); } - - @Override - public void compile(CompileTarget target, ScopeRecord scope, boolean pollute) { - if (first instanceof ConstantStatement) { - if (Values.not(((ConstantStatement)first).value)) { - first.compile(target, scope, pollute); - } - else second.compile(target, scope, pollute); - return; - } - - first.compile(target, scope, true); - if (pollute) target.add(Instruction.dup(loc())); - int start = target.size(); - target.add(Instruction.nop(null)); - if (pollute) target.add(Instruction.discard(loc())); - second.compile(target, scope, pollute); - target.set(start, Instruction.jmpIfNot(loc(), target.size() - start)); - } - - public LazyAndStatement(Location loc, Statement first, Statement second) { - super(loc); - this.first = first; - this.second = second; - } -} diff --git a/src/java/me/topchetoeu/jscript/core/compilation/values/LazyOrStatement.java b/src/java/me/topchetoeu/jscript/core/compilation/values/LazyOrStatement.java deleted file mode 100644 index 42f3aa9..0000000 --- a/src/java/me/topchetoeu/jscript/core/compilation/values/LazyOrStatement.java +++ /dev/null @@ -1,39 +0,0 @@ -package me.topchetoeu.jscript.core.compilation.values; - -import me.topchetoeu.jscript.common.Location; -import me.topchetoeu.jscript.core.compilation.CompileTarget; -import me.topchetoeu.jscript.core.compilation.Instruction; -import me.topchetoeu.jscript.core.compilation.Statement; -import me.topchetoeu.jscript.core.engine.scope.ScopeRecord; -import me.topchetoeu.jscript.core.engine.values.Values; - -public class LazyOrStatement extends Statement { - public final Statement first, second; - - @Override public boolean pure() { return first.pure() && second.pure(); } - - @Override - public void compile(CompileTarget target, ScopeRecord scope, boolean pollute) { - if (first instanceof ConstantStatement) { - if (Values.not(((ConstantStatement)first).value)) { - second.compile(target, scope, pollute); - } - else first.compile(target, scope, pollute); - return; - } - - first.compile(target, scope, true); - if (pollute) target.add(Instruction.dup(loc())); - int start = target.size(); - target.add(Instruction.nop(null)); - if (pollute) target.add(Instruction.discard(loc())); - second.compile(target, scope, pollute); - target.set(start, Instruction.jmpIf(loc(), target.size() - start)); - } - - public LazyOrStatement(Location loc, Statement first, Statement second) { - super(loc); - this.first = first; - this.second = second; - } -} diff --git a/src/java/me/topchetoeu/jscript/core/compilation/values/ObjectStatement.java b/src/java/me/topchetoeu/jscript/core/compilation/values/ObjectStatement.java deleted file mode 100644 index 6400897..0000000 --- a/src/java/me/topchetoeu/jscript/core/compilation/values/ObjectStatement.java +++ /dev/null @@ -1,63 +0,0 @@ -package me.topchetoeu.jscript.core.compilation.values; - -import java.util.ArrayList; -import java.util.Map; - -import me.topchetoeu.jscript.common.Location; -import me.topchetoeu.jscript.core.compilation.CompileTarget; -import me.topchetoeu.jscript.core.compilation.Instruction; -import me.topchetoeu.jscript.core.compilation.Statement; -import me.topchetoeu.jscript.core.engine.scope.ScopeRecord; - -public class ObjectStatement extends Statement { - public final Map map; - public final Map getters; - public final Map setters; - - @Override public boolean pure() { - for (var el : map.values()) { - if (!el.pure()) return false; - } - - return true; - } - - @Override - public void compile(CompileTarget target, ScopeRecord scope, boolean pollute) { - target.add(Instruction.loadObj(loc())); - - for (var el : map.entrySet()) { - target.add(Instruction.dup(loc())); - target.add(Instruction.loadValue(loc(), el.getKey())); - var val = el.getValue(); - FunctionStatement.compileWithName(val, target, scope, true, el.getKey().toString()); - target.add(Instruction.storeMember(loc())); - } - - var keys = new ArrayList(); - keys.addAll(getters.keySet()); - keys.addAll(setters.keySet()); - - for (var key : keys) { - if (key instanceof String) target.add(Instruction.loadValue(loc(), (String)key)); - else target.add(Instruction.loadValue(loc(), (Double)key)); - - if (getters.containsKey(key)) getters.get(key).compile(target, scope, true); - else target.add(Instruction.loadValue(loc(), null)); - - if (setters.containsKey(key)) setters.get(key).compile(target, scope, true); - else target.add(Instruction.loadValue(loc(), null)); - - target.add(Instruction.defProp(loc())); - } - - if (!pollute) target.add(Instruction.discard(loc())); - } - - public ObjectStatement(Location loc, Map map, Map getters, Map setters) { - super(loc); - this.map = map; - this.getters = getters; - this.setters = setters; - } -} diff --git a/src/java/me/topchetoeu/jscript/core/compilation/values/OperationStatement.java b/src/java/me/topchetoeu/jscript/core/compilation/values/OperationStatement.java deleted file mode 100644 index 4a42755..0000000 --- a/src/java/me/topchetoeu/jscript/core/compilation/values/OperationStatement.java +++ /dev/null @@ -1,37 +0,0 @@ -package me.topchetoeu.jscript.core.compilation.values; - -import me.topchetoeu.jscript.common.Location; -import me.topchetoeu.jscript.core.compilation.CompileTarget; -import me.topchetoeu.jscript.core.compilation.Instruction; -import me.topchetoeu.jscript.core.compilation.Statement; -import me.topchetoeu.jscript.core.engine.Operation; -import me.topchetoeu.jscript.core.engine.scope.ScopeRecord; - -public class OperationStatement extends Statement { - public final Statement[] args; - public final Operation operation; - - @Override public boolean pure() { - for (var el : args) { - if (!el.pure()) return false; - } - - return true; - } - - @Override - public void compile(CompileTarget target, ScopeRecord scope, boolean pollute) { - for (var arg : args) { - arg.compile(target, scope, true); - } - - if (pollute) target.add(Instruction.operation(loc(), operation)); - else target.add(Instruction.discard(loc())); - } - - public OperationStatement(Location loc, Operation operation, Statement ...args) { - super(loc); - this.operation = operation; - this.args = args; - } -} diff --git a/src/java/me/topchetoeu/jscript/core/compilation/values/RegexStatement.java b/src/java/me/topchetoeu/jscript/core/compilation/values/RegexStatement.java deleted file mode 100644 index b3bd04b..0000000 --- a/src/java/me/topchetoeu/jscript/core/compilation/values/RegexStatement.java +++ /dev/null @@ -1,26 +0,0 @@ -package me.topchetoeu.jscript.core.compilation.values; - -import me.topchetoeu.jscript.common.Location; -import me.topchetoeu.jscript.core.compilation.CompileTarget; -import me.topchetoeu.jscript.core.compilation.Instruction; -import me.topchetoeu.jscript.core.compilation.Statement; -import me.topchetoeu.jscript.core.engine.scope.ScopeRecord; - -public class RegexStatement extends Statement { - public final String pattern, flags; - - // Not really pure, since a function is called, but can be ignored. - @Override public boolean pure() { return true; } - - @Override - public void compile(CompileTarget target, ScopeRecord scope, boolean pollute) { - target.add(Instruction.loadRegex(loc(), pattern, flags)); - if (!pollute) target.add(Instruction.discard(loc())); - } - - public RegexStatement(Location loc, String pattern, String flags) { - super(loc); - this.pattern = pattern; - this.flags = flags; - } -} diff --git a/src/java/me/topchetoeu/jscript/core/compilation/values/VariableAssignStatement.java b/src/java/me/topchetoeu/jscript/core/compilation/values/VariableAssignStatement.java deleted file mode 100644 index 8208b49..0000000 --- a/src/java/me/topchetoeu/jscript/core/compilation/values/VariableAssignStatement.java +++ /dev/null @@ -1,38 +0,0 @@ -package me.topchetoeu.jscript.core.compilation.values; - -import me.topchetoeu.jscript.common.Location; -import me.topchetoeu.jscript.core.compilation.CompileTarget; -import me.topchetoeu.jscript.core.compilation.Instruction; -import me.topchetoeu.jscript.core.compilation.Statement; -import me.topchetoeu.jscript.core.engine.Operation; -import me.topchetoeu.jscript.core.engine.scope.ScopeRecord; - -public class VariableAssignStatement extends Statement { - public final String name; - public final Statement value; - public final Operation operation; - - @Override public boolean pure() { return false; } - - @Override - public void compile(CompileTarget target, ScopeRecord scope, boolean pollute) { - var i = scope.getKey(name); - if (operation != null) { - target.add(Instruction.loadVar(loc(), i)); - FunctionStatement.compileWithName(value, target, scope, true, name); - target.add(Instruction.operation(loc(), operation)); - target.add(Instruction.storeVar(loc(), i, pollute)); - } - else { - FunctionStatement.compileWithName(value, target, scope, true, name); - target.add(Instruction.storeVar(loc(), i, pollute)); - } - } - - public VariableAssignStatement(Location loc, String name, Statement val, Operation operation) { - super(loc); - this.name = name; - this.value = val; - this.operation = operation; - } -} diff --git a/src/java/me/topchetoeu/jscript/core/compilation/values/VariableIndexStatement.java b/src/java/me/topchetoeu/jscript/core/compilation/values/VariableIndexStatement.java deleted file mode 100644 index 739df12..0000000 --- a/src/java/me/topchetoeu/jscript/core/compilation/values/VariableIndexStatement.java +++ /dev/null @@ -1,23 +0,0 @@ -package me.topchetoeu.jscript.core.compilation.values; - -import me.topchetoeu.jscript.common.Location; -import me.topchetoeu.jscript.core.compilation.CompileTarget; -import me.topchetoeu.jscript.core.compilation.Instruction; -import me.topchetoeu.jscript.core.compilation.Statement; -import me.topchetoeu.jscript.core.engine.scope.ScopeRecord; - -public class VariableIndexStatement extends Statement { - public final int index; - - @Override public boolean pure() { return true; } - - @Override - public void compile(CompileTarget target, ScopeRecord scope, boolean pollute) { - if (pollute) target.add(Instruction.loadVar(loc(), index)); - } - - public VariableIndexStatement(Location loc, int i) { - super(loc); - this.index = i; - } -} diff --git a/src/java/me/topchetoeu/jscript/core/compilation/values/VariableStatement.java b/src/java/me/topchetoeu/jscript/core/compilation/values/VariableStatement.java deleted file mode 100644 index 7b258d2..0000000 --- a/src/java/me/topchetoeu/jscript/core/compilation/values/VariableStatement.java +++ /dev/null @@ -1,32 +0,0 @@ -package me.topchetoeu.jscript.core.compilation.values; - -import me.topchetoeu.jscript.common.Location; -import me.topchetoeu.jscript.core.compilation.AssignableStatement; -import me.topchetoeu.jscript.core.compilation.CompileTarget; -import me.topchetoeu.jscript.core.compilation.Instruction; -import me.topchetoeu.jscript.core.compilation.Statement; -import me.topchetoeu.jscript.core.engine.Operation; -import me.topchetoeu.jscript.core.engine.scope.ScopeRecord; - -public class VariableStatement extends AssignableStatement { - public final String name; - - @Override public boolean pure() { return false; } - - @Override - public Statement toAssign(Statement val, Operation operation) { - return new VariableAssignStatement(loc(), name, val, operation); - } - - @Override - public void compile(CompileTarget target, ScopeRecord scope, boolean pollute) { - var i = scope.getKey(name); - target.add(Instruction.loadVar(loc(), i)); - if (!pollute) target.add(Instruction.discard(loc())); - } - - public VariableStatement(Location loc, String name) { - super(loc); - this.name = name; - } -} diff --git a/src/java/me/topchetoeu/jscript/core/debug/DebugContext.java b/src/java/me/topchetoeu/jscript/core/debug/DebugContext.java new file mode 100644 index 0000000..b94287a --- /dev/null +++ b/src/java/me/topchetoeu/jscript/core/debug/DebugContext.java @@ -0,0 +1,129 @@ +package me.topchetoeu.jscript.core.debug; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.WeakHashMap; + +import me.topchetoeu.jscript.common.Filename; +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.core.Context; +import me.topchetoeu.jscript.core.Extensions; +import me.topchetoeu.jscript.core.Frame; +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"); + + private HashMap sources; + private WeakHashMap maps; + private DebugController debugger; + + public boolean attachDebugger(DebugController debugger) { + if (this.debugger != null) return false; + + if (sources != null) { + for (var source : sources.entrySet()) debugger.onSource(source.getKey(), source.getValue()); + } + + this.debugger = debugger; + return true; + } + public boolean detachDebugger() { + this.debugger = null; + return true; + } + + public DebugController debugger() { + if (debugger == null) return DebugController.empty(); + else return debugger; + } + + public FunctionMap getMap(FunctionBody func) { + if (maps == null) return null; + return maps.get(func); + } + public FunctionMap getMap(FunctionValue func) { + if (maps == null || !(func instanceof CodeFunction)) return null; + return getMap(((CodeFunction)func).body); + } + public FunctionMap getMapOrEmpty(FunctionBody func) { + if (maps == null) return FunctionMap.EMPTY; + var res = maps.get(func); + if (res == null) return FunctionMap.EMPTY; + else return res; + } + public FunctionMap getMapOrEmpty(FunctionValue func) { + if (maps == null || !(func instanceof CodeFunction)) return null; + return getMapOrEmpty(((CodeFunction)func).body); + } + + @Override public void onFramePop(Context ctx, Frame frame) { + if (debugger != null) debugger.onFramePop(ctx, frame); + } + @Override 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) { + 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); + if (sources != null) sources.put(filename, source); + } + + private DebugContext(boolean enabled) { + if (enabled) { + sources = new HashMap<>(); + maps = new WeakHashMap<>(); + } + } + + public DebugContext() { + this(true); + } + + public static boolean enabled(Extensions exts) { + return exts.hasNotNull(ENV_KEY) && !exts.has(IGNORE); + } + public static DebugContext get(Extensions exts) { + if (enabled(exts)) return exts.get(ENV_KEY); + else return new DebugContext(false); + } + + public static List stackTrace(Context ctx) { + var res = new ArrayList(); + var dbgCtx = get(ctx); + + for (var el : ctx.frames()) { + var name = el.function.name; + + var map = dbgCtx.getMap(el.function); + Location loc = null; + + if (map != null) { + loc = map.toLocation(el.codePtr, true); + if (loc == null) loc = map.start(); + } + + var trace = ""; + + if (loc != null) trace += "at " + loc.toString() + " "; + if (name != null && !name.equals("")) trace += "in " + name + " "; + + trace = trace.trim(); + + if (!trace.equals("")) res.add(trace); + } + + return res; + } +} diff --git a/src/java/me/topchetoeu/jscript/core/engine/debug/DebugController.java b/src/java/me/topchetoeu/jscript/core/debug/DebugController.java similarity index 62% rename from src/java/me/topchetoeu/jscript/core/engine/debug/DebugController.java rename to src/java/me/topchetoeu/jscript/core/debug/DebugController.java index 93c10c7..e94e958 100644 --- a/src/java/me/topchetoeu/jscript/core/engine/debug/DebugController.java +++ b/src/java/me/topchetoeu/jscript/core/debug/DebugController.java @@ -1,14 +1,10 @@ -package me.topchetoeu.jscript.core.engine.debug; - -import java.util.TreeSet; +package me.topchetoeu.jscript.core.debug; import me.topchetoeu.jscript.common.Filename; -import me.topchetoeu.jscript.common.Location; -import me.topchetoeu.jscript.core.compilation.Instruction; -import me.topchetoeu.jscript.core.engine.Context; -import me.topchetoeu.jscript.core.engine.frame.CodeFrame; +import me.topchetoeu.jscript.compilation.Instruction; +import me.topchetoeu.jscript.core.Context; +import me.topchetoeu.jscript.core.Frame; import me.topchetoeu.jscript.core.exceptions.EngineException; -import me.topchetoeu.jscript.utils.mapping.SourceMap; public interface DebugController { /** @@ -18,7 +14,7 @@ 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, TreeSet breakpoints, SourceMap map); + void onSource(Filename filename, String source); /** * Called immediatly before an instruction is executed, as well as after an instruction, if it has threw or returned. @@ -26,13 +22,12 @@ public interface DebugController { * @param ctx The context of execution * @param frame The frame in which execution is occuring * @param instruction The instruction which was or will be executed - * @param loc The most recent location the code frame has been at * @param returnVal The return value of the instruction, Values.NO_RETURN if none * @param error The error that the instruction threw, null if none * @param caught Whether or not the error has been caught - * @return Whether or not the frame should restart + * @return Whether or not the frame should restart (currently does nothing) */ - boolean onInstruction(Context ctx, CodeFrame frame, Instruction instruction, Object returnVal, EngineException error, boolean caught); + boolean onInstruction(Context ctx, Frame frame, Instruction instruction, Object returnVal, EngineException error, boolean caught); /** * Called immediatly before a frame has been pushed on the frame stack. @@ -40,23 +35,23 @@ public interface DebugController { * @param ctx The context of execution * @param frame The code frame which was pushed */ - void onFramePush(Context ctx, CodeFrame frame); + void onFramePush(Context ctx, Frame frame); /** * Called immediatly after a frame has been popped out of the frame stack. * This function might pause in order to await debugging commands. * @param ctx The context of execution * @param frame The code frame which was popped out */ - void onFramePop(Context ctx, CodeFrame frame); + void onFramePop(Context ctx, Frame frame); public static DebugController empty() { return new DebugController () { - @Override public void onFramePop(Context ctx, CodeFrame frame) { } - @Override public void onFramePush(Context ctx, CodeFrame frame) { } - @Override public boolean onInstruction(Context ctx, CodeFrame frame, Instruction instruction, Object returnVal, EngineException error, boolean caught) { + @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, TreeSet breakpoints, SourceMap map) { } + @Override public void onSource(Filename filename, String source) { } }; } } diff --git a/src/java/me/topchetoeu/jscript/core/engine/Operation.java b/src/java/me/topchetoeu/jscript/core/engine/Operation.java deleted file mode 100644 index 7ea7c8f..0000000 --- a/src/java/me/topchetoeu/jscript/core/engine/Operation.java +++ /dev/null @@ -1,42 +0,0 @@ -package me.topchetoeu.jscript.core.engine; - -public enum Operation { - INSTANCEOF(2, false), - IN(2, false), - - MULTIPLY(2, true), - DIVIDE(2, true), - MODULO(2, true), - ADD(2, true), - SUBTRACT(2, true), - - USHIFT_RIGHT(2, true), - SHIFT_RIGHT(2, true), - SHIFT_LEFT(2, true), - - GREATER(2, true), - LESS(2, true), - GREATER_EQUALS(2, true), - LESS_EQUALS(2, true), - LOOSE_EQUALS(2, true), - LOOSE_NOT_EQUALS(2, true), - EQUALS(2, true), - NOT_EQUALS(2, true), - - AND(2, true), - OR(2, true), - XOR(2, true), - - NEG(1, true), - POS(1, true), - NOT(1, true), - INVERSE(1, true); - - public final int operands; - public final boolean optimizable; - - private Operation(int n, boolean opt) { - this.operands = n; - this.optimizable = opt; - } -} diff --git a/src/java/me/topchetoeu/jscript/core/engine/debug/DebugContext.java b/src/java/me/topchetoeu/jscript/core/engine/debug/DebugContext.java deleted file mode 100644 index fefcd75..0000000 --- a/src/java/me/topchetoeu/jscript/core/engine/debug/DebugContext.java +++ /dev/null @@ -1,100 +0,0 @@ -package me.topchetoeu.jscript.core.engine.debug; - -import java.util.HashMap; -import java.util.TreeSet; - -import me.topchetoeu.jscript.common.Filename; -import me.topchetoeu.jscript.common.Location; -import me.topchetoeu.jscript.core.compilation.Instruction; -import me.topchetoeu.jscript.core.engine.Context; -import me.topchetoeu.jscript.core.engine.Extensions; -import me.topchetoeu.jscript.core.engine.frame.CodeFrame; -import me.topchetoeu.jscript.core.engine.values.Symbol; -import me.topchetoeu.jscript.core.exceptions.EngineException; -import me.topchetoeu.jscript.utils.mapping.SourceMap; - -public class DebugContext implements DebugController { - public static final Symbol ENV_KEY = Symbol.get("Engine.debug"); - public static final Symbol IGNORE = Symbol.get("Engine.ignoreDebug"); - - private HashMap sources; - private HashMap> bpts; - private HashMap maps; - private DebugController debugger; - - public boolean attachDebugger(DebugController debugger) { - if (this.debugger != null) return false; - - if (sources != null) { - for (var source : sources.entrySet()) debugger.onSource( - source.getKey(), source.getValue(), - bpts.get(source.getKey()), - maps.get(source.getKey()) - ); - } - - this.debugger = debugger; - return true; - } - public boolean detachDebugger() { - this.debugger = null; - return true; - } - - public DebugController debugger() { - if (debugger == null) return DebugController.empty(); - else return debugger; - } - - @Override public void onFramePop(Context ctx, CodeFrame frame) { - if (debugger != null) debugger.onFramePop(ctx, frame); - } - @Override public void onFramePush(Context ctx, CodeFrame frame) { - if (debugger != null) debugger.onFramePush(ctx, frame); - } - @Override public boolean onInstruction(Context ctx, CodeFrame 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, TreeSet breakpoints, SourceMap map) { - if (debugger != null) debugger.onSource(filename, source, breakpoints, map); - if (sources != null) sources.put(filename, source); - if (bpts != null) bpts.put(filename, breakpoints); - if (maps != null) maps.put(filename, map); - } - - public Location mapToCompiled(Location location) { - if (maps == null) return location; - - var map = maps.get(location.filename()); - if (map == null) return location; - return map.toCompiled(location); - } - public Location mapToOriginal(Location location) { - if (maps == null) return location; - - var map = maps.get(location.filename()); - if (map == null) return location; - return map.toOriginal(location); - } - - private DebugContext(boolean enabled) { - if (enabled) { - sources = new HashMap<>(); - bpts = new HashMap<>(); - maps = new HashMap<>(); - } - } - - public DebugContext() { - this(true); - } - - public static boolean enabled(Extensions exts) { - return exts.hasNotNull(ENV_KEY) && !exts.has(IGNORE); - } - public static DebugContext get(Extensions exts) { - if (enabled(exts)) return exts.get(ENV_KEY); - else return new DebugContext(false); - } -} diff --git a/src/java/me/topchetoeu/jscript/core/engine/values/CodeFunction.java b/src/java/me/topchetoeu/jscript/core/engine/values/CodeFunction.java deleted file mode 100644 index 1ab8c9d..0000000 --- a/src/java/me/topchetoeu/jscript/core/engine/values/CodeFunction.java +++ /dev/null @@ -1,57 +0,0 @@ -package me.topchetoeu.jscript.core.engine.values; - -import me.topchetoeu.jscript.common.Location; -import me.topchetoeu.jscript.core.compilation.FunctionBody; -import me.topchetoeu.jscript.core.compilation.Instruction; -import me.topchetoeu.jscript.core.engine.Context; -import me.topchetoeu.jscript.core.engine.Environment; -import me.topchetoeu.jscript.core.engine.frame.CodeFrame; -import me.topchetoeu.jscript.core.engine.scope.ValueVariable; - -public class CodeFunction extends FunctionValue { - public final int localsN; - public final Instruction[] body; - public final String[] captureNames, localNames; - public final ValueVariable[] captures; - public Environment environment; - - public Location loc() { - for (var instr : body) { - if (instr.location != null) return instr.location; - } - return null; - } - public String readable() { - var loc = loc(); - if (loc == null) return name; - else if (name.equals("")) return loc.toString(); - else return name + "@" + loc; - } - - @Override - public Object call(Context ctx, Object thisArg, Object ...args) { - var frame = new CodeFrame(ctx, thisArg, args, this); - - frame.onPush(); - - try { - while (true) { - var res = frame.next(Values.NO_RETURN, Values.NO_RETURN, null); - if (res != Values.NO_RETURN) return res; - } - } - finally { - frame.onPop(); - } - } - - public CodeFunction(Environment environment, String name, FunctionBody body, ValueVariable... captures) { - super(name, body.argsN); - this.captures = captures; - this.captureNames = body.captureNames; - this.localNames = body.localNames; - this.environment = environment; - this.localsN = body.localsN; - this.body = body.instructions; - } -} diff --git a/src/java/me/topchetoeu/jscript/core/exceptions/EngineException.java b/src/java/me/topchetoeu/jscript/core/exceptions/EngineException.java index c383f35..27ed22e 100644 --- a/src/java/me/topchetoeu/jscript/core/exceptions/EngineException.java +++ b/src/java/me/topchetoeu/jscript/core/exceptions/EngineException.java @@ -4,18 +4,17 @@ import java.util.ArrayList; import java.util.List; import me.topchetoeu.jscript.common.Location; -import me.topchetoeu.jscript.core.engine.Context; -import me.topchetoeu.jscript.core.engine.Engine; -import me.topchetoeu.jscript.core.engine.Environment; -import me.topchetoeu.jscript.core.engine.debug.DebugContext; -import me.topchetoeu.jscript.core.engine.values.ObjectValue; -import me.topchetoeu.jscript.core.engine.values.Values; -import me.topchetoeu.jscript.core.engine.values.ObjectValue.PlaceholderProto; +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; +import me.topchetoeu.jscript.core.values.ObjectValue.PlaceholderProto; public class EngineException extends RuntimeException { public static class StackElement { public final Location location; - public final String function; + public final String name; public final Context ctx; public boolean visible() { @@ -25,22 +24,20 @@ public class EngineException extends RuntimeException { var res = ""; var loc = location; - if (loc != null && ctx != null && ctx.engine != null) loc = DebugContext.get(ctx).mapToCompiled(loc); - if (loc != null) res += "at " + loc.toString() + " "; - if (function != null && !function.equals("")) res += "in " + function + " "; + if (name != null && !name.equals("")) res += "in " + name + " "; return res.trim(); } - public StackElement(Context ctx, Location location, String function) { - if (function != null) function = function.trim(); - if (function.equals("")) function = null; + public StackElement(Context ctx, Location location, String name) { + if (name != null) name = name.trim(); + if (name.equals("")) name = null; if (ctx == null) this.ctx = null; else this.ctx = new Context(ctx.engine, ctx.environment); this.location = location; - this.function = function; + this.name = name; } } @@ -52,8 +49,8 @@ public class EngineException extends RuntimeException { public EngineException add(Context ctx, String name, Location location) { var el = new StackElement(ctx, location, name); - if (el.function == null && el.location == null) return this; - setCtx(ctx.environment, ctx.engine); + if (el.name == null && el.location == null) return this; + setCtx(ctx); stackTrace.add(el); return this; } @@ -61,11 +58,6 @@ public class EngineException extends RuntimeException { this.cause = cause; return this; } - public EngineException setCtx(Environment env, Engine engine) { - if (this.env == null) this.env = env; - if (this.engine == null) this.engine = engine; - return this; - } public EngineException setCtx(Context ctx) { if (this.env == null) this.env = ctx.environment; if (this.engine == null) this.engine = ctx.engine; @@ -108,9 +100,6 @@ public class EngineException extends RuntimeException { public static EngineException ofError(String msg) { return new EngineException(err(null, msg, PlaceholderProto.ERROR)); } - public static EngineException ofSyntax(SyntaxException e) { - return new EngineException(err(null, e.msg, PlaceholderProto.SYNTAX_ERROR)).add(null, null, e.loc); - } public static EngineException ofSyntax(String msg) { return new EngineException(err(null, msg, PlaceholderProto.SYNTAX_ERROR)); } diff --git a/src/java/me/topchetoeu/jscript/core/engine/scope/GlobalScope.java b/src/java/me/topchetoeu/jscript/core/scope/GlobalScope.java similarity index 87% rename from src/java/me/topchetoeu/jscript/core/engine/scope/GlobalScope.java rename to src/java/me/topchetoeu/jscript/core/scope/GlobalScope.java index 59070e1..200296a 100644 --- a/src/java/me/topchetoeu/jscript/core/engine/scope/GlobalScope.java +++ b/src/java/me/topchetoeu/jscript/core/scope/GlobalScope.java @@ -1,13 +1,14 @@ -package me.topchetoeu.jscript.core.engine.scope; +package me.topchetoeu.jscript.core.scope; import java.util.HashSet; import java.util.Set; -import me.topchetoeu.jscript.core.engine.Context; -import me.topchetoeu.jscript.core.engine.values.FunctionValue; -import me.topchetoeu.jscript.core.engine.values.NativeFunction; -import me.topchetoeu.jscript.core.engine.values.ObjectValue; -import me.topchetoeu.jscript.core.engine.values.Values; +import me.topchetoeu.jscript.common.ScopeRecord; +import me.topchetoeu.jscript.core.Context; +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; public class GlobalScope implements ScopeRecord { diff --git a/src/java/me/topchetoeu/jscript/core/engine/scope/LocalScope.java b/src/java/me/topchetoeu/jscript/core/scope/LocalScope.java similarity index 93% rename from src/java/me/topchetoeu/jscript/core/engine/scope/LocalScope.java rename to src/java/me/topchetoeu/jscript/core/scope/LocalScope.java index 5b5527f..0716041 100644 --- a/src/java/me/topchetoeu/jscript/core/engine/scope/LocalScope.java +++ b/src/java/me/topchetoeu/jscript/core/scope/LocalScope.java @@ -1,4 +1,4 @@ -package me.topchetoeu.jscript.core.engine.scope; +package me.topchetoeu.jscript.core.scope; import java.util.ArrayList; diff --git a/src/java/me/topchetoeu/jscript/core/engine/scope/LocalScopeRecord.java b/src/java/me/topchetoeu/jscript/core/scope/LocalScopeRecord.java similarity index 95% rename from src/java/me/topchetoeu/jscript/core/engine/scope/LocalScopeRecord.java rename to src/java/me/topchetoeu/jscript/core/scope/LocalScopeRecord.java index 0fa9d99..174686b 100644 --- a/src/java/me/topchetoeu/jscript/core/engine/scope/LocalScopeRecord.java +++ b/src/java/me/topchetoeu/jscript/core/scope/LocalScopeRecord.java @@ -1,7 +1,9 @@ -package me.topchetoeu.jscript.core.engine.scope; +package me.topchetoeu.jscript.core.scope; import java.util.ArrayList; +import me.topchetoeu.jscript.common.ScopeRecord; + public class LocalScopeRecord implements ScopeRecord { public final LocalScopeRecord parent; diff --git a/src/java/me/topchetoeu/jscript/core/engine/scope/ValueVariable.java b/src/java/me/topchetoeu/jscript/core/scope/ValueVariable.java similarity index 77% rename from src/java/me/topchetoeu/jscript/core/engine/scope/ValueVariable.java rename to src/java/me/topchetoeu/jscript/core/scope/ValueVariable.java index 461f23e..21ffada 100644 --- a/src/java/me/topchetoeu/jscript/core/engine/scope/ValueVariable.java +++ b/src/java/me/topchetoeu/jscript/core/scope/ValueVariable.java @@ -1,7 +1,7 @@ -package me.topchetoeu.jscript.core.engine.scope; +package me.topchetoeu.jscript.core.scope; -import me.topchetoeu.jscript.core.engine.Context; -import me.topchetoeu.jscript.core.engine.values.Values; +import me.topchetoeu.jscript.core.Context; +import me.topchetoeu.jscript.core.values.Values; public class ValueVariable implements Variable { public boolean readonly; diff --git a/src/java/me/topchetoeu/jscript/core/engine/scope/Variable.java b/src/java/me/topchetoeu/jscript/core/scope/Variable.java similarity index 61% rename from src/java/me/topchetoeu/jscript/core/engine/scope/Variable.java rename to src/java/me/topchetoeu/jscript/core/scope/Variable.java index 656095f..731259c 100644 --- a/src/java/me/topchetoeu/jscript/core/engine/scope/Variable.java +++ b/src/java/me/topchetoeu/jscript/core/scope/Variable.java @@ -1,6 +1,6 @@ -package me.topchetoeu.jscript.core.engine.scope; +package me.topchetoeu.jscript.core.scope; -import me.topchetoeu.jscript.core.engine.Context; +import me.topchetoeu.jscript.core.Context; public interface Variable { Object get(Context ctx); diff --git a/src/java/me/topchetoeu/jscript/core/engine/values/ArrayValue.java b/src/java/me/topchetoeu/jscript/core/values/ArrayValue.java similarity index 98% rename from src/java/me/topchetoeu/jscript/core/engine/values/ArrayValue.java rename to src/java/me/topchetoeu/jscript/core/values/ArrayValue.java index a6c749c..180567a 100644 --- a/src/java/me/topchetoeu/jscript/core/engine/values/ArrayValue.java +++ b/src/java/me/topchetoeu/jscript/core/values/ArrayValue.java @@ -1,4 +1,4 @@ -package me.topchetoeu.jscript.core.engine.values; +package me.topchetoeu.jscript.core.values; import java.util.Arrays; import java.util.Collection; @@ -6,7 +6,7 @@ import java.util.Comparator; import java.util.Iterator; import java.util.List; -import me.topchetoeu.jscript.core.engine.Context; +import me.topchetoeu.jscript.core.Context; // TODO: Make methods generic public class ArrayValue extends ObjectValue implements Iterable { diff --git a/src/java/me/topchetoeu/jscript/core/values/CodeFunction.java b/src/java/me/topchetoeu/jscript/core/values/CodeFunction.java new file mode 100644 index 0000000..e4e2a00 --- /dev/null +++ b/src/java/me/topchetoeu/jscript/core/values/CodeFunction.java @@ -0,0 +1,50 @@ +package me.topchetoeu.jscript.core.values; + +import me.topchetoeu.jscript.compilation.FunctionBody; +import me.topchetoeu.jscript.core.Context; +import me.topchetoeu.jscript.core.Environment; +import me.topchetoeu.jscript.core.Frame; +import me.topchetoeu.jscript.core.scope.ValueVariable; + +public class CodeFunction extends FunctionValue { + public final FunctionBody body; + public final ValueVariable[] captures; + public Environment environment; + + // public Location loc() { + // for (var instr : body.instructions) { + // if (instr.location != null) return instr.location; + // } + // return null; + // } + // public String readable() { + // var loc = loc(); + // if (loc == null) return name; + // else if (name.equals("")) return loc.toString(); + // else return name + "@" + loc; + // } + + @Override + public Object call(Context ctx, Object thisArg, Object ...args) { + var frame = new Frame(ctx, thisArg, args, this); + + frame.onPush(); + + try { + while (true) { + var res = frame.next(Values.NO_RETURN, Values.NO_RETURN, null); + if (res != Values.NO_RETURN) return res; + } + } + finally { + frame.onPop(); + } + } + + public CodeFunction(Environment environment, String name, FunctionBody body, ValueVariable[] captures) { + super(name, body.argsN); + this.captures = captures; + this.environment = environment; + this.body = body; + } +} diff --git a/src/java/me/topchetoeu/jscript/core/engine/frame/ConvertHint.java b/src/java/me/topchetoeu/jscript/core/values/ConvertHint.java similarity index 52% rename from src/java/me/topchetoeu/jscript/core/engine/frame/ConvertHint.java rename to src/java/me/topchetoeu/jscript/core/values/ConvertHint.java index 5b5fabf..536eb28 100644 --- a/src/java/me/topchetoeu/jscript/core/engine/frame/ConvertHint.java +++ b/src/java/me/topchetoeu/jscript/core/values/ConvertHint.java @@ -1,4 +1,4 @@ -package me.topchetoeu.jscript.core.engine.frame; +package me.topchetoeu.jscript.core.values; public enum ConvertHint { TOSTRING, diff --git a/src/java/me/topchetoeu/jscript/core/engine/values/FunctionValue.java b/src/java/me/topchetoeu/jscript/core/values/FunctionValue.java similarity index 95% rename from src/java/me/topchetoeu/jscript/core/engine/values/FunctionValue.java rename to src/java/me/topchetoeu/jscript/core/values/FunctionValue.java index 61178dc..e4556f5 100644 --- a/src/java/me/topchetoeu/jscript/core/engine/values/FunctionValue.java +++ b/src/java/me/topchetoeu/jscript/core/values/FunctionValue.java @@ -1,8 +1,8 @@ -package me.topchetoeu.jscript.core.engine.values; +package me.topchetoeu.jscript.core.values; import java.util.List; -import me.topchetoeu.jscript.core.engine.Context; +import me.topchetoeu.jscript.core.Context; public abstract class FunctionValue extends ObjectValue { public String name = ""; diff --git a/src/java/me/topchetoeu/jscript/core/engine/values/NativeFunction.java b/src/java/me/topchetoeu/jscript/core/values/NativeFunction.java similarity index 86% rename from src/java/me/topchetoeu/jscript/core/engine/values/NativeFunction.java rename to src/java/me/topchetoeu/jscript/core/values/NativeFunction.java index 0e519f4..3b21256 100644 --- a/src/java/me/topchetoeu/jscript/core/engine/values/NativeFunction.java +++ b/src/java/me/topchetoeu/jscript/core/values/NativeFunction.java @@ -1,6 +1,6 @@ -package me.topchetoeu.jscript.core.engine.values; +package me.topchetoeu.jscript.core.values; -import me.topchetoeu.jscript.core.engine.Context; +import me.topchetoeu.jscript.core.Context; import me.topchetoeu.jscript.utils.interop.Arguments; public class NativeFunction extends FunctionValue { diff --git a/src/java/me/topchetoeu/jscript/core/engine/values/NativeWrapper.java b/src/java/me/topchetoeu/jscript/core/values/NativeWrapper.java similarity index 88% rename from src/java/me/topchetoeu/jscript/core/engine/values/NativeWrapper.java rename to src/java/me/topchetoeu/jscript/core/values/NativeWrapper.java index 05a05c6..cb7b6e3 100644 --- a/src/java/me/topchetoeu/jscript/core/engine/values/NativeWrapper.java +++ b/src/java/me/topchetoeu/jscript/core/values/NativeWrapper.java @@ -1,6 +1,6 @@ -package me.topchetoeu.jscript.core.engine.values; +package me.topchetoeu.jscript.core.values; -import me.topchetoeu.jscript.core.engine.Context; +import me.topchetoeu.jscript.core.Context; public class NativeWrapper extends ObjectValue { private static final Object NATIVE_PROTO = new Object(); diff --git a/src/java/me/topchetoeu/jscript/core/engine/values/ObjectValue.java b/src/java/me/topchetoeu/jscript/core/values/ObjectValue.java similarity index 98% rename from src/java/me/topchetoeu/jscript/core/engine/values/ObjectValue.java rename to src/java/me/topchetoeu/jscript/core/values/ObjectValue.java index d7e4175..81efb39 100644 --- a/src/java/me/topchetoeu/jscript/core/engine/values/ObjectValue.java +++ b/src/java/me/topchetoeu/jscript/core/values/ObjectValue.java @@ -1,4 +1,4 @@ -package me.topchetoeu.jscript.core.engine.values; +package me.topchetoeu.jscript.core.values; import java.util.ArrayList; import java.util.LinkedHashMap; @@ -6,8 +6,8 @@ import java.util.LinkedHashSet; import java.util.List; import java.util.Map; -import me.topchetoeu.jscript.core.engine.Context; -import me.topchetoeu.jscript.core.engine.Environment; +import me.topchetoeu.jscript.core.Context; +import me.topchetoeu.jscript.core.Environment; public class ObjectValue { public static enum PlaceholderProto { @@ -282,7 +282,7 @@ public class ObjectValue { return true; } else if (val instanceof ObjectValue) { - var obj = Values.object(val); + var obj = (ObjectValue)val; if (ctx != null) { if (obj == ctx.get(Environment.OBJECT_PROTO)) prototype = OBJ_PROTO; diff --git a/src/java/me/topchetoeu/jscript/core/engine/values/ScopeValue.java b/src/java/me/topchetoeu/jscript/core/values/ScopeValue.java similarity index 90% rename from src/java/me/topchetoeu/jscript/core/engine/values/ScopeValue.java rename to src/java/me/topchetoeu/jscript/core/values/ScopeValue.java index 2094dd9..a5b145c 100644 --- a/src/java/me/topchetoeu/jscript/core/engine/values/ScopeValue.java +++ b/src/java/me/topchetoeu/jscript/core/values/ScopeValue.java @@ -1,10 +1,10 @@ -package me.topchetoeu.jscript.core.engine.values; +package me.topchetoeu.jscript.core.values; import java.util.HashMap; import java.util.List; -import me.topchetoeu.jscript.core.engine.Context; -import me.topchetoeu.jscript.core.engine.scope.ValueVariable; +import me.topchetoeu.jscript.core.Context; +import me.topchetoeu.jscript.core.scope.ValueVariable; public class ScopeValue extends ObjectValue { public final ValueVariable[] variables; diff --git a/src/java/me/topchetoeu/jscript/core/engine/values/Symbol.java b/src/java/me/topchetoeu/jscript/core/values/Symbol.java similarity index 92% rename from src/java/me/topchetoeu/jscript/core/engine/values/Symbol.java rename to src/java/me/topchetoeu/jscript/core/values/Symbol.java index 562265e..312ab3e 100644 --- a/src/java/me/topchetoeu/jscript/core/engine/values/Symbol.java +++ b/src/java/me/topchetoeu/jscript/core/values/Symbol.java @@ -1,4 +1,4 @@ -package me.topchetoeu.jscript.core.engine.values; +package me.topchetoeu.jscript.core.values; import java.util.HashMap; diff --git a/src/java/me/topchetoeu/jscript/core/engine/values/Values.java b/src/java/me/topchetoeu/jscript/core/values/Values.java similarity index 95% rename from src/java/me/topchetoeu/jscript/core/engine/values/Values.java rename to src/java/me/topchetoeu/jscript/core/values/Values.java index e2c1be7..8f455ae 100644 --- a/src/java/me/topchetoeu/jscript/core/engine/values/Values.java +++ b/src/java/me/topchetoeu/jscript/core/values/Values.java @@ -1,4 +1,4 @@ -package me.topchetoeu.jscript.core.engine.values; +package me.topchetoeu.jscript.core.values; import java.io.ByteArrayOutputStream; import java.io.PrintStream; @@ -12,10 +12,10 @@ import java.util.Iterator; import java.util.List; import java.util.Map; -import me.topchetoeu.jscript.core.engine.Context; -import me.topchetoeu.jscript.core.engine.Environment; -import me.topchetoeu.jscript.core.engine.Operation; -import me.topchetoeu.jscript.core.engine.frame.ConvertHint; +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; import me.topchetoeu.jscript.core.exceptions.SyntaxException; @@ -51,18 +51,6 @@ public class Values { } public static boolean isNan(Object val) { return val instanceof Number && Double.isNaN(number(val)); } - public static ObjectValue object(Object val) { - if (val instanceof ObjectValue) return (ObjectValue)val; - else return null; - } - public static ArrayValue array(Object val) { - if (val instanceof ArrayValue) return (ArrayValue)val; - else return null; - } - public static FunctionValue function(Object val) { - if (val instanceof FunctionValue) return (FunctionValue)val; - else return null; - } public static double number(Object val) { if (val instanceof Number) return ((Number)val).doubleValue(); else return Double.NaN; @@ -319,7 +307,7 @@ public class Values { obj = normalize(ctx, obj); key = normalize(ctx, key); if ("__proto__".equals(key)) return true; - if (obj instanceof ObjectValue) return object(obj).hasMember(ctx, key, own); + if (obj instanceof ObjectValue) return ((ObjectValue)obj).hasMember(ctx, key, own); if (obj instanceof String && key instanceof Number) { var i = number(key); @@ -336,7 +324,7 @@ public class Values { if (obj == null || obj == NULL) return false; obj = normalize(ctx, obj); key = normalize(ctx, key); - if (obj instanceof ObjectValue) return object(obj).deleteMember(ctx, key); + if (obj instanceof ObjectValue) return ((ObjectValue)obj).deleteMember(ctx, key); else return false; } public static ObjectValue getPrototype(Context ctx, Object obj) { @@ -364,7 +352,7 @@ public class Values { public static List getMembers(Context ctx, Object obj, boolean own, boolean includeNonEnumerable) { List res = new ArrayList<>(); - if (obj instanceof ObjectValue) res = object(obj).keys(includeNonEnumerable); + if (obj instanceof ObjectValue) res = ((ObjectValue)obj).keys(includeNonEnumerable); if (obj instanceof String) { for (var i = 0; i < ((String)obj).length(); i++) res.add((double)i); } @@ -401,7 +389,7 @@ public class Values { public static Object call(Context ctx, Object func, Object thisArg, Object ...args) { if (!(func instanceof FunctionValue)) throw EngineException.ofType("Tried to call a non-function value."); - return function(func).call(ctx, thisArg, args); + return ((FunctionValue)func).call(ctx, thisArg, args); } public static Object callNew(Context ctx, Object func, Object ...args) { var res = new ObjectValue(); @@ -499,19 +487,19 @@ public class Values { if (obj instanceof ArrayValue) { if (clazz.isAssignableFrom(ArrayList.class)) { - var raw = array(obj).toArray(); + var raw = ((ArrayValue)obj).toArray(); var res = new ArrayList<>(); for (var i = 0; i < raw.length; i++) res.add(convert(ctx, raw[i], Object.class)); return (T)new ArrayList<>(res); } if (clazz.isAssignableFrom(HashSet.class)) { - var raw = array(obj).toArray(); + var raw = ((ArrayValue)obj).toArray(); var res = new HashSet<>(); for (var i = 0; i < raw.length; i++) res.add(convert(ctx, raw[i], Object.class)); return (T)new HashSet<>(res); } if (clazz.isArray()) { - var raw = array(obj).toArray(); + var raw = ((ArrayValue)obj).toArray(); Object res = Array.newInstance(clazz.getComponentType(), raw.length); for (var i = 0; i < raw.length; i++) Array.set(res, i, convert(ctx, raw[i], Object.class)); return (T)res; @@ -520,7 +508,7 @@ public class Values { if (obj instanceof ObjectValue && clazz.isAssignableFrom(HashMap.class)) { var res = new HashMap<>(); - for (var el : object(obj).values.entrySet()) res.put( + for (var el : ((ObjectValue)obj).values.entrySet()) res.put( convert(ctx, el.getKey(), null), convert(ctx, el.getValue(), null) ); @@ -672,10 +660,11 @@ public class Values { var printed = true; var res = new StringBuilder(); + var dbg = DebugContext.get(ctx); if (val instanceof FunctionValue) { res.append(val.toString()); - var loc = val instanceof CodeFunction ? ((CodeFunction)val).loc() : null; + var loc = val instanceof CodeFunction ? dbg.getMap((CodeFunction)val).start() : null; if (loc != null) res.append(" @ " + loc); } diff --git a/src/java/me/topchetoeu/jscript/lib/ArrayLib.java b/src/java/me/topchetoeu/jscript/lib/ArrayLib.java index a1cab7e..e0d8c7a 100644 --- a/src/java/me/topchetoeu/jscript/lib/ArrayLib.java +++ b/src/java/me/topchetoeu/jscript/lib/ArrayLib.java @@ -3,11 +3,11 @@ package me.topchetoeu.jscript.lib; import java.util.Iterator; import java.util.Stack; -import me.topchetoeu.jscript.core.engine.values.ArrayValue; -import me.topchetoeu.jscript.core.engine.values.FunctionValue; -import me.topchetoeu.jscript.core.engine.values.NativeFunction; -import me.topchetoeu.jscript.core.engine.values.ObjectValue; -import me.topchetoeu.jscript.core.engine.values.Values; +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.utils.interop.Arguments; import me.topchetoeu.jscript.utils.interop.Expose; import me.topchetoeu.jscript.utils.interop.ExposeConstructor; diff --git a/src/java/me/topchetoeu/jscript/lib/AsyncFunctionLib.java b/src/java/me/topchetoeu/jscript/lib/AsyncFunctionLib.java index c12924f..73be8e4 100644 --- a/src/java/me/topchetoeu/jscript/lib/AsyncFunctionLib.java +++ b/src/java/me/topchetoeu/jscript/lib/AsyncFunctionLib.java @@ -1,11 +1,11 @@ package me.topchetoeu.jscript.lib; -import me.topchetoeu.jscript.core.engine.Context; -import me.topchetoeu.jscript.core.engine.frame.CodeFrame; -import me.topchetoeu.jscript.core.engine.values.CodeFunction; -import me.topchetoeu.jscript.core.engine.values.FunctionValue; -import me.topchetoeu.jscript.core.engine.values.NativeFunction; -import me.topchetoeu.jscript.core.engine.values.Values; +import me.topchetoeu.jscript.core.Context; +import me.topchetoeu.jscript.core.Frame; +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.core.values.Values; import me.topchetoeu.jscript.core.exceptions.EngineException; import me.topchetoeu.jscript.lib.PromiseLib.Handle; import me.topchetoeu.jscript.utils.interop.Arguments; @@ -17,7 +17,7 @@ public class AsyncFunctionLib extends FunctionValue { private static class AsyncHelper { public PromiseLib promise = new PromiseLib(); - public CodeFrame frame; + public Frame frame; private boolean awaiting = false; @@ -69,7 +69,7 @@ public class AsyncFunctionLib extends FunctionValue { 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 CodeFrame(ctx, thisArg, args, (CodeFunction)func); + handler.frame = new Frame(ctx, thisArg, args, (CodeFunction)func); handler.next(ctx, Values.NO_RETURN, null); return handler.promise; } diff --git a/src/java/me/topchetoeu/jscript/lib/AsyncGeneratorFunctionLib.java b/src/java/me/topchetoeu/jscript/lib/AsyncGeneratorFunctionLib.java index ea07505..7e2ce55 100644 --- a/src/java/me/topchetoeu/jscript/lib/AsyncGeneratorFunctionLib.java +++ b/src/java/me/topchetoeu/jscript/lib/AsyncGeneratorFunctionLib.java @@ -1,10 +1,10 @@ package me.topchetoeu.jscript.lib; -import me.topchetoeu.jscript.core.engine.Context; -import me.topchetoeu.jscript.core.engine.frame.CodeFrame; -import me.topchetoeu.jscript.core.engine.values.CodeFunction; -import me.topchetoeu.jscript.core.engine.values.FunctionValue; -import me.topchetoeu.jscript.core.engine.values.NativeFunction; +import me.topchetoeu.jscript.core.Context; +import me.topchetoeu.jscript.core.Frame; +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.core.exceptions.EngineException; import me.topchetoeu.jscript.utils.interop.WrapperName; @@ -20,7 +20,7 @@ public class AsyncGeneratorFunctionLib extends FunctionValue { new NativeFunction("yield", handler::yield) ); if (!(func instanceof CodeFunction)) throw EngineException.ofType("Return value of argument must be a js function."); - handler.frame = new CodeFrame(ctx, thisArg, args, (CodeFunction)func); + handler.frame = new Frame(ctx, thisArg, args, (CodeFunction)func); return handler; } diff --git a/src/java/me/topchetoeu/jscript/lib/AsyncGeneratorLib.java b/src/java/me/topchetoeu/jscript/lib/AsyncGeneratorLib.java index 33e6097..c96431c 100644 --- a/src/java/me/topchetoeu/jscript/lib/AsyncGeneratorLib.java +++ b/src/java/me/topchetoeu/jscript/lib/AsyncGeneratorLib.java @@ -2,10 +2,10 @@ package me.topchetoeu.jscript.lib; import java.util.Map; -import me.topchetoeu.jscript.core.engine.Context; -import me.topchetoeu.jscript.core.engine.frame.CodeFrame; -import me.topchetoeu.jscript.core.engine.values.ObjectValue; -import me.topchetoeu.jscript.core.engine.values.Values; +import me.topchetoeu.jscript.core.Context; +import me.topchetoeu.jscript.core.Frame; +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.lib.PromiseLib.Handle; import me.topchetoeu.jscript.utils.interop.Arguments; @@ -17,7 +17,7 @@ public class AsyncGeneratorLib { private int state = 0; private boolean done = false; private PromiseLib currPromise; - public CodeFrame frame; + public Frame frame; private void next(Context ctx, Object inducedValue, Object inducedReturn, EngineException inducedError) { if (done) { diff --git a/src/java/me/topchetoeu/jscript/lib/BooleanLib.java b/src/java/me/topchetoeu/jscript/lib/BooleanLib.java index fc751ba..79f9b55 100644 --- a/src/java/me/topchetoeu/jscript/lib/BooleanLib.java +++ b/src/java/me/topchetoeu/jscript/lib/BooleanLib.java @@ -1,7 +1,7 @@ package me.topchetoeu.jscript.lib; -import me.topchetoeu.jscript.core.engine.values.ObjectValue; -import me.topchetoeu.jscript.core.engine.values.Values; +import me.topchetoeu.jscript.core.values.ObjectValue; +import me.topchetoeu.jscript.core.values.Values; import me.topchetoeu.jscript.utils.interop.Arguments; import me.topchetoeu.jscript.utils.interop.Expose; import me.topchetoeu.jscript.utils.interop.ExposeConstructor; diff --git a/src/java/me/topchetoeu/jscript/lib/ConsoleLib.java b/src/java/me/topchetoeu/jscript/lib/ConsoleLib.java index 14bb9d6..0627c55 100644 --- a/src/java/me/topchetoeu/jscript/lib/ConsoleLib.java +++ b/src/java/me/topchetoeu/jscript/lib/ConsoleLib.java @@ -2,7 +2,7 @@ package me.topchetoeu.jscript.lib; import java.io.IOException; -import me.topchetoeu.jscript.core.engine.values.Values; +import me.topchetoeu.jscript.core.values.Values; import me.topchetoeu.jscript.utils.filesystem.File; import me.topchetoeu.jscript.utils.interop.Arguments; import me.topchetoeu.jscript.utils.interop.Expose; diff --git a/src/java/me/topchetoeu/jscript/lib/EncodingLib.java b/src/java/me/topchetoeu/jscript/lib/EncodingLib.java index 4601bf7..b212c10 100644 --- a/src/java/me/topchetoeu/jscript/lib/EncodingLib.java +++ b/src/java/me/topchetoeu/jscript/lib/EncodingLib.java @@ -3,10 +3,10 @@ package me.topchetoeu.jscript.lib; import java.util.ArrayList; import me.topchetoeu.jscript.common.Buffer; -import me.topchetoeu.jscript.core.engine.values.ArrayValue; -import me.topchetoeu.jscript.core.engine.values.Values; +import me.topchetoeu.jscript.compilation.parsing.Parsing; +import me.topchetoeu.jscript.core.values.ArrayValue; +import me.topchetoeu.jscript.core.values.Values; import me.topchetoeu.jscript.core.exceptions.EngineException; -import me.topchetoeu.jscript.core.parsing.Parsing; import me.topchetoeu.jscript.utils.interop.Arguments; import me.topchetoeu.jscript.utils.interop.Expose; import me.topchetoeu.jscript.utils.interop.ExposeTarget; diff --git a/src/java/me/topchetoeu/jscript/lib/EnvironmentLib.java b/src/java/me/topchetoeu/jscript/lib/EnvironmentLib.java index 229b58c..5d69727 100644 --- a/src/java/me/topchetoeu/jscript/lib/EnvironmentLib.java +++ b/src/java/me/topchetoeu/jscript/lib/EnvironmentLib.java @@ -1,8 +1,8 @@ package me.topchetoeu.jscript.lib; -import me.topchetoeu.jscript.core.engine.Environment; -import me.topchetoeu.jscript.core.engine.values.FunctionValue; -import me.topchetoeu.jscript.core.engine.values.ObjectValue; +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; diff --git a/src/java/me/topchetoeu/jscript/lib/ErrorLib.java b/src/java/me/topchetoeu/jscript/lib/ErrorLib.java index f0514ed..dd52e07 100644 --- a/src/java/me/topchetoeu/jscript/lib/ErrorLib.java +++ b/src/java/me/topchetoeu/jscript/lib/ErrorLib.java @@ -1,9 +1,9 @@ package me.topchetoeu.jscript.lib; -import me.topchetoeu.jscript.core.engine.Context; -import me.topchetoeu.jscript.core.engine.values.ObjectValue; -import me.topchetoeu.jscript.core.engine.values.Values; -import me.topchetoeu.jscript.core.engine.values.ObjectValue.PlaceholderProto; +import me.topchetoeu.jscript.core.Context; +import me.topchetoeu.jscript.core.values.ObjectValue; +import me.topchetoeu.jscript.core.values.Values; +import me.topchetoeu.jscript.core.values.ObjectValue.PlaceholderProto; import me.topchetoeu.jscript.core.exceptions.ConvertException; import me.topchetoeu.jscript.utils.interop.Arguments; import me.topchetoeu.jscript.utils.interop.Expose; diff --git a/src/java/me/topchetoeu/jscript/lib/FileLib.java b/src/java/me/topchetoeu/jscript/lib/FileLib.java index 4bcf4ea..bb1ef88 100644 --- a/src/java/me/topchetoeu/jscript/lib/FileLib.java +++ b/src/java/me/topchetoeu/jscript/lib/FileLib.java @@ -1,7 +1,7 @@ package me.topchetoeu.jscript.lib; -import me.topchetoeu.jscript.core.engine.values.ArrayValue; -import me.topchetoeu.jscript.core.engine.values.Values; +import me.topchetoeu.jscript.core.values.ArrayValue; +import me.topchetoeu.jscript.core.values.Values; import me.topchetoeu.jscript.utils.filesystem.File; import me.topchetoeu.jscript.utils.filesystem.FilesystemException; import me.topchetoeu.jscript.utils.interop.Arguments; diff --git a/src/java/me/topchetoeu/jscript/lib/FilesystemLib.java b/src/java/me/topchetoeu/jscript/lib/FilesystemLib.java index c5162fd..3938c12 100644 --- a/src/java/me/topchetoeu/jscript/lib/FilesystemLib.java +++ b/src/java/me/topchetoeu/jscript/lib/FilesystemLib.java @@ -4,9 +4,9 @@ import java.io.IOException; import java.util.Iterator; import java.util.Stack; -import me.topchetoeu.jscript.core.engine.Context; -import me.topchetoeu.jscript.core.engine.values.ObjectValue; -import me.topchetoeu.jscript.core.engine.values.Values; +import me.topchetoeu.jscript.core.Context; +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.utils.filesystem.ActionType; import me.topchetoeu.jscript.utils.filesystem.EntryType; diff --git a/src/java/me/topchetoeu/jscript/lib/FunctionLib.java b/src/java/me/topchetoeu/jscript/lib/FunctionLib.java index af52e64..99b07ba 100644 --- a/src/java/me/topchetoeu/jscript/lib/FunctionLib.java +++ b/src/java/me/topchetoeu/jscript/lib/FunctionLib.java @@ -1,10 +1,8 @@ package me.topchetoeu.jscript.lib; -import me.topchetoeu.jscript.common.Location; -import me.topchetoeu.jscript.core.engine.values.ArrayValue; -import me.topchetoeu.jscript.core.engine.values.CodeFunction; -import me.topchetoeu.jscript.core.engine.values.FunctionValue; -import me.topchetoeu.jscript.core.engine.values.NativeFunction; +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.utils.interop.Arguments; import me.topchetoeu.jscript.utils.interop.Expose; import me.topchetoeu.jscript.utils.interop.ExposeTarget; @@ -12,10 +10,6 @@ import me.topchetoeu.jscript.utils.interop.WrapperName; @WrapperName("Function") public class FunctionLib { - @Expose public static Object __location(Arguments args) { - if (args.self instanceof CodeFunction) return ((CodeFunction)args.self).loc().toString(); - else return Location.INTERNAL.toString(); - } @Expose public static Object __apply(Arguments args) { return args.self(FunctionValue.class).call(args.ctx, args.get(0), args.convert(1, ArrayValue.class).toArray()); } diff --git a/src/java/me/topchetoeu/jscript/lib/GeneratorFunctionLib.java b/src/java/me/topchetoeu/jscript/lib/GeneratorFunctionLib.java index 718b536..2622677 100644 --- a/src/java/me/topchetoeu/jscript/lib/GeneratorFunctionLib.java +++ b/src/java/me/topchetoeu/jscript/lib/GeneratorFunctionLib.java @@ -1,10 +1,10 @@ package me.topchetoeu.jscript.lib; -import me.topchetoeu.jscript.core.engine.Context; -import me.topchetoeu.jscript.core.engine.frame.CodeFrame; -import me.topchetoeu.jscript.core.engine.values.CodeFunction; -import me.topchetoeu.jscript.core.engine.values.FunctionValue; -import me.topchetoeu.jscript.core.engine.values.NativeFunction; +import me.topchetoeu.jscript.core.Context; +import me.topchetoeu.jscript.core.Frame; +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.core.exceptions.EngineException; import me.topchetoeu.jscript.utils.interop.WrapperName; @@ -16,7 +16,7 @@ public class GeneratorFunctionLib extends FunctionValue { 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 CodeFrame(ctx, thisArg, args, (CodeFunction)func); + handler.frame = new Frame(ctx, thisArg, args, (CodeFunction)func); return handler; } diff --git a/src/java/me/topchetoeu/jscript/lib/GeneratorLib.java b/src/java/me/topchetoeu/jscript/lib/GeneratorLib.java index 8dd1c22..827c5ce 100644 --- a/src/java/me/topchetoeu/jscript/lib/GeneratorLib.java +++ b/src/java/me/topchetoeu/jscript/lib/GeneratorLib.java @@ -1,9 +1,9 @@ package me.topchetoeu.jscript.lib; -import me.topchetoeu.jscript.core.engine.Context; -import me.topchetoeu.jscript.core.engine.frame.CodeFrame; -import me.topchetoeu.jscript.core.engine.values.ObjectValue; -import me.topchetoeu.jscript.core.engine.values.Values; +import me.topchetoeu.jscript.core.Context; +import me.topchetoeu.jscript.core.Frame; +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.utils.interop.Arguments; import me.topchetoeu.jscript.utils.interop.Expose; @@ -13,7 +13,7 @@ import me.topchetoeu.jscript.utils.interop.WrapperName; public class GeneratorLib { private boolean yielding = true; private boolean done = false; - public CodeFrame frame; + public Frame frame; private ObjectValue next(Context ctx, Object inducedValue, Object inducedReturn, EngineException inducedError) { if (done) { diff --git a/src/java/me/topchetoeu/jscript/lib/Internals.java b/src/java/me/topchetoeu/jscript/lib/Internals.java index 1f08cc5..7d19ac7 100644 --- a/src/java/me/topchetoeu/jscript/lib/Internals.java +++ b/src/java/me/topchetoeu/jscript/lib/Internals.java @@ -2,12 +2,12 @@ package me.topchetoeu.jscript.lib; import java.util.HashMap; -import me.topchetoeu.jscript.core.engine.Context; -import me.topchetoeu.jscript.core.engine.Environment; -import me.topchetoeu.jscript.core.engine.scope.GlobalScope; -import me.topchetoeu.jscript.core.engine.values.FunctionValue; -import me.topchetoeu.jscript.core.engine.values.Symbol; -import me.topchetoeu.jscript.core.engine.values.Values; +import me.topchetoeu.jscript.core.Context; +import me.topchetoeu.jscript.core.Environment; +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; import me.topchetoeu.jscript.utils.interop.Expose; diff --git a/src/java/me/topchetoeu/jscript/lib/MapLib.java b/src/java/me/topchetoeu/jscript/lib/MapLib.java index 4be3bcc..dfe4c02 100644 --- a/src/java/me/topchetoeu/jscript/lib/MapLib.java +++ b/src/java/me/topchetoeu/jscript/lib/MapLib.java @@ -4,10 +4,10 @@ import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.stream.Collectors; -import me.topchetoeu.jscript.core.engine.Context; -import me.topchetoeu.jscript.core.engine.values.ArrayValue; -import me.topchetoeu.jscript.core.engine.values.ObjectValue; -import me.topchetoeu.jscript.core.engine.values.Values; +import me.topchetoeu.jscript.core.Context; +import me.topchetoeu.jscript.core.values.ArrayValue; +import me.topchetoeu.jscript.core.values.ObjectValue; +import me.topchetoeu.jscript.core.values.Values; import me.topchetoeu.jscript.utils.interop.Arguments; import me.topchetoeu.jscript.utils.interop.Expose; import me.topchetoeu.jscript.utils.interop.ExposeConstructor; diff --git a/src/java/me/topchetoeu/jscript/lib/NumberLib.java b/src/java/me/topchetoeu/jscript/lib/NumberLib.java index 8725012..694a0eb 100644 --- a/src/java/me/topchetoeu/jscript/lib/NumberLib.java +++ b/src/java/me/topchetoeu/jscript/lib/NumberLib.java @@ -1,7 +1,7 @@ package me.topchetoeu.jscript.lib; -import me.topchetoeu.jscript.core.engine.values.ObjectValue; -import me.topchetoeu.jscript.core.engine.values.Values; +import me.topchetoeu.jscript.core.values.ObjectValue; +import me.topchetoeu.jscript.core.values.Values; import me.topchetoeu.jscript.utils.interop.Arguments; import me.topchetoeu.jscript.utils.interop.Expose; import me.topchetoeu.jscript.utils.interop.ExposeConstructor; diff --git a/src/java/me/topchetoeu/jscript/lib/ObjectLib.java b/src/java/me/topchetoeu/jscript/lib/ObjectLib.java index 9030e4f..a73ace6 100644 --- a/src/java/me/topchetoeu/jscript/lib/ObjectLib.java +++ b/src/java/me/topchetoeu/jscript/lib/ObjectLib.java @@ -1,10 +1,10 @@ package me.topchetoeu.jscript.lib; -import me.topchetoeu.jscript.core.engine.values.ArrayValue; -import me.topchetoeu.jscript.core.engine.values.FunctionValue; -import me.topchetoeu.jscript.core.engine.values.ObjectValue; -import me.topchetoeu.jscript.core.engine.values.Symbol; -import me.topchetoeu.jscript.core.engine.values.Values; +import me.topchetoeu.jscript.core.values.ArrayValue; +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.core.exceptions.EngineException; import me.topchetoeu.jscript.utils.interop.Arguments; import me.topchetoeu.jscript.utils.interop.Expose; diff --git a/src/java/me/topchetoeu/jscript/lib/PromiseLib.java b/src/java/me/topchetoeu/jscript/lib/PromiseLib.java index 759bdbe..1022f4d 100644 --- a/src/java/me/topchetoeu/jscript/lib/PromiseLib.java +++ b/src/java/me/topchetoeu/jscript/lib/PromiseLib.java @@ -4,13 +4,13 @@ import java.util.ArrayList; import java.util.List; import me.topchetoeu.jscript.common.ResultRunnable; -import me.topchetoeu.jscript.core.engine.Context; -import me.topchetoeu.jscript.core.engine.EventLoop; -import me.topchetoeu.jscript.core.engine.values.ArrayValue; -import me.topchetoeu.jscript.core.engine.values.FunctionValue; -import me.topchetoeu.jscript.core.engine.values.NativeFunction; -import me.topchetoeu.jscript.core.engine.values.ObjectValue; -import me.topchetoeu.jscript.core.engine.values.Values; +import me.topchetoeu.jscript.core.Context; +import me.topchetoeu.jscript.core.EventLoop; +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.utils.interop.Arguments; import me.topchetoeu.jscript.utils.interop.Expose; @@ -61,7 +61,7 @@ public class PromiseLib { } if (state == STATE_REJECTED && !handled) { - Values.printError(((EngineException)val).setCtx(ctx.environment, ctx.engine), "(in promise)"); + Values.printError(((EngineException)val).setCtx(ctx), "(in promise)"); } handles = null; diff --git a/src/java/me/topchetoeu/jscript/lib/RangeErrorLib.java b/src/java/me/topchetoeu/jscript/lib/RangeErrorLib.java index 850849f..eacc4b3 100644 --- a/src/java/me/topchetoeu/jscript/lib/RangeErrorLib.java +++ b/src/java/me/topchetoeu/jscript/lib/RangeErrorLib.java @@ -1,7 +1,7 @@ package me.topchetoeu.jscript.lib; -import me.topchetoeu.jscript.core.engine.values.ObjectValue; -import me.topchetoeu.jscript.core.engine.values.ObjectValue.PlaceholderProto; +import me.topchetoeu.jscript.core.values.ObjectValue; +import me.topchetoeu.jscript.core.values.ObjectValue.PlaceholderProto; import me.topchetoeu.jscript.utils.interop.Arguments; import me.topchetoeu.jscript.utils.interop.ExposeConstructor; import me.topchetoeu.jscript.utils.interop.ExposeField; diff --git a/src/java/me/topchetoeu/jscript/lib/RegExpLib.java b/src/java/me/topchetoeu/jscript/lib/RegExpLib.java index dfd5175..587700a 100644 --- a/src/java/me/topchetoeu/jscript/lib/RegExpLib.java +++ b/src/java/me/topchetoeu/jscript/lib/RegExpLib.java @@ -4,12 +4,12 @@ import java.util.ArrayList; import java.util.Iterator; import java.util.regex.Pattern; -import me.topchetoeu.jscript.core.engine.Context; -import me.topchetoeu.jscript.core.engine.values.ArrayValue; -import me.topchetoeu.jscript.core.engine.values.FunctionValue; -import me.topchetoeu.jscript.core.engine.values.NativeWrapper; -import me.topchetoeu.jscript.core.engine.values.ObjectValue; -import me.topchetoeu.jscript.core.engine.values.Values; +import me.topchetoeu.jscript.core.Context; +import me.topchetoeu.jscript.core.values.ArrayValue; +import me.topchetoeu.jscript.core.values.FunctionValue; +import me.topchetoeu.jscript.core.values.NativeWrapper; +import me.topchetoeu.jscript.core.values.ObjectValue; +import me.topchetoeu.jscript.core.values.Values; import me.topchetoeu.jscript.utils.interop.Arguments; import me.topchetoeu.jscript.utils.interop.Expose; import me.topchetoeu.jscript.utils.interop.ExposeConstructor; @@ -78,13 +78,13 @@ public class RegExpLib { } var obj = new ArrayValue(); - var groups = new ObjectValue(); + ObjectValue groups = null; for (var el : namedGroups) { + if (groups == null) groups = new ObjectValue(); try { groups.defineProperty(null, el, matcher.group(el)); } catch (IllegalArgumentException e) { } } - if (groups.values.size() == 0) groups = null; for (int i = 0; i < matcher.groupCount() + 1; i++) { diff --git a/src/java/me/topchetoeu/jscript/lib/SetLib.java b/src/java/me/topchetoeu/jscript/lib/SetLib.java index bd0bed9..9a0582b 100644 --- a/src/java/me/topchetoeu/jscript/lib/SetLib.java +++ b/src/java/me/topchetoeu/jscript/lib/SetLib.java @@ -4,10 +4,10 @@ import java.util.ArrayList; import java.util.LinkedHashSet; import java.util.stream.Collectors; -import me.topchetoeu.jscript.core.engine.Context; -import me.topchetoeu.jscript.core.engine.values.ArrayValue; -import me.topchetoeu.jscript.core.engine.values.ObjectValue; -import me.topchetoeu.jscript.core.engine.values.Values; +import me.topchetoeu.jscript.core.Context; +import me.topchetoeu.jscript.core.values.ArrayValue; +import me.topchetoeu.jscript.core.values.ObjectValue; +import me.topchetoeu.jscript.core.values.Values; import me.topchetoeu.jscript.utils.interop.Arguments; import me.topchetoeu.jscript.utils.interop.Expose; import me.topchetoeu.jscript.utils.interop.ExposeConstructor; diff --git a/src/java/me/topchetoeu/jscript/lib/StringLib.java b/src/java/me/topchetoeu/jscript/lib/StringLib.java index fa51e19..8078ef5 100644 --- a/src/java/me/topchetoeu/jscript/lib/StringLib.java +++ b/src/java/me/topchetoeu/jscript/lib/StringLib.java @@ -2,12 +2,12 @@ package me.topchetoeu.jscript.lib; import java.util.regex.Pattern; -import me.topchetoeu.jscript.core.engine.Environment; -import me.topchetoeu.jscript.core.engine.values.ArrayValue; -import me.topchetoeu.jscript.core.engine.values.FunctionValue; -import me.topchetoeu.jscript.core.engine.values.ObjectValue; -import me.topchetoeu.jscript.core.engine.values.Symbol; -import me.topchetoeu.jscript.core.engine.values.Values; +import me.topchetoeu.jscript.core.Environment; +import me.topchetoeu.jscript.core.values.ArrayValue; +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.core.exceptions.EngineException; import me.topchetoeu.jscript.utils.interop.Arguments; import me.topchetoeu.jscript.utils.interop.Expose; diff --git a/src/java/me/topchetoeu/jscript/lib/SymbolLib.java b/src/java/me/topchetoeu/jscript/lib/SymbolLib.java index bd83c3d..b121bec 100644 --- a/src/java/me/topchetoeu/jscript/lib/SymbolLib.java +++ b/src/java/me/topchetoeu/jscript/lib/SymbolLib.java @@ -3,9 +3,9 @@ package me.topchetoeu.jscript.lib; import java.util.HashMap; import java.util.Map; -import me.topchetoeu.jscript.core.engine.values.ObjectValue; -import me.topchetoeu.jscript.core.engine.values.Symbol; -import me.topchetoeu.jscript.core.engine.values.Values; +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.core.exceptions.EngineException; import me.topchetoeu.jscript.utils.interop.Arguments; import me.topchetoeu.jscript.utils.interop.Expose; diff --git a/src/java/me/topchetoeu/jscript/lib/SyntaxErrorLib.java b/src/java/me/topchetoeu/jscript/lib/SyntaxErrorLib.java index bd2f042..177e98d 100644 --- a/src/java/me/topchetoeu/jscript/lib/SyntaxErrorLib.java +++ b/src/java/me/topchetoeu/jscript/lib/SyntaxErrorLib.java @@ -1,7 +1,7 @@ package me.topchetoeu.jscript.lib; -import me.topchetoeu.jscript.core.engine.values.ObjectValue; -import me.topchetoeu.jscript.core.engine.values.ObjectValue.PlaceholderProto; +import me.topchetoeu.jscript.core.values.ObjectValue; +import me.topchetoeu.jscript.core.values.ObjectValue.PlaceholderProto; import me.topchetoeu.jscript.utils.interop.Arguments; import me.topchetoeu.jscript.utils.interop.ExposeConstructor; import me.topchetoeu.jscript.utils.interop.ExposeField; diff --git a/src/java/me/topchetoeu/jscript/lib/TypeErrorLib.java b/src/java/me/topchetoeu/jscript/lib/TypeErrorLib.java index 02d5039..74f9b31 100644 --- a/src/java/me/topchetoeu/jscript/lib/TypeErrorLib.java +++ b/src/java/me/topchetoeu/jscript/lib/TypeErrorLib.java @@ -1,7 +1,7 @@ package me.topchetoeu.jscript.lib; -import me.topchetoeu.jscript.core.engine.values.ObjectValue; -import me.topchetoeu.jscript.core.engine.values.ObjectValue.PlaceholderProto; +import me.topchetoeu.jscript.core.values.ObjectValue; +import me.topchetoeu.jscript.core.values.ObjectValue.PlaceholderProto; import me.topchetoeu.jscript.utils.interop.Arguments; import me.topchetoeu.jscript.utils.interop.ExposeConstructor; import me.topchetoeu.jscript.utils.interop.ExposeField; diff --git a/src/java/me/topchetoeu/jscript/utils/JScriptRepl.java b/src/java/me/topchetoeu/jscript/utils/JScriptRepl.java index 4b1cba6..2394249 100644 --- a/src/java/me/topchetoeu/jscript/utils/JScriptRepl.java +++ b/src/java/me/topchetoeu/jscript/utils/JScriptRepl.java @@ -8,17 +8,17 @@ 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.engine.Engine; -import me.topchetoeu.jscript.core.engine.Environment; -import me.topchetoeu.jscript.core.engine.debug.DebugContext; -import me.topchetoeu.jscript.core.engine.values.NativeFunction; -import me.topchetoeu.jscript.core.engine.values.Values; +import me.topchetoeu.jscript.core.Engine; +import me.topchetoeu.jscript.core.Environment; +import me.topchetoeu.jscript.core.debug.DebugContext; +import me.topchetoeu.jscript.core.values.NativeFunction; +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.core.exceptions.SyntaxException; import me.topchetoeu.jscript.lib.Internals; import me.topchetoeu.jscript.utils.debug.DebugServer; -import me.topchetoeu.jscript.utils.debug.SimpleDebugger; +// import me.topchetoeu.jscript.utils.debug.SimpleDebugger; import me.topchetoeu.jscript.utils.filesystem.Filesystem; import me.topchetoeu.jscript.utils.filesystem.MemoryFilesystem; import me.topchetoeu.jscript.utils.filesystem.Mode; @@ -116,12 +116,12 @@ public class JScriptRepl { environment.add(ModuleRepo.ENV_KEY, ModuleRepo.ofFilesystem(fs)); } private static void initEngine() { - var ctx = new DebugContext(); - engine.add(DebugContext.ENV_KEY, ctx); + // var ctx = new DebugContext(); + // engine.add(DebugContext.ENV_KEY, ctx); - debugServer.targets.put("target", (ws, req) -> new SimpleDebugger(ws).attach(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[]) { diff --git a/src/java/me/topchetoeu/jscript/utils/debug/DebugServer.java b/src/java/me/topchetoeu/jscript/utils/debug/DebugServer.java index 1bfd026..f0f5a27 100644 --- a/src/java/me/topchetoeu/jscript/utils/debug/DebugServer.java +++ b/src/java/me/topchetoeu/jscript/utils/debug/DebugServer.java @@ -92,7 +92,6 @@ public class DebugServer { case "Runtime.releaseObject": debugger.releaseObject(msg); continue; case "Runtime.getProperties": debugger.getProperties(msg); continue; case "Runtime.callFunctionOn": debugger.callFunctionOn(msg); continue; - // case "NodeWorker.enable": debugger.nodeWorkerEnable(msg); continue; case "Runtime.enable": debugger.runtimeEnable(msg); continue; } diff --git a/src/java/me/topchetoeu/jscript/utils/debug/Debugger.java b/src/java/me/topchetoeu/jscript/utils/debug/Debugger.java index 53c35ff..93dc922 100644 --- a/src/java/me/topchetoeu/jscript/utils/debug/Debugger.java +++ b/src/java/me/topchetoeu/jscript/utils/debug/Debugger.java @@ -1,6 +1,6 @@ package me.topchetoeu.jscript.utils.debug; -import me.topchetoeu.jscript.core.engine.debug.DebugController; +import me.topchetoeu.jscript.core.debug.DebugController; public interface Debugger extends DebugHandler, DebugController { void close(); diff --git a/src/java/me/topchetoeu/jscript/utils/debug/SimpleDebugger.java b/src/java/me/topchetoeu/jscript/utils/debug/SimpleDebugger.java- similarity index 93% rename from src/java/me/topchetoeu/jscript/utils/debug/SimpleDebugger.java rename to src/java/me/topchetoeu/jscript/utils/debug/SimpleDebugger.java- index c286c9b..168c156 100644 --- a/src/java/me/topchetoeu/jscript/utils/debug/SimpleDebugger.java +++ b/src/java/me/topchetoeu/jscript/utils/debug/SimpleDebugger.java- @@ -17,23 +17,24 @@ import me.topchetoeu.jscript.common.json.JSON; import me.topchetoeu.jscript.common.json.JSONElement; import me.topchetoeu.jscript.common.json.JSONList; import me.topchetoeu.jscript.common.json.JSONMap; -import me.topchetoeu.jscript.core.compilation.Instruction; -import me.topchetoeu.jscript.core.compilation.Instruction.Type; -import me.topchetoeu.jscript.core.engine.Context; -import me.topchetoeu.jscript.core.engine.Engine; -import me.topchetoeu.jscript.core.engine.Environment; -import me.topchetoeu.jscript.core.engine.debug.DebugContext; -import me.topchetoeu.jscript.core.engine.frame.CodeFrame; -import me.topchetoeu.jscript.core.engine.scope.GlobalScope; -import me.topchetoeu.jscript.core.engine.values.ArrayValue; -import me.topchetoeu.jscript.core.engine.values.CodeFunction; -import me.topchetoeu.jscript.core.engine.values.FunctionValue; -import me.topchetoeu.jscript.core.engine.values.ObjectValue; -import me.topchetoeu.jscript.core.engine.values.Symbol; -import me.topchetoeu.jscript.core.engine.values.Values; +import me.topchetoeu.jscript.compilation.Instruction; +import me.topchetoeu.jscript.compilation.Instruction.BreakpointType; +import me.topchetoeu.jscript.compilation.Instruction.Type; +import me.topchetoeu.jscript.compilation.parsing.Parsing; +import me.topchetoeu.jscript.core.Context; +import me.topchetoeu.jscript.core.Engine; +import me.topchetoeu.jscript.core.Environment; +import me.topchetoeu.jscript.core.Extensions; +import me.topchetoeu.jscript.core.Frame; +import me.topchetoeu.jscript.core.debug.DebugContext; +import me.topchetoeu.jscript.core.scope.GlobalScope; +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.ObjectValue; +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.core.parsing.Parsing; -import me.topchetoeu.jscript.utils.mapping.SourceMap; // very simple indeed public class SimpleDebugger implements Debugger { @@ -64,17 +65,15 @@ public class SimpleDebugger implements Debugger { UNCAUGHT, ALL, } - private static class Source { + private static class DebugSource { public final int id; public final Filename filename; public final String source; - public final TreeSet breakpoints; - public Source(int id, Filename filename, String source, TreeSet breakpoints) { + public DebugSource(int id, Filename filename, String source) { this.id = id; this.filename = filename; this.source = source; - this.breakpoints = breakpoints; } } private static class Breakpoint { @@ -104,8 +103,8 @@ public class SimpleDebugger implements Debugger { this.condition = condition; } } - private class Frame { - public CodeFrame frame; + private class DebugFrame { + public Frame frame; public CodeFunction func; public int id; public ObjectValue local, capture, global, valstack; @@ -117,7 +116,7 @@ public class SimpleDebugger implements Debugger { this.location = loc; } - public Frame(CodeFrame frame, int id) { + public DebugFrame(Frame frame, int id) { this.frame = frame; this.func = frame.function; this.id = id; @@ -198,11 +197,11 @@ public class SimpleDebugger implements Debugger { private HashSet tmpBreakpts = new HashSet<>(); private HashMap filenameToId = new HashMap<>(); - private HashMap idToSource = new HashMap<>(); - private ArrayList pendingSources = new ArrayList<>(); + private HashMap idToSource = new HashMap<>(); + private ArrayList pendingSources = new ArrayList<>(); - private HashMap idToFrame = new HashMap<>(); - private HashMap codeFrameToFrame = new HashMap<>(); + private HashMap idToFrame = new HashMap<>(); + private HashMap codeFrameToFrame = new HashMap<>(); private HashMap idToObject = new HashMap<>(); private HashMap objectToId = new HashMap<>(); @@ -212,7 +211,7 @@ public class SimpleDebugger implements Debugger { private boolean pendingPause = false; private int nextId = 0; - private Frame stepOutFrame = null, currFrame = null; + private DebugFrame stepOutFrame = null, currFrame = null; private int stepOutPtr = 0; private boolean compare(String src, String target) { @@ -246,10 +245,10 @@ public class SimpleDebugger implements Debugger { return nextId++; } - private synchronized Frame getFrame(CodeFrame frame) { + private synchronized DebugFrame getFrame(Frame frame) { if (!codeFrameToFrame.containsKey(frame)) { var id = nextId(); - var fr = new Frame(frame, id); + var fr = new DebugFrame(frame, id); idToFrame.put(id, fr); codeFrameToFrame.put(frame, fr); @@ -277,7 +276,7 @@ public class SimpleDebugger implements Debugger { return res; } - private Location correctLocation(Source source, Location loc) { + private Location correctLocation(DebugSource source, Location loc) { var set = source.breakpoints; if (set.contains(loc)) return loc; @@ -494,7 +493,7 @@ public class SimpleDebugger implements Debugger { } } - private void sendSource(Source src){ + private void sendSource(DebugSource src){ try { ws.send(new V8Event("Debugger.scriptParsed", new JSONMap() .set("scriptId", src.id + "") @@ -524,7 +523,7 @@ public class SimpleDebugger implements Debugger { } } - private RunResult run(Frame codeFrame, String code) { + private RunResult run(DebugFrame codeFrame, String code) { if (codeFrame == null) return new RunResult(null, code, new EngineException("Invalid code frame!")); var engine = new Engine(); var env = codeFrame.func.environment.copy(); @@ -916,9 +915,9 @@ public class SimpleDebugger implements Debugger { ws.send(msg.respond()); } - @Override public void onSource(Filename filename, String source, TreeSet locations, SourceMap map) { + @Override public void onSource(Filename filename, String source) { int id = nextId(); - var src = new Source(id, filename, source, locations); + var src = new DebugSource(id, filename, source); idToSource.put(id, src); filenameToId.put(filename, id); @@ -935,19 +934,23 @@ public class SimpleDebugger implements Debugger { if (!enabled) pendingSources.add(src); else sendSource(src); } - @Override public boolean onInstruction(Context ctx, CodeFrame cf, Instruction instruction, Object returnVal, EngineException error, boolean caught) { + @Override public boolean onInstruction(Context ctx, Frame cf, Instruction instruction, Object returnVal, EngineException error, boolean caught) { if (!enabled) return false; boolean isBreakpointable; Location loc; - Frame frame; + DebugFrame frame; + BreakpointType bptType; synchronized (this) { frame = getFrame(cf); - if (instruction.location != null) frame.updateLoc(DebugContext.get(ctx).mapToCompiled(instruction.location)); + var map = DebugContext.get(ctx).getMap(frame.func); + + frame.updateLoc(map.toLocation(frame.frame.codePtr)); loc = frame.location; - isBreakpointable = loc != null && (instruction.breakpoint.shouldStepIn()); + bptType = DebugContext.get(ctx).getMap(frame.func).getBreakpoint(loc); + isBreakpointable = loc != null && (bptType.shouldStepIn()); if (error != null && (execptionType == CatchType.ALL || execptionType == CatchType.UNCAUGHT && !caught)) { pauseException(ctx); @@ -990,11 +993,12 @@ public class SimpleDebugger implements Debugger { continue; } else if (stepOutPtr != frame.frame.codePtr) { - if (state == State.STEPPING_IN && instruction.breakpoint.shouldStepIn()) { + + if (state == State.STEPPING_IN && bptType.shouldStepIn()) { pauseDebug(ctx, null); break; } - else if (state == State.STEPPING_OVER && instruction.breakpoint.shouldStepOver()) { + else if (state == State.STEPPING_OVER && bptType.shouldStepOver()) { pauseDebug(ctx, null); break; } @@ -1008,7 +1012,7 @@ public class SimpleDebugger implements Debugger { return false; } - @Override public void onFramePush(Context ctx, CodeFrame frame) { + @Override public void onFramePush(Context ctx, Frame frame) { var prevFrame = currFrame; updateFrames(ctx); @@ -1016,7 +1020,7 @@ public class SimpleDebugger implements Debugger { stepOutFrame = currFrame; } } - @Override public void onFramePop(Context ctx, CodeFrame frame) { + @Override public void onFramePop(Context ctx, Frame frame) { updateFrames(ctx); try { idToFrame.remove(codeFrameToFrame.remove(frame).id); } diff --git a/src/java/me/topchetoeu/jscript/utils/filesystem/Filesystem.java b/src/java/me/topchetoeu/jscript/utils/filesystem/Filesystem.java index 8cac973..8035898 100644 --- a/src/java/me/topchetoeu/jscript/utils/filesystem/Filesystem.java +++ b/src/java/me/topchetoeu/jscript/utils/filesystem/Filesystem.java @@ -1,7 +1,7 @@ package me.topchetoeu.jscript.utils.filesystem; -import me.topchetoeu.jscript.core.engine.Extensions; -import me.topchetoeu.jscript.core.engine.values.Symbol; +import me.topchetoeu.jscript.core.Extensions; +import me.topchetoeu.jscript.core.values.Symbol; public interface Filesystem { public static final Symbol ENV_KEY = Symbol.get("Environment.fs"); diff --git a/src/java/me/topchetoeu/jscript/utils/filesystem/FilesystemException.java b/src/java/me/topchetoeu/jscript/utils/filesystem/FilesystemException.java index 688280b..486b6c9 100644 --- a/src/java/me/topchetoeu/jscript/utils/filesystem/FilesystemException.java +++ b/src/java/me/topchetoeu/jscript/utils/filesystem/FilesystemException.java @@ -2,7 +2,7 @@ package me.topchetoeu.jscript.utils.filesystem; import java.util.ArrayList; -import me.topchetoeu.jscript.core.engine.values.Values; +import me.topchetoeu.jscript.core.values.Values; import me.topchetoeu.jscript.core.exceptions.EngineException; public class FilesystemException extends RuntimeException { diff --git a/src/java/me/topchetoeu/jscript/utils/interop/Arguments.java b/src/java/me/topchetoeu/jscript/utils/interop/Arguments.java index 97ce741..8e8a606 100644 --- a/src/java/me/topchetoeu/jscript/utils/interop/Arguments.java +++ b/src/java/me/topchetoeu/jscript/utils/interop/Arguments.java @@ -2,9 +2,9 @@ package me.topchetoeu.jscript.utils.interop; import java.lang.reflect.Array; -import me.topchetoeu.jscript.core.engine.Context; -import me.topchetoeu.jscript.core.engine.values.NativeWrapper; -import me.topchetoeu.jscript.core.engine.values.Values; +import me.topchetoeu.jscript.core.Context; +import me.topchetoeu.jscript.core.values.NativeWrapper; +import me.topchetoeu.jscript.core.values.Values; public class Arguments { public final Object self; diff --git a/src/java/me/topchetoeu/jscript/utils/interop/NativeWrapperProvider.java b/src/java/me/topchetoeu/jscript/utils/interop/NativeWrapperProvider.java index bf2ef51..fdee1a4 100644 --- a/src/java/me/topchetoeu/jscript/utils/interop/NativeWrapperProvider.java +++ b/src/java/me/topchetoeu/jscript/utils/interop/NativeWrapperProvider.java @@ -10,14 +10,14 @@ import java.util.HashSet; import java.util.stream.Collectors; import me.topchetoeu.jscript.common.Location; -import me.topchetoeu.jscript.core.engine.Context; -import me.topchetoeu.jscript.core.engine.Environment; -import me.topchetoeu.jscript.core.engine.WrapperProvider; -import me.topchetoeu.jscript.core.engine.values.FunctionValue; -import me.topchetoeu.jscript.core.engine.values.NativeFunction; -import me.topchetoeu.jscript.core.engine.values.ObjectValue; -import me.topchetoeu.jscript.core.engine.values.Symbol; -import me.topchetoeu.jscript.core.engine.values.Values; +import me.topchetoeu.jscript.core.Context; +import me.topchetoeu.jscript.core.Environment; +import me.topchetoeu.jscript.core.WrapperProvider; +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.Symbol; +import me.topchetoeu.jscript.core.values.Values; import me.topchetoeu.jscript.core.exceptions.EngineException; import me.topchetoeu.jscript.core.exceptions.InterruptException; diff --git a/src/java/me/topchetoeu/jscript/utils/modules/Module.java b/src/java/me/topchetoeu/jscript/utils/modules/Module.java index 71a5c36..71bfb0a 100644 --- a/src/java/me/topchetoeu/jscript/utils/modules/Module.java +++ b/src/java/me/topchetoeu/jscript/utils/modules/Module.java @@ -1,6 +1,6 @@ package me.topchetoeu.jscript.utils.modules; -import me.topchetoeu.jscript.core.engine.Context; +import me.topchetoeu.jscript.core.Context; public abstract class Module { private Object value; diff --git a/src/java/me/topchetoeu/jscript/utils/modules/ModuleRepo.java b/src/java/me/topchetoeu/jscript/utils/modules/ModuleRepo.java index 2dd764b..2941bf3 100644 --- a/src/java/me/topchetoeu/jscript/utils/modules/ModuleRepo.java +++ b/src/java/me/topchetoeu/jscript/utils/modules/ModuleRepo.java @@ -3,9 +3,9 @@ package me.topchetoeu.jscript.utils.modules; import java.util.HashMap; import me.topchetoeu.jscript.common.Filename; -import me.topchetoeu.jscript.core.engine.Context; -import me.topchetoeu.jscript.core.engine.Extensions; -import me.topchetoeu.jscript.core.engine.values.Symbol; +import me.topchetoeu.jscript.core.Context; +import me.topchetoeu.jscript.core.Extensions; +import me.topchetoeu.jscript.core.values.Symbol; import me.topchetoeu.jscript.utils.filesystem.Filesystem; import me.topchetoeu.jscript.utils.filesystem.Mode; diff --git a/src/java/me/topchetoeu/jscript/utils/modules/RootModuleRepo.java b/src/java/me/topchetoeu/jscript/utils/modules/RootModuleRepo.java index 8589c05..0647154 100644 --- a/src/java/me/topchetoeu/jscript/utils/modules/RootModuleRepo.java +++ b/src/java/me/topchetoeu/jscript/utils/modules/RootModuleRepo.java @@ -2,7 +2,7 @@ package me.topchetoeu.jscript.utils.modules; import java.util.HashMap; -import me.topchetoeu.jscript.core.engine.Context; +import me.topchetoeu.jscript.core.Context; import me.topchetoeu.jscript.core.exceptions.EngineException; public class RootModuleRepo implements ModuleRepo { diff --git a/src/java/me/topchetoeu/jscript/utils/modules/SourceModule.java b/src/java/me/topchetoeu/jscript/utils/modules/SourceModule.java index a662482..1cab1b0 100644 --- a/src/java/me/topchetoeu/jscript/utils/modules/SourceModule.java +++ b/src/java/me/topchetoeu/jscript/utils/modules/SourceModule.java @@ -1,8 +1,8 @@ package me.topchetoeu.jscript.utils.modules; import me.topchetoeu.jscript.common.Filename; -import me.topchetoeu.jscript.core.engine.Context; -import me.topchetoeu.jscript.core.engine.Environment; +import me.topchetoeu.jscript.core.Context; +import me.topchetoeu.jscript.core.Environment; public class SourceModule extends Module { public final Filename filename; diff --git a/src/java/me/topchetoeu/jscript/utils/permissions/PermissionsProvider.java b/src/java/me/topchetoeu/jscript/utils/permissions/PermissionsProvider.java index 4a5ea60..f2b51e9 100644 --- a/src/java/me/topchetoeu/jscript/utils/permissions/PermissionsProvider.java +++ b/src/java/me/topchetoeu/jscript/utils/permissions/PermissionsProvider.java @@ -1,7 +1,7 @@ package me.topchetoeu.jscript.utils.permissions; -import me.topchetoeu.jscript.core.engine.Extensions; -import me.topchetoeu.jscript.core.engine.values.Symbol; +import me.topchetoeu.jscript.core.Extensions; +import me.topchetoeu.jscript.core.values.Symbol; public interface PermissionsProvider { public static final Symbol ENV_KEY = new Symbol("Environment.perms");