From 62aba62a4190643d13b126fea98dfcf6d576a14f Mon Sep 17 00:00:00 2001 From: TopchetoEU <36534413+TopchetoEU@users.noreply.github.com> Date: Fri, 30 Aug 2024 18:48:48 +0300 Subject: [PATCH] refactor: make Environment more reusable --- src/assets/lib/index.js | 319 ++++++++++++++++++ .../topchetoeu/jscript/common/Compiler.java | 10 +- .../common/environment/Environment.java | 195 +++++++++++ .../jscript/common/environment/Key.java | 7 + .../jscript/common/environment/MultiKey.java | 7 + .../topchetoeu/jscript/runtime/EventLoop.java | 6 +- .../me/topchetoeu/jscript/runtime/Frame.java | 11 +- .../jscript/runtime/InstructionRunner.java | 19 +- .../jscript/runtime/JSONConverter.java | 8 +- .../jscript/runtime/SimpleRepl.java | 260 +++++++++++++- .../jscript/runtime/debug/DebugContext.java | 8 +- .../jscript/runtime/debug/DebugHandler.java | 2 +- .../runtime/environment/Environment.java | 144 -------- .../jscript/runtime/environment/Key.java | 5 - .../runtime/exceptions/EngineException.java | 14 +- .../jscript/runtime/scope/GlobalScope.java | 9 +- .../jscript/runtime/scope/ValueVariable.java | 2 +- .../jscript/runtime/scope/Variable.java | 2 +- .../jscript/runtime/values/KeyCache.java | 2 +- .../jscript/runtime/values/Member.java | 9 +- .../jscript/runtime/values/Value.java | 99 ++---- .../runtime/values/functions/Arguments.java | 5 +- .../values/functions/CodeFunction.java | 2 +- .../values/functions/FunctionValue.java | 4 +- .../values/functions/NativeFunction.java | 2 +- .../runtime/values/objects/ArrayValue.java | 6 +- .../runtime/values/objects/ObjectValue.java | 4 +- .../runtime/values/objects/ScopeValue.java | 2 +- .../runtime/values/primitives/BoolValue.java | 4 +- .../values/primitives/NumberValue.java | 4 +- .../values/primitives/PrimitiveValue.java | 2 +- .../values/primitives/StringValue.java | 4 +- .../values/primitives/SymbolValue.java | 6 +- .../runtime/values/primitives/VoidValue.java | 13 +- 34 files changed, 886 insertions(+), 310 deletions(-) create mode 100644 src/assets/lib/index.js create mode 100644 src/java/me/topchetoeu/jscript/common/environment/Environment.java create mode 100644 src/java/me/topchetoeu/jscript/common/environment/Key.java create mode 100644 src/java/me/topchetoeu/jscript/common/environment/MultiKey.java delete mode 100644 src/java/me/topchetoeu/jscript/runtime/environment/Environment.java delete mode 100644 src/java/me/topchetoeu/jscript/runtime/environment/Key.java diff --git a/src/assets/lib/index.js b/src/assets/lib/index.js new file mode 100644 index 0000000..6176ce2 --- /dev/null +++ b/src/assets/lib/index.js @@ -0,0 +1,319 @@ +(function(target, primordials) { + var makeSymbol = primordials.symbol.makeSymbol; + var getSymbol = primordials.symbol.getSymbol; + var getSymbolKey = primordials.symbol.getSymbolKey; + var getSymbolDescription = primordials.symbol.getSymbolDescription; + + var parseInt = primordials.number.parseInt; + var parseFloat = primordials.number.parseFloat; + var isNaN = primordials.number.isNaN; + var NaN = primordials.number.NaN; + var Infinity = primordials.number.Infinity; + + var fromCharCode = primordials.string.fromCharCode; + var fromCodePoint = primordials.string.fromCodePoint; + var stringBuild = primordials.string.stringBuild; + + var defineProperty = primordials.object.defineProperty; + var defineField = primordials.object.defineField; + var getOwnMember = primordials.object.getMember; + var getOwnSymbolMember = primordials.object.getOwnSymbolMember; + var getOwnMembers = primordials.object.getOwnMembers; + var getOwnSymbolMembers = primordials.object.getOwnSymbolMembers; + var getPrototype = primordials.object.getPrototype; + var setPrototype = primordials.object.setPrototype; + + var invokeType = primordials.function.invokeType; + var setConstructable = primordials.function.setConstructable; + var setCallable = primordials.function.setCallable; + var invoke = primordials.function.invoke; + + var setGlobalPrototype = primordials.setGlobalPrototype; + var compile = primordials.compile; + + var json = primordials.json; + + var valueKey = makeSymbol("Primitive.value"); + + function unwrapThis(self, type, constr, name, arg, defaultVal) { + if (arg == null) arg = "this"; + if (typeof self === type) return self; + if (self instanceof constr && valueKey in self) self = self[valueKey]; + if (typeof self === type) return self; + if (arguments.length > 5) return defaultVal; + + throw new TypeError(name + " requires that '" + arg + "' be a " + constr.name); + } + + function wrapIndex(i, len) { + } + + var Symbol = function(name) { + if (arguments.length === 0) return makeSymbol(""); + else return makeSymbol(name + ""); + }; + setConstructable(Symbol, false); + + defineField(Symbol, "for", true, false, true, function(name) { + return getSymbol(name + ""); + }); + defineField(Symbol, "keyFor", true, false, true, function(symbol) { + return getSymbolKey(unwrapThis(symbol, "symbol", Symbol, "Symbol.keyFor")); + }); + + defineField(Symbol, "asyncIterator", false, false, false, Symbol("Symbol.asyncIterator")); + defineField(Symbol, "iterator", false, false, false, Symbol("Symbol.iterator")); + defineField(Symbol, "match", false, false, false, Symbol("Symbol.match")); + defineField(Symbol, "matchAll", false, false, false, Symbol("Symbol.matchAll")); + defineField(Symbol, "replace", false, false, false, Symbol("Symbol.replace")); + defineField(Symbol, "search", false, false, false, Symbol("Symbol.search")); + defineField(Symbol, "split", false, false, false, Symbol("Symbol.split")); + defineField(Symbol, "toStringTag", false, false, false, Symbol("Symbol.toStringTag")); + defineField(Symbol, "prototype", false, false, false, {}); + + defineProperty(Symbol.prototype, "description", false, true, function () { + return getSymbolDescription(unwrapThis(this, "symbol", Symbol, "Symbol.prototype.description")); + }, undefined); + defineField(Symbol.prototype, "toString", true, false, true, function() { + return "Symbol(" + unwrapThis(this, "symbol", Symbol, "Symbol.prototype.toString").description + ")"; + }); + defineField(Symbol.prototype, "valueOf", true, false, true, function() { + return unwrapThis(this, "symbol", Symbol, "Symbol.prototype.valueOf"); + }); + + target.Symbol = Symbol; + + var Number = function(value) { + if (invokeType(arguments) === "call") { + if (arguments.length === 0) return 0; + else return +value; + } + + this[valueKey] = target.Number(value); + }; + + defineField(Number, "isFinite", true, false, true, function(value) { + value = unwrapThis(value, "number", Number, "Number.isFinite", "value", undefined); + + if (value === undefined || isNaN(value)) return false; + if (value === Infinity || value === -Infinity) return false; + + return true; + }); + defineField(Number, "isInteger", true, false, true, function(value) { + value = unwrapThis(value, "number", Number, "Number.isInteger", "value", undefined); + if (value === undefined) return false; + return parseInt(value) === value; + }); + defineField(Number, "isNaN", true, false, true, function(value) { + return isNaN(value); + }); + defineField(Number, "isSafeInteger", true, false, true, function(value) { + value = unwrapThis(value, "number", Number, "Number.isSafeInteger", "value", undefined); + if (value === undefined || parseInt(value) !== value) return false; + return value >= -9007199254740991 && value <= 9007199254740991; + }); + defineField(Number, "parseFloat", true, false, true, function(value) { + value = 0 + value; + return parseFloat(value); + }); + defineField(Number, "parseInt", true, false, true, function(value, radix) { + value = 0 + value; + radix = +radix; + if (isNaN(radix)) radix = 10; + + return parseInt(value, radix); + }); + + defineField(Number, "EPSILON", false, false, false, 2.220446049250313e-16); + defineField(Number, "MIN_SAFE_INTEGER", false, false, false, -9007199254740991); + defineField(Number, "MAX_SAFE_INTEGER", false, false, false, 9007199254740991); + defineField(Number, "POSITIVE_INFINITY", false, false, false, +Infinity); + defineField(Number, "NEGATIVE_INFINITY", false, false, false, -Infinity); + defineField(Number, "NaN", false, false, false, NaN); + defineField(Number, "MAX_VALUE", false, false, false, 1.7976931348623157e+308); + defineField(Number, "MIN_VALUE", false, false, false, 5e-324); + defineField(Number, "prototype", false, false, false, {}); + + defineField(Number.prototype, "toString", true, false, true); + defineField(Number.prototype, "toString", true, false, true, function() { + return "" + unwrapThis(this, "number", Number, "Number.prototype.toString"); + }); + defineField(Number.prototype, "valueOf", true, false, true, function() { + return unwrapThis(this, "number", Number, "Number.prototype.toString"); + }); + + target.Number = Number; + + var String = function(value) { + if (invokeType(arguments) === "call") { + if (arguments.length === 0) return ""; + else return value + ""; + } + + this[valueKey] = target.String(value); + }; + + defineField(String, "fromCharCode", true, false, true, function() { + var res = []; + res[arguments.length] = 0; + + for (var i = 0; i < arguments.length; i++) { + res[res.length] = fromCharCode(+arguments[i]); + } + + return stringBuild(res); + }); + defineField(String, "fromCodePoint", true, false, true, function(value) { + var res = []; + res[arguments.length] = 0; + + for (var i = 0; i < arguments.length; i++) { + res[res.length] = fromCodePoint(+arguments[i]); + } + + return stringBuild(res); + }); + + defineField(String, "prototype", false, false, false, {}); + + defineField(String.prototype, "at", true, false, true, function(index) { + return "" + unwrapThis(this, "string", String, "String.prototype.at"); + }); + defineField(String.prototype, "toString", true, false, true, function() { + return unwrapThis(this, "string", String, "String.prototype.toString"); + }); + defineField(String.prototype, "valueOf", true, false, true, function() { + return unwrapThis(this, "string", String, "String.prototype.valueOf"); + }); + + target.String = String; + + var Boolean = function(value) { + if (invokeType(arguments) === "call") { + if (arguments.length === 0) return false; + else return !!value; + } + + this[valueKey] = target.Boolean(value); + }; + + defineField(Boolean, "prototype", false, false, false, {}); + + defineField(Boolean.prototype, "toString", true, false, true, function() { + return "" + unwrapThis(this, "boolean", Boolean, "Boolean.prototype.toString"); + }); + defineField(Boolean.prototype, "valueOf", true, false, true, function() { + return unwrapThis(this, "boolean", Boolean, "Boolean.prototype.valueOf"); + }); + + target.Boolean = Boolean; + + var Object = function(value) { + if (typeof value === 'object' && value !== null) return value; + + if (typeof value === 'string') return new String(value); + if (typeof value === 'number') return new Number(value); + if (typeof value === 'boolean') return new Boolean(value); + if (typeof value === 'symbol') { + var res = {}; + setPrototype(res, Symbol.prototype); + res[valueKey] = value; + return res; + } + + var target = this; + if (target === undefined || target === null || typeof target !== 'object') target = {}; + + this[valueKey] = target.Object(value); + }; + + defineField(Object, "prototype", false, false, false, setPrototype({}, null)); + + defineField(Object.prototype, "toString", true, false, true, function() { + if (this !== null && this !== undefined && (Symbol.toStringTag in this)) return "[object " + this[Symbol.toStringTag] + "]"; + else if (typeof this === "number" || this instanceof Number) return "[object Number]"; + else if (typeof this === "symbol" || this instanceof Symbol) return "[object Symbol]"; + else if (typeof this === "string" || this instanceof String) return "[object String]"; + else if (typeof this === "boolean" || this instanceof Boolean) return "[object Boolean]"; + else if (typeof this === "function") return "[object Function]"; + else return "[object Object]"; + }); + defineField(Object.prototype, "valueOf", true, false, true, function() { + return this; + }); + + target.Boolean = Boolean; + + var Function = function() { + if (invokeType(arguments) === "new") return Function(value); + + var res = ["return function ("]; + + for (var i = 0; i < arguments.length - 1; i++) { + if (i > 0) res[res.length] = ","; + res[res.length] = arguments[i]; + } + res[res.length] = "){"; + res[res.length] = String(arguments[arguments.length - 1]); + res[res.length] = "}"; + + log(res); + + return compile(stringBuild(res))(); + }; + + defineField(Function, "compile", true, false, true, function(src, options) { + if (options == null) options = {}; + if (src == null) src = ""; + + if (options.globals == null) options.globals = []; + if (options.wrap == null) options.wrap = true; + + var res = []; + + if (options.wrap) res[res.length] = "return (function() {\n"; + if (options.globals.length > 0) { + res[res.length] = "var "; + + for (var i = 0; i < options.globals.length; i++) { + if (i > 0) res[res.length] = ","; + res[res.length] = options.globals[i]; + } + + res[res.length] = ";(function(g){"; + + for (var i = 0; i < options.globals.length; i++) { + var name = options.globals[i]; + res[res.length] = name; + res[res.length] = "=g["; + res[res.length] = json.stringify(name); + res[res.length] = "];"; + } + + res[res.length] = "})(arguments[0] || {});\n"; + } + + res[res.length] = src; + if (options.wrap) res[res.length] = "\n})(arguments[0])"; + + return compile(stringBuild(res)); + }); + defineField(Function, "prototype", false, false, false, setPrototype({}, null)); + + defineField(Function.prototype, "toString", true, false, true, function() { + if (this.name !== "") return "function " + this.name + "(...) { ... }"; + else return "function (...) { ... }"; + }); + defineField(Function.prototype, "valueOf", true, false, true, function() { + return this; + }); + + target.Function = Function; + + setGlobalPrototype("string", String.prototype); + setGlobalPrototype("number", Number.prototype); + setGlobalPrototype("boolean", Boolean.prototype); + setGlobalPrototype("symbol", Symbol.prototype); + setGlobalPrototype("object", Object.prototype); +})(arguments[0], arguments[1]); \ No newline at end of file diff --git a/src/java/me/topchetoeu/jscript/common/Compiler.java b/src/java/me/topchetoeu/jscript/common/Compiler.java index 812530a..5944988 100644 --- a/src/java/me/topchetoeu/jscript/common/Compiler.java +++ b/src/java/me/topchetoeu/jscript/common/Compiler.java @@ -1,18 +1,18 @@ package me.topchetoeu.jscript.common; +import me.topchetoeu.jscript.common.environment.Environment; +import me.topchetoeu.jscript.common.environment.Key; import me.topchetoeu.jscript.common.parsing.Filename; import me.topchetoeu.jscript.compilation.CompileResult; -import me.topchetoeu.jscript.compilation.ES5; +import me.topchetoeu.jscript.compilation.JavaScript; import me.topchetoeu.jscript.runtime.debug.DebugContext; -import me.topchetoeu.jscript.runtime.environment.Environment; -import me.topchetoeu.jscript.runtime.environment.Key; import me.topchetoeu.jscript.runtime.exceptions.EngineException; import me.topchetoeu.jscript.runtime.scope.ValueVariable; import me.topchetoeu.jscript.runtime.values.functions.CodeFunction; public interface Compiler { public static final Compiler DEFAULT = (env, filename, raw) -> { - var res = ES5.compile(filename, raw); + var res = JavaScript.compile(filename, raw); var body = res.body(); DebugContext.get(env).onSource(filename, raw); registerFunc(env, body, res); @@ -20,7 +20,7 @@ public interface Compiler { return body; }; - public Key KEY = new Key<>(); + public Key KEY = Key.of(); public FunctionBody compile(Environment env, Filename filename, String source); diff --git a/src/java/me/topchetoeu/jscript/common/environment/Environment.java b/src/java/me/topchetoeu/jscript/common/environment/Environment.java new file mode 100644 index 0000000..7bb724e --- /dev/null +++ b/src/java/me/topchetoeu/jscript/common/environment/Environment.java @@ -0,0 +1,195 @@ +package me.topchetoeu.jscript.common.environment; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Random; +import java.util.Set; +import java.util.function.Supplier; + +public class Environment { + public final Environment parent; + private final Map, Object> map = new HashMap<>(); + private final Set> hidden = new HashSet<>(); + + private final Map, Set> multi = new HashMap<>(); + private final Map, Set> multiHidden = new HashMap<>(); + + @SuppressWarnings("unchecked") + private Set getAll(MultiKey key, boolean forceClone) { + Set parent = null, child = null; + boolean cloned = false; + + if (this.parent != null && !hidden.contains(key)) { + parent = this.parent.getAll(key, false); + if (parent.size() == 0) parent = null; + else if (multiHidden.containsKey(key)) { + parent = new HashSet<>(parent); + parent.removeAll(multiHidden.get(key)); + cloned = true; + } + } + if (multi.containsKey(key)) { + child = (Set)multi.get(key); + if (child.size() == 0) child = null; + } + + if (!forceClone) { + if (parent == null && child == null) return Set.of(); + if (parent == null && child != null) return child; + if (parent != null && child == null) return parent; + } + + if (!cloned) parent = new HashSet<>(); + parent.addAll(child); + return parent; + } + private T getMulti(MultiKey key) { + return key.of(getAll(key, false)); + } + private boolean hasMulti(MultiKey key) { + return getAll(key, false).size() > 0; + } + + @SuppressWarnings("all") + private Environment addMulti(MultiKey key, T value) { + if (!multi.containsKey(key)) { + if (hidden.contains(key)) { + multiHidden.put((MultiKey)key, (Set)parent.getAll(key, true)); + hidden.remove(key); + } + + multi.put((MultiKey)key, new HashSet<>()); + } + + multi.get(key).add(value); + return this; + } + + @SuppressWarnings("unchecked") + public T get(Key key) { + if (key instanceof MultiKey) return getMulti((MultiKey)key); + + if (map.containsKey(key)) return (T)map.get(key); + else if (!hidden.contains(key) && parent != null) return parent.get(key); + else return null; + } + public boolean has(Key key) { + if (key instanceof MultiKey) return hasMulti((MultiKey)key); + + if (map.containsKey(key)) return true; + else if (!hidden.contains(key) && parent != null) return parent.has(key); + else return false; + } + + public boolean hasNotNull(Key key) { + return get(key) != null; + } + + public T get(Key key, T defaultVal) { + if (has(key)) return get(key); + else return defaultVal; + } + public T get(Key key, Supplier defaultVal) { + if (has(key)) return get(key); + else return defaultVal.get(); + } + + @SuppressWarnings("unchecked") + public Environment add(Key key, T val) { + if (key instanceof MultiKey) return add(key, val); + + map.put((Key)key, val); + hidden.remove(key); + return this; + } + public Environment add(Key key) { + return add(key, null); + } + @SuppressWarnings("all") + public Environment addAll(Map, ?> map, boolean iterableAsMulti) { + for (var pair : map.entrySet()) { + if (iterableAsMulti && pair.getKey() instanceof MultiKey && pair.getValue() instanceof Iterable) { + for (var val : (Iterable)pair.getValue()) { + addMulti((MultiKey)pair.getKey(), val); + } + } + else add((Key)pair.getKey(), pair.getValue()); + } + map.putAll((Map)map); + hidden.removeAll(map.keySet()); + return this; + } + public Environment addAll(Map, ?> map) { + return addAll(map, true); + } + // public Environment addAll(Environment env) { + // this.map.putAll(env.map); + // this.hidden.removeAll(env.map.keySet()); + + // for (var el : env.multi.entrySet()) { + // for (var val : el.getValue()) { + // add(el.getKey(), val); + // } + // } + + // return this; + // } + + @SuppressWarnings("unchecked") + public Environment remove(Key key) { + map.remove(key); + multi.remove(key); + multiHidden.remove(key); + hidden.add((Key)key); + return this; + } + @SuppressWarnings("all") + public Environment remove(MultiKey key, T val) { + if (multi.containsKey(key)) { + multi.get(key).remove(val); + multiHidden.get(key).add(val); + + if (multi.get(key).size() == 0) { + multi.remove(key); + multiHidden.remove(key); + hidden.add((Key)key); + } + } + + return this; + } + + public Environment init(Key key, T val) { + if (!has(key)) this.add(key, val); + return this; + } + public Environment init(Key key, Supplier val) { + if (!has(key)) this.add(key, val.get()); + return this; + } + + public Environment child() { + return new Environment(this); + } + + public Environment(Environment parent) { + this.parent = parent; + } + public Environment() { + this.parent = null; + } + + public static Environment wrap(Environment env) { + if (env == null) return empty(); + else return env; + } + + public static Environment empty() { + return new Environment(); + } + + public static int nextId() { + return new Random().nextInt(); + } +} diff --git a/src/java/me/topchetoeu/jscript/common/environment/Key.java b/src/java/me/topchetoeu/jscript/common/environment/Key.java new file mode 100644 index 0000000..1bb96b3 --- /dev/null +++ b/src/java/me/topchetoeu/jscript/common/environment/Key.java @@ -0,0 +1,7 @@ +package me.topchetoeu.jscript.common.environment; + +public interface Key { + public static Key of() { + return new Key<>() { }; + } +} diff --git a/src/java/me/topchetoeu/jscript/common/environment/MultiKey.java b/src/java/me/topchetoeu/jscript/common/environment/MultiKey.java new file mode 100644 index 0000000..79e8404 --- /dev/null +++ b/src/java/me/topchetoeu/jscript/common/environment/MultiKey.java @@ -0,0 +1,7 @@ +package me.topchetoeu.jscript.common.environment; + +import java.util.Set; + +public interface MultiKey extends Key { + public T of(Set values); +} diff --git a/src/java/me/topchetoeu/jscript/runtime/EventLoop.java b/src/java/me/topchetoeu/jscript/runtime/EventLoop.java index 3d48364..0227682 100644 --- a/src/java/me/topchetoeu/jscript/runtime/EventLoop.java +++ b/src/java/me/topchetoeu/jscript/runtime/EventLoop.java @@ -4,15 +4,15 @@ import java.util.concurrent.Future; import java.util.function.Supplier; import me.topchetoeu.jscript.common.Compiler; +import me.topchetoeu.jscript.common.environment.Environment; +import me.topchetoeu.jscript.common.environment.Key; import me.topchetoeu.jscript.common.parsing.Filename; -import me.topchetoeu.jscript.runtime.environment.Environment; -import me.topchetoeu.jscript.runtime.environment.Key; import me.topchetoeu.jscript.runtime.exceptions.EngineException; import me.topchetoeu.jscript.runtime.values.Value; import me.topchetoeu.jscript.runtime.values.functions.FunctionValue; public interface EventLoop { - public static final Key KEY = new Key<>(); + public static final Key KEY = Key.of(); public static EventLoop get(Environment ext) { if (ext.hasNotNull(KEY)) return ext.get(KEY); diff --git a/src/java/me/topchetoeu/jscript/runtime/Frame.java b/src/java/me/topchetoeu/jscript/runtime/Frame.java index 4741223..cc56651 100644 --- a/src/java/me/topchetoeu/jscript/runtime/Frame.java +++ b/src/java/me/topchetoeu/jscript/runtime/Frame.java @@ -6,9 +6,9 @@ import java.util.Map; import java.util.Stack; import me.topchetoeu.jscript.common.Instruction; +import me.topchetoeu.jscript.common.environment.Environment; +import me.topchetoeu.jscript.common.environment.Key; import me.topchetoeu.jscript.runtime.debug.DebugContext; -import me.topchetoeu.jscript.runtime.environment.Environment; -import me.topchetoeu.jscript.runtime.environment.Key; import me.topchetoeu.jscript.runtime.exceptions.EngineException; import me.topchetoeu.jscript.runtime.exceptions.InterruptException; import me.topchetoeu.jscript.runtime.scope.LocalScope; @@ -20,10 +20,9 @@ import me.topchetoeu.jscript.runtime.values.Member.FieldMember; import me.topchetoeu.jscript.runtime.values.functions.CodeFunction; import me.topchetoeu.jscript.runtime.values.objects.ObjectValue; import me.topchetoeu.jscript.runtime.values.objects.ScopeValue; -import me.topchetoeu.jscript.runtime.values.primitives.VoidValue; public class Frame { - public static final Key KEY = new Key<>(); + public static final Key KEY = Key.of(); public static enum TryState { TRY, @@ -127,7 +126,7 @@ public class Frame { else return stack[stackPtr - 1 - offset]; } public Value pop() { - if (stackPtr == 0) return VoidValue.UNDEFINED; + if (stackPtr == 0) return Value.UNDEFINED; return stack[--stackPtr]; } public Value[] take(int n) { @@ -138,7 +137,7 @@ public class Frame { int copyN = stackPtr - srcI; Value[] res = new Value[n]; - Arrays.fill(res, VoidValue.UNDEFINED); + Arrays.fill(res, Value.UNDEFINED); System.arraycopy(stack, srcI, res, dstI, copyN); stackPtr -= copyN; diff --git a/src/java/me/topchetoeu/jscript/runtime/InstructionRunner.java b/src/java/me/topchetoeu/jscript/runtime/InstructionRunner.java index 67ce302..4b0db70 100644 --- a/src/java/me/topchetoeu/jscript/runtime/InstructionRunner.java +++ b/src/java/me/topchetoeu/jscript/runtime/InstructionRunner.java @@ -5,7 +5,7 @@ import java.util.Collections; import me.topchetoeu.jscript.common.Instruction; import me.topchetoeu.jscript.common.Operation; -import me.topchetoeu.jscript.runtime.environment.Environment; +import me.topchetoeu.jscript.common.environment.Environment; import me.topchetoeu.jscript.runtime.exceptions.EngineException; import me.topchetoeu.jscript.runtime.scope.GlobalScope; import me.topchetoeu.jscript.runtime.scope.ValueVariable; @@ -19,7 +19,6 @@ import me.topchetoeu.jscript.runtime.values.objects.ObjectValue; import me.topchetoeu.jscript.runtime.values.primitives.BoolValue; import me.topchetoeu.jscript.runtime.values.primitives.NumberValue; import me.topchetoeu.jscript.runtime.values.primitives.StringValue; -import me.topchetoeu.jscript.runtime.values.primitives.VoidValue; public class InstructionRunner { private static Value execReturn(Environment env, Instruction instr, Frame frame) { @@ -36,7 +35,7 @@ public class InstructionRunner { var callArgs = frame.take(instr.get(0)); var func = frame.pop(); - frame.push(func.call(env, false, instr.get(1), VoidValue.UNDEFINED, callArgs)); + frame.push(func.call(env, false, instr.get(1), Value.UNDEFINED, callArgs)); frame.codePtr++; return null; @@ -75,11 +74,11 @@ public class InstructionRunner { FunctionValue getter, setter; - if (getterVal == VoidValue.UNDEFINED) getter = null; + if (getterVal == Value.UNDEFINED) getter = null; else if (getterVal instanceof FunctionValue) getter = (FunctionValue)getterVal; else throw EngineException.ofType("Getter must be a function or undefined."); - if (setterVal == VoidValue.UNDEFINED) setter = null; + if (setterVal == Value.UNDEFINED) setter = null; else if (setterVal instanceof FunctionValue) setter = (FunctionValue)setterVal; else throw EngineException.ofType("Setter must be a function or undefined."); @@ -135,8 +134,8 @@ public class InstructionRunner { } private static Value execLoadValue(Environment env, Instruction instr, Frame frame) { switch (instr.type) { - case PUSH_UNDEFINED: frame.push(VoidValue.UNDEFINED); break; - case PUSH_NULL: frame.push(VoidValue.NULL); break; + case PUSH_UNDEFINED: frame.push(Value.UNDEFINED); break; + case PUSH_NULL: frame.push(Value.NULL); break; case PUSH_BOOL: frame.push(BoolValue.of(instr.get(0))); break; case PUSH_NUMBER: frame.push(new NumberValue(instr.get(0))); break; case PUSH_STRING: frame.push(new StringValue(instr.get(0))); break; @@ -157,7 +156,7 @@ public class InstructionRunner { } private static Value execLoadObj(Environment env, Instruction instr, Frame frame) { var obj = new ObjectValue(); - obj.setPrototype(Environment.OBJECT_PROTO); + obj.setPrototype(Value.OBJECT_PROTO); frame.push(obj); frame.codePtr++; return null; @@ -204,8 +203,8 @@ public class InstructionRunner { return null; } private static Value execLoadRegEx(Environment env, Instruction instr, Frame frame) { - if (env.hasNotNull(Environment.REGEX_CONSTR)) { - frame.push(env.get(Environment.REGEX_CONSTR).callNew(env, instr.get(0), instr.get(1))); + if (env.hasNotNull(Value.REGEX_CONSTR)) { + frame.push(env.get(Value.REGEX_CONSTR).callNew(env, instr.get(0), instr.get(1))); } else { throw EngineException.ofSyntax("Regex is not supported."); diff --git a/src/java/me/topchetoeu/jscript/runtime/JSONConverter.java b/src/java/me/topchetoeu/jscript/runtime/JSONConverter.java index ab4c9fd..b895dea 100644 --- a/src/java/me/topchetoeu/jscript/runtime/JSONConverter.java +++ b/src/java/me/topchetoeu/jscript/runtime/JSONConverter.java @@ -3,10 +3,10 @@ package me.topchetoeu.jscript.runtime; import java.util.HashSet; import java.util.stream.Collectors; +import me.topchetoeu.jscript.common.environment.Environment; 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.runtime.environment.Environment; import me.topchetoeu.jscript.runtime.exceptions.EngineException; import me.topchetoeu.jscript.runtime.values.Member.FieldMember; import me.topchetoeu.jscript.runtime.values.Value; @@ -32,8 +32,8 @@ public class JSONConverter { return res; } - if (val.isNull()) return VoidValue.NULL; - return VoidValue.UNDEFINED; + if (val.isNull()) return Value.NULL; + return Value.UNDEFINED; } public static JSONElement fromJs(Environment ext, Value val) { @@ -46,7 +46,7 @@ public class JSONConverter { if (val instanceof BoolValue) return JSONElement.bool(((BoolValue)val).value); if (val instanceof NumberValue) return JSONElement.number(((NumberValue)val).value); if (val instanceof StringValue) return JSONElement.string(((StringValue)val).value); - if (val == VoidValue.NULL) return JSONElement.NULL; + if (val == Value.NULL) return JSONElement.NULL; if (val instanceof VoidValue) return null; if (val instanceof ArrayValue) { diff --git a/src/java/me/topchetoeu/jscript/runtime/SimpleRepl.java b/src/java/me/topchetoeu/jscript/runtime/SimpleRepl.java index 551d4b6..18a4278 100644 --- a/src/java/me/topchetoeu/jscript/runtime/SimpleRepl.java +++ b/src/java/me/topchetoeu/jscript/runtime/SimpleRepl.java @@ -9,16 +9,25 @@ import java.util.concurrent.ExecutionException; import me.topchetoeu.jscript.common.Compiler; import me.topchetoeu.jscript.common.Metadata; import me.topchetoeu.jscript.common.Reading; +import me.topchetoeu.jscript.common.environment.Environment; +import me.topchetoeu.jscript.common.json.JSON; import me.topchetoeu.jscript.common.parsing.Filename; import me.topchetoeu.jscript.runtime.debug.DebugContext; -import me.topchetoeu.jscript.runtime.environment.Environment; import me.topchetoeu.jscript.runtime.exceptions.EngineException; import me.topchetoeu.jscript.runtime.exceptions.InterruptException; import me.topchetoeu.jscript.runtime.exceptions.SyntaxException; import me.topchetoeu.jscript.runtime.scope.GlobalScope; +import me.topchetoeu.jscript.runtime.values.Member.FieldMember; +import me.topchetoeu.jscript.runtime.values.Member.PropertyMember; import me.topchetoeu.jscript.runtime.values.Value; +import me.topchetoeu.jscript.runtime.values.functions.FunctionValue; import me.topchetoeu.jscript.runtime.values.functions.NativeFunction; +import me.topchetoeu.jscript.runtime.values.objects.ArrayValue; +import me.topchetoeu.jscript.runtime.values.objects.ObjectValue; +import me.topchetoeu.jscript.runtime.values.primitives.BoolValue; +import me.topchetoeu.jscript.runtime.values.primitives.NumberValue; import me.topchetoeu.jscript.runtime.values.primitives.StringValue; +import me.topchetoeu.jscript.runtime.values.primitives.SymbolValue; import me.topchetoeu.jscript.runtime.values.primitives.VoidValue; public class SimpleRepl { @@ -31,6 +40,11 @@ public class SimpleRepl { private static void reader() { try { + try { + try { initGlobals(); } catch (ExecutionException e) { throw e.getCause(); } + } + catch (EngineException | SyntaxException e) { System.err.println(Value.errorToReadable(e, null)); } + for (var arg : args) { try { var file = Path.of(arg); @@ -59,7 +73,7 @@ public class SimpleRepl { var res = engine.pushMsg( false, environment, new Filename("jscript", "repl/" + i + ".js"), raw, - VoidValue.UNDEFINED + Value.UNDEFINED ).get(); System.err.println(res.toReadable(environment)); } @@ -79,10 +93,240 @@ public class SimpleRepl { } } + private static ObjectValue symbolPrimordials(Environment env) { + var res = new ObjectValue(); + res.setPrototype(null, null); + + res.defineOwnMember(env, "makeSymbol", new NativeFunction(args -> new SymbolValue(args.get(0).toString(args.env).value))); + res.defineOwnMember(env, "getSymbol", new NativeFunction(args -> SymbolValue.get(args.get(0).toString(args.env).value))); + res.defineOwnMember(env, "getSymbolKey", new NativeFunction(args -> ((SymbolValue)args.get(0)).key())); + res.defineOwnMember(env, "getSymbolDescriptor", new NativeFunction(args -> new StringValue(((SymbolValue)args.get(0)).value))); + + return res; + } + + private static ObjectValue numberPrimordials(Environment env) { + var res = new ObjectValue(); + res.setPrototype(null, null); + + res.defineOwnMember(env, "parseInt", new NativeFunction(args -> { + var radix = args.get(1).toInt(env); + + if (radix != 10 && args.get(0) instanceof NumberValue) { + return new NumberValue(args.get(0).toNumber(env).value - args.get(0).toNumber(env).value % 1); + } + else { + return NumberValue.parseInt(args.get(0).toString(), radix, false); + } + })); + res.defineOwnMember(env, "parseFloat", new NativeFunction(args -> { + if (args.get(0) instanceof NumberValue) { + return args.get(0); + } + else return NumberValue.parseFloat(args.get(0).toString(), false); + })); + res.defineOwnMember(env, "isNaN", new NativeFunction(args -> BoolValue.of(args.get(0).isNaN()))); + res.defineOwnMember(env, "NaN", new NumberValue(Double.NaN)); + res.defineOwnMember(env, "Infinity", new NumberValue(Double.POSITIVE_INFINITY)); + + return res; + } + + private static ObjectValue stringPrimordials(Environment env) { + var res = new ObjectValue(); + res.setPrototype(null, null); + + res.defineOwnMember(env, "stringBuild", new NativeFunction(args -> { + var parts = ((ArrayValue)args.get(0)).toArray(); + var sb = new StringBuilder(); + + for (var i = 0; i < parts.length; i++) { + sb.append(((StringValue)parts[i]).value); + } + + return new StringValue(sb.toString()); + })); + + res.defineOwnMember(env, "fromCharCode", new NativeFunction(args -> { + var parts = ((ArrayValue)args.get(0)).toArray(); + var sb = new StringBuilder(); + + for (var i = 0; i < parts.length; i++) { + sb.append(((StringValue)parts[i]).value); + } + + return new StringValue(sb.toString()); + })); + + return res; + } + + private static ObjectValue objectPrimordials(Environment env) { + var res = new ObjectValue(); + res.setPrototype(null, null); + + res.defineOwnMember(env, "defineField", new NativeFunction(args -> { + var obj = (ObjectValue)args.get(0); + var key = args.get(1); + var writable = args.get(2).toBoolean(); + var enumerable = args.get(3).toBoolean(); + var configurable = args.get(4).toBoolean(); + var value = args.get(5); + + obj.defineOwnMember(args.env, key, FieldMember.of(value, enumerable, configurable, writable)); + + return Value.UNDEFINED; + })); + res.defineOwnMember(env, "defineProperty", new NativeFunction(args -> { + var obj = (ObjectValue)args.get(0); + var key = args.get(1); + var enumerable = args.get(2).toBoolean(); + var configurable = args.get(3).toBoolean(); + var getter = args.get(4) instanceof VoidValue ? null : (FunctionValue)args.get(4); + var setter = args.get(5) instanceof VoidValue ? null : (FunctionValue)args.get(5); + + obj.defineOwnMember(args.env, key, new PropertyMember(getter, setter, configurable, enumerable)); + + return Value.UNDEFINED; + })); + res.defineOwnMember(env, "getPrototype", new NativeFunction(args -> { + return args.get(0).getPrototype(env); + })); + res.defineOwnMember(env, "setPrototype", new NativeFunction(args -> { + var proto = args.get(1) instanceof VoidValue ? null : (ObjectValue)args.get(1); + args.get(0).setPrototype(env, proto); + return args.get(0); + })); + return res; + } + + private static ObjectValue functionPrimordials(Environment env) { + var res = new ObjectValue(); + res.setPrototype(null, null); + + res.defineOwnMember(env, "setCallable", new NativeFunction(args -> { + var func = (FunctionValue)args.get(0); + func.enableCall = args.get(1).toBoolean(); + return Value.UNDEFINED; + })); + res.defineOwnMember(env, "setConstructable", new NativeFunction(args -> { + var func = (FunctionValue)args.get(0); + func.enableNew = args.get(1).toBoolean(); + return Value.UNDEFINED; + })); + res.defineOwnMember(env, "invokeType", new NativeFunction(args -> { + if (((ArgumentsValue)args.get(0)).frame.isNew) return new StringValue("new"); + else return new StringValue("call"); + })); + res.defineOwnMember(env, "invoke", new NativeFunction(args -> { + var func = (FunctionValue)args.get(0); + var self = args.get(1); + var funcArgs = (ArrayValue)args.get(2); + + return func.call(env, self, funcArgs.toArray()); + })); + + return res; + } + + private static ObjectValue jsonPrimordials(Environment env) { + var res = new ObjectValue(); + res.setPrototype(null, null); + + res.defineOwnMember(env, "stringify", new NativeFunction(args -> { + return new StringValue(JSON.stringify(JSONConverter.fromJs(env, args.get(0)))); + })); + res.defineOwnMember(env, "parse", new NativeFunction(args -> { + return JSONConverter.toJs(JSON.parse(null, args.get(0).toString(env).value)); + })); + res.defineOwnMember(env, "setConstructable", new NativeFunction(args -> { + var func = (FunctionValue)args.get(0); + func.enableNew = args.get(1).toBoolean(); + return Value.UNDEFINED; + })); + res.defineOwnMember(env, "invokeType", new NativeFunction(args -> { + if (((ArgumentsValue)args.get(0)).frame.isNew) return new StringValue("new"); + else return new StringValue("call"); + })); + res.defineOwnMember(env, "invoke", new NativeFunction(args -> { + var func = (FunctionValue)args.get(0); + var self = args.get(1); + var funcArgs = (ArrayValue)args.get(2); + + return func.call(env, self, funcArgs.toArray()); + })); + + return res; + } + + private static ObjectValue primordials(Environment env) { + var res = new ObjectValue(); + res.setPrototype(null, null); + + res.defineOwnMember(env, "symbol", symbolPrimordials(env)); + res.defineOwnMember(env, "number", numberPrimordials(env)); + res.defineOwnMember(env, "string", stringPrimordials(env)); + res.defineOwnMember(env, "object", objectPrimordials(env)); + res.defineOwnMember(env, "function", functionPrimordials(env)); + res.defineOwnMember(env, "json", jsonPrimordials(env)); + + int[] i = new int[1]; + + res.defineOwnMember(env, "setGlobalPrototype", new NativeFunction(args -> { + var type = args.get(0).toString(env).value; + var obj = (ObjectValue)args.get(1); + + switch (type) { + case "string": + args.env.add(Value.STRING_PROTO, obj); + break; + case "number": + args.env.add(Value.NUMBER_PROTO, obj); + break; + case "boolean": + args.env.add(Value.BOOL_PROTO, obj); + break; + case "symbol": + args.env.add(Value.SYMBOL_PROTO, obj); + break; + case "object": + args.env.add(Value.OBJECT_PROTO, obj); + break; + } + + return Value.UNDEFINED; + })); + res.defineOwnMember(env, "compile", new NativeFunction(args -> { + return Compiler.compileFunc(env, new Filename("jscript", "func" + i[0]++ + ".js"), args.get(0).toString(env).value); + })); + return res; + } + private static void initEnv() { + // glob.define(null, false, new NativeFunction("go", args -> { + // try { + // var f = Path.of("do.js"); + // var func = Compiler.compile(args.env, new Filename("do", "do/" + j++ + ".js"), new String(Files.readAllBytes(f))); + // return func.call(args.env); + // } + // catch (IOException e) { + // throw new EngineException("Couldn't open do.js"); + // } + // })); + + // var fs = new RootFilesystem(PermissionsProvider.get(environment)); + // fs.protocols.put("temp", new MemoryFilesystem(Mode.READ_WRITE)); + // fs.protocols.put("file", new PhysicalFilesystem(".")); + // fs.protocols.put("std", new STDFilesystem(System.in, System.out, System.err)); + + // environment.add(PermissionsProvider.KEY, PermissionsManager.ALL_PERMS); + // environment.add(Filesystem.KEY, fs); + // environment.add(ModuleRepo.KEY, ModuleRepo.ofFilesystem(fs)); + // environment.add(Compiler.KEY, new JSCompiler(environment)); environment.add(EventLoop.KEY, engine); environment.add(GlobalScope.KEY, new GlobalScope()); environment.add(DebugContext.KEY, new DebugContext()); + // environment.add(EventLoop.KEY, engine); environment.add(Compiler.KEY, Compiler.DEFAULT); var glob = GlobalScope.get(environment); @@ -101,7 +345,19 @@ public class SimpleRepl { })); } private static void initEngine() { + // var ctx = new DebugContext(); + // environment.add(DebugContext.KEY, ctx); + + // debugServer.targets.put("target", (ws, req) -> new SimpleDebugger(ws).attach(ctx)); engineTask = engine.start(); + // debugTask = debugServer.start(new InetSocketAddress("127.0.0.1", 9229), true); + } + private static void initGlobals() throws InterruptedException, ExecutionException { + EventLoop.get(environment).pushMsg( + false, environment, + Filename.parse("jscript://init.js"), Reading.resourceToString("lib/index.js"), + Value.UNDEFINED, GlobalScope.get(environment).object, primordials(environment) + ).get(); } public static void main(String args[]) throws InterruptedException { diff --git a/src/java/me/topchetoeu/jscript/runtime/debug/DebugContext.java b/src/java/me/topchetoeu/jscript/runtime/debug/DebugContext.java index 0ecc549..df26c27 100644 --- a/src/java/me/topchetoeu/jscript/runtime/debug/DebugContext.java +++ b/src/java/me/topchetoeu/jscript/runtime/debug/DebugContext.java @@ -7,19 +7,19 @@ import java.util.WeakHashMap; import me.topchetoeu.jscript.common.FunctionBody; import me.topchetoeu.jscript.common.Instruction; +import me.topchetoeu.jscript.common.environment.Environment; +import me.topchetoeu.jscript.common.environment.Key; import me.topchetoeu.jscript.common.mapping.FunctionMap; import me.topchetoeu.jscript.common.parsing.Filename; import me.topchetoeu.jscript.common.parsing.Location; import me.topchetoeu.jscript.runtime.Frame; -import me.topchetoeu.jscript.runtime.environment.Environment; -import me.topchetoeu.jscript.runtime.environment.Key; import me.topchetoeu.jscript.runtime.exceptions.EngineException; import me.topchetoeu.jscript.runtime.values.functions.CodeFunction; import me.topchetoeu.jscript.runtime.values.functions.FunctionValue; public class DebugContext { - public static final Key KEY = new Key<>(); - public static final Key IGNORE = new Key<>(); + public static final Key KEY = Key.of(); + public static final Key IGNORE = Key.of(); private HashMap sources; private WeakHashMap maps; diff --git a/src/java/me/topchetoeu/jscript/runtime/debug/DebugHandler.java b/src/java/me/topchetoeu/jscript/runtime/debug/DebugHandler.java index 5bf3817..2d67c6f 100644 --- a/src/java/me/topchetoeu/jscript/runtime/debug/DebugHandler.java +++ b/src/java/me/topchetoeu/jscript/runtime/debug/DebugHandler.java @@ -4,10 +4,10 @@ import java.util.List; import me.topchetoeu.jscript.common.FunctionBody; import me.topchetoeu.jscript.common.Instruction; +import me.topchetoeu.jscript.common.environment.Environment; import me.topchetoeu.jscript.common.mapping.FunctionMap; import me.topchetoeu.jscript.common.parsing.Filename; import me.topchetoeu.jscript.runtime.Frame; -import me.topchetoeu.jscript.runtime.environment.Environment; import me.topchetoeu.jscript.runtime.exceptions.EngineException; public interface DebugHandler { diff --git a/src/java/me/topchetoeu/jscript/runtime/environment/Environment.java b/src/java/me/topchetoeu/jscript/runtime/environment/Environment.java deleted file mode 100644 index 11e10e6..0000000 --- a/src/java/me/topchetoeu/jscript/runtime/environment/Environment.java +++ /dev/null @@ -1,144 +0,0 @@ -package me.topchetoeu.jscript.runtime.environment; - -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Random; -import java.util.Set; -import java.util.function.Supplier; - -import me.topchetoeu.jscript.common.Compiler; -import me.topchetoeu.jscript.runtime.values.functions.FunctionValue; -import me.topchetoeu.jscript.runtime.values.objects.ObjectValue; - -public class Environment { - public static final Key COMPILE_FUNC = new Key<>(); - - public static final Key REGEX_CONSTR = new Key<>(); - public static final Key MAX_STACK_COUNT = new Key<>(); - public static final Key HIDE_STACK = new Key<>(); - - public static final Key OBJECT_PROTO = new Key<>(); - public static final Key FUNCTION_PROTO = new Key<>(); - public static final Key ARRAY_PROTO = new Key<>(); - public static final Key BOOL_PROTO = new Key<>(); - public static final Key NUMBER_PROTO = new Key<>(); - public static final Key STRING_PROTO = new Key<>(); - public static final Key SYMBOL_PROTO = new Key<>(); - public static final Key ERROR_PROTO = new Key<>(); - public static final Key SYNTAX_ERR_PROTO = new Key<>(); - public static final Key TYPE_ERR_PROTO = new Key<>(); - public static final Key RANGE_ERR_PROTO = new Key<>(); - - public final Environment parent; - private final Map, Object> map = new HashMap<>(); - private final Set> hidden = new HashSet<>(); - - @SuppressWarnings("unchecked") - public T get(Key key) { - if (map.containsKey(key)) return (T)map.get(key); - else if (!hidden.contains(key) && parent != null) return parent.get(key); - else return null; - } - public boolean has(Key key) { - if (map.containsKey(key)) return true; - else if (!hidden.contains(key) && parent != null) return parent.has(key); - else return false; - } - - @SuppressWarnings("all") - public Set> keys() { - if (parent != null) { - if (map.size() == 0) return (Set)map.keySet(); - - var res = new HashSet(); - res.addAll(parent.keys()); - res.addAll(map.keySet()); - return res; - } - else return (Set)map.keySet(); - } - - public boolean hasNotNull(Key key) { - return get(key) != null; - } - - public T get(Key key, T defaultVal) { - if (has(key)) return get(key); - else return defaultVal; - } - public T get(Key key, Supplier defaultVal) { - if (has(key)) return get(key); - else return defaultVal.get(); - } - - @SuppressWarnings("unchecked") - public Environment add(Key key, T val) { - map.put((Key)key, val); - hidden.remove(key); - return this; - } - @SuppressWarnings("unchecked") - public Environment add(Key key) { - map.put((Key)(Key)key, null); - hidden.remove(key); - return this; - } - @SuppressWarnings("all") - public Environment addAll(Map, ?> map) { - map.putAll((Map)map); - hidden.removeAll(map.keySet()); - return this; - } - public Environment addAll(Environment env) { - this.map.putAll(env.map); - this.hidden.removeAll(env.map.keySet()); - return this; - } - - @SuppressWarnings("unchecked") - public Environment remove(Key key) { - map.remove((Key)key); - hidden.add((Key)key); - return this; - } - - public Environment init(Key key, T val) { - if (!has(key)) this.add(key, val); - return this; - } - public Environment init(Key key, Supplier val) { - if (!has(key)) this.add(key, val.get()); - return this; - } - - public Environment child() { - return new Environment(this); - } - - public Environment(Environment parent) { - this.parent = parent; - } - public Environment() { - this.parent = null; - } - - public static Environment wrap(Environment ext) { - if (ext == null) return empty(); - else return ext; - } - - // public static Environment chain(int id, Environment ...envs) { - // var res = new Environment(); - // for (var env : envs) res.addAll(env); - // return res; - // } - - public static Environment empty() { - return new Environment(); - } - - public static int nextId() { - return new Random().nextInt(); - } -} diff --git a/src/java/me/topchetoeu/jscript/runtime/environment/Key.java b/src/java/me/topchetoeu/jscript/runtime/environment/Key.java deleted file mode 100644 index 67a5156..0000000 --- a/src/java/me/topchetoeu/jscript/runtime/environment/Key.java +++ /dev/null @@ -1,5 +0,0 @@ -package me.topchetoeu.jscript.runtime.environment; - -public class Key { - -} diff --git a/src/java/me/topchetoeu/jscript/runtime/exceptions/EngineException.java b/src/java/me/topchetoeu/jscript/runtime/exceptions/EngineException.java index 7912f09..1c0706d 100644 --- a/src/java/me/topchetoeu/jscript/runtime/exceptions/EngineException.java +++ b/src/java/me/topchetoeu/jscript/runtime/exceptions/EngineException.java @@ -3,8 +3,8 @@ package me.topchetoeu.jscript.runtime.exceptions; import java.util.ArrayList; import java.util.List; +import me.topchetoeu.jscript.common.environment.Environment; import me.topchetoeu.jscript.common.parsing.Location; -import me.topchetoeu.jscript.runtime.environment.Environment; import me.topchetoeu.jscript.runtime.values.Value; import me.topchetoeu.jscript.runtime.values.Member.FieldMember; import me.topchetoeu.jscript.runtime.values.objects.ObjectValue; @@ -19,7 +19,7 @@ public class EngineException extends RuntimeException { public final Environment ext; public boolean visible() { - return ext == null || !ext.get(Environment.HIDE_STACK, false); + return ext == null || !ext.get(Value.HIDE_STACK, false); } public String toString() { var res = ""; @@ -109,18 +109,18 @@ public class EngineException extends RuntimeException { } public static EngineException ofError(String name, String msg) { - return new EngineException(err(name, msg, env -> env.get(Environment.ERROR_PROTO))); + return new EngineException(err(name, msg, env -> env.get(Value.ERROR_PROTO))); } public static EngineException ofError(String msg) { - return new EngineException(err(null, msg, env -> env.get(Environment.ERROR_PROTO))); + return new EngineException(err(null, msg, env -> env.get(Value.ERROR_PROTO))); } public static EngineException ofSyntax(String msg) { - return new EngineException(err(null, msg, env -> env.get(Environment.SYNTAX_ERR_PROTO))); + return new EngineException(err(null, msg, env -> env.get(Value.SYNTAX_ERR_PROTO))); } public static EngineException ofType(String msg) { - return new EngineException(err(null, msg, env -> env.get(Environment.TYPE_ERR_PROTO))); + return new EngineException(err(null, msg, env -> env.get(Value.TYPE_ERR_PROTO))); } public static EngineException ofRange(String msg) { - return new EngineException(err(null, msg, env -> env.get(Environment.RANGE_ERR_PROTO))); + return new EngineException(err(null, msg, env -> env.get(Value.RANGE_ERR_PROTO))); } } diff --git a/src/java/me/topchetoeu/jscript/runtime/scope/GlobalScope.java b/src/java/me/topchetoeu/jscript/runtime/scope/GlobalScope.java index 88cd8fc..4092749 100644 --- a/src/java/me/topchetoeu/jscript/runtime/scope/GlobalScope.java +++ b/src/java/me/topchetoeu/jscript/runtime/scope/GlobalScope.java @@ -3,18 +3,17 @@ package me.topchetoeu.jscript.runtime.scope; import java.util.HashSet; import java.util.Set; -import me.topchetoeu.jscript.runtime.environment.Environment; -import me.topchetoeu.jscript.runtime.environment.Key; +import me.topchetoeu.jscript.common.environment.Environment; +import me.topchetoeu.jscript.common.environment.Key; import me.topchetoeu.jscript.runtime.exceptions.EngineException; import me.topchetoeu.jscript.runtime.values.Value; import me.topchetoeu.jscript.runtime.values.Member.FieldMember; import me.topchetoeu.jscript.runtime.values.functions.FunctionValue; import me.topchetoeu.jscript.runtime.values.objects.ObjectValue; import me.topchetoeu.jscript.runtime.values.primitives.StringValue; -import me.topchetoeu.jscript.runtime.values.primitives.VoidValue; public class GlobalScope { - public static final Key KEY = new Key<>(); + public static final Key KEY = Key.of(); public final ObjectValue object; @@ -35,7 +34,7 @@ public class GlobalScope { object.defineOwnMember(ext, name, FieldMember.of(val, !readonly)); } public void define(Environment ext, boolean readonly, String ...names) { - for (var name : names) define(ext, name, new ValueVariable(readonly, VoidValue.UNDEFINED)); + for (var name : names) define(ext, name, new ValueVariable(readonly, Value.UNDEFINED)); } public void define(Environment ext, boolean readonly, FunctionValue val) { define(ext, readonly, val.name, val); diff --git a/src/java/me/topchetoeu/jscript/runtime/scope/ValueVariable.java b/src/java/me/topchetoeu/jscript/runtime/scope/ValueVariable.java index a4b4a43..22e2329 100644 --- a/src/java/me/topchetoeu/jscript/runtime/scope/ValueVariable.java +++ b/src/java/me/topchetoeu/jscript/runtime/scope/ValueVariable.java @@ -1,6 +1,6 @@ package me.topchetoeu.jscript.runtime.scope; -import me.topchetoeu.jscript.runtime.environment.Environment; +import me.topchetoeu.jscript.common.environment.Environment; import me.topchetoeu.jscript.runtime.values.Value; public class ValueVariable implements Variable { diff --git a/src/java/me/topchetoeu/jscript/runtime/scope/Variable.java b/src/java/me/topchetoeu/jscript/runtime/scope/Variable.java index 85f5f5b..43393a1 100644 --- a/src/java/me/topchetoeu/jscript/runtime/scope/Variable.java +++ b/src/java/me/topchetoeu/jscript/runtime/scope/Variable.java @@ -1,6 +1,6 @@ package me.topchetoeu.jscript.runtime.scope; -import me.topchetoeu.jscript.runtime.environment.Environment; +import me.topchetoeu.jscript.common.environment.Environment; import me.topchetoeu.jscript.runtime.values.Value; import me.topchetoeu.jscript.runtime.values.Member.FieldMember; diff --git a/src/java/me/topchetoeu/jscript/runtime/values/KeyCache.java b/src/java/me/topchetoeu/jscript/runtime/values/KeyCache.java index df1c4c0..c1d4840 100644 --- a/src/java/me/topchetoeu/jscript/runtime/values/KeyCache.java +++ b/src/java/me/topchetoeu/jscript/runtime/values/KeyCache.java @@ -1,6 +1,6 @@ package me.topchetoeu.jscript.runtime.values; -import me.topchetoeu.jscript.runtime.environment.Environment; +import me.topchetoeu.jscript.common.environment.Environment; import me.topchetoeu.jscript.runtime.values.primitives.NumberValue; import me.topchetoeu.jscript.runtime.values.primitives.StringValue; import me.topchetoeu.jscript.runtime.values.primitives.SymbolValue; diff --git a/src/java/me/topchetoeu/jscript/runtime/values/Member.java b/src/java/me/topchetoeu/jscript/runtime/values/Member.java index 2dae69b..8f99012 100644 --- a/src/java/me/topchetoeu/jscript/runtime/values/Member.java +++ b/src/java/me/topchetoeu/jscript/runtime/values/Member.java @@ -1,10 +1,9 @@ package me.topchetoeu.jscript.runtime.values; -import me.topchetoeu.jscript.runtime.environment.Environment; +import me.topchetoeu.jscript.common.environment.Environment; import me.topchetoeu.jscript.runtime.values.functions.FunctionValue; import me.topchetoeu.jscript.runtime.values.objects.ObjectValue; import me.topchetoeu.jscript.runtime.values.primitives.BoolValue; -import me.topchetoeu.jscript.runtime.values.primitives.VoidValue; public interface Member { public static final class PropertyMember implements Member { @@ -15,7 +14,7 @@ public interface Member { @Override public Value get(Environment env, Value self) { if (getter != null) return getter.call(env, self); - else return VoidValue.UNDEFINED; + else return Value.UNDEFINED; } @Override public boolean set(Environment env, Value val, Value self) { if (setter == null) return false; @@ -41,10 +40,10 @@ public interface Member { @Override public ObjectValue descriptor(Environment env, Value self) { var res = new ObjectValue(); - if (getter == null) res.defineOwnMember(env, "getter", FieldMember.of(VoidValue.UNDEFINED)); + if (getter == null) res.defineOwnMember(env, "getter", FieldMember.of(Value.UNDEFINED)); else res.defineOwnMember(env, "getter", FieldMember.of(getter)); - if (setter == null) res.defineOwnMember(env, "setter", FieldMember.of(VoidValue.UNDEFINED)); + if (setter == null) res.defineOwnMember(env, "setter", FieldMember.of(Value.UNDEFINED)); else res.defineOwnMember(env, "setter", FieldMember.of(setter)); res.defineOwnMember(env, "enumerable", FieldMember.of(BoolValue.of(enumerable))); diff --git a/src/java/me/topchetoeu/jscript/runtime/values/Value.java b/src/java/me/topchetoeu/jscript/runtime/values/Value.java index d15e324..9282791 100644 --- a/src/java/me/topchetoeu/jscript/runtime/values/Value.java +++ b/src/java/me/topchetoeu/jscript/runtime/values/Value.java @@ -10,11 +10,12 @@ import java.util.LinkedHashMap; import java.util.Map; import me.topchetoeu.jscript.common.Operation; +import me.topchetoeu.jscript.common.environment.Environment; +import me.topchetoeu.jscript.common.environment.Key; import me.topchetoeu.jscript.common.json.JSON; import me.topchetoeu.jscript.common.json.JSONElement; import me.topchetoeu.jscript.runtime.EventLoop; import me.topchetoeu.jscript.runtime.debug.DebugContext; -import me.topchetoeu.jscript.runtime.environment.Environment; import me.topchetoeu.jscript.runtime.exceptions.EngineException; import me.topchetoeu.jscript.runtime.exceptions.SyntaxException; import me.topchetoeu.jscript.runtime.values.Member.FieldMember; @@ -48,8 +49,24 @@ public abstract class Value { } } - public static final Object NULL = new Object(); - public static final Object NO_RETURN = new Object(); + public static final Key REGEX_CONSTR = Key.of(); + + public static final Key MAX_STACK_COUNT = Key.of(); + public static final Key HIDE_STACK = Key.of(); + public static final Key OBJECT_PROTO = Key.of(); + public static final Key FUNCTION_PROTO = Key.of(); + public static final Key ARRAY_PROTO = Key.of(); + public static final Key BOOL_PROTO = Key.of(); + public static final Key NUMBER_PROTO = Key.of(); + public static final Key STRING_PROTO = Key.of(); + public static final Key SYMBOL_PROTO = Key.of(); + public static final Key ERROR_PROTO = Key.of(); + public static final Key SYNTAX_ERR_PROTO = Key.of(); + public static final Key TYPE_ERR_PROTO = Key.of(); + public static final Key RANGE_ERR_PROTO = Key.of(); + + public static final VoidValue UNDEFINED = new VoidValue("undefined", new StringValue("undefined")); + public static final VoidValue NULL = new VoidValue("null", new StringValue("object")); public abstract StringValue type(); public abstract boolean isPrimitive(); @@ -267,7 +284,7 @@ public abstract class Value { if (member != null) return member.get(env, obj); } - return VoidValue.UNDEFINED; + return Value.UNDEFINED; } public final Value getMember(Environment env, Value key) { return getMember(env, new KeyCache(key)); @@ -437,74 +454,6 @@ public abstract class Value { return a.toString(env).strictEquals(env, b.toString(env)); } - // @SuppressWarnings("unchecked") - // public static T convert(Environment ext, Class clazz) { - // if (clazz == Void.class) return null; - - // if (this instanceof NativeWrapper) { - // var res = ((NativeWrapper)this).wrapped; - // if (clazz.isInstance(res)) return (T)res; - // } - - // if (clazz == null || clazz == Object.class) return (T)this; - - // if (this instanceof ArrayValue) { - // if (clazz.isAssignableFrom(ArrayList.class)) { - // var raw = ((ArrayValue)this).toArray(); - // var res = new ArrayList<>(); - // for (var i = 0; i < raw.length; i++) res.add(convert(ext, raw[i], Object.class)); - // return (T)new ArrayList<>(res); - // } - // if (clazz.isAssignableFrom(HashSet.class)) { - // var raw = ((ArrayValue)this).toArray(); - // var res = new HashSet<>(); - // for (var i = 0; i < raw.length; i++) res.add(convert(ext, raw[i], Object.class)); - // return (T)new HashSet<>(res); - // } - // if (clazz.isArray()) { - // var raw = ((ArrayValue)this).toArray(); - // Object res = Array.newInstance(clazz.getComponentType(), raw.length); - // for (var i = 0; i < raw.length; i++) Array.set(res, i, convert(ext, raw[i], Object.class)); - // return (T)res; - // } - // } - - // if (this instanceof ObjectValue && clazz.isAssignableFrom(HashMap.class)) { - // var res = new HashMap<>(); - // for (var el : ((ObjectValue)this).values.entrySet()) res.put( - // convert(ext, el.getKey(), null), - // convert(ext, el.getValue(), null) - // ); - // return (T)res; - // } - - // if (clazz == String.class) return (T)toString(ext, this); - // if (clazz == Boolean.class || clazz == Boolean.TYPE) return (T)(Boolean)toBoolean(this); - // if (clazz == Byte.class || clazz == byte.class) return (T)(Byte)(byte)toNumber(ext, this); - // if (clazz == Integer.class || clazz == int.class) return (T)(Integer)(int)toNumber(ext, this); - // if (clazz == Long.class || clazz == long.class) return (T)(Long)(long)toNumber(ext, this); - // if (clazz == Short.class || clazz == short.class) return (T)(Short)(short)toNumber(ext, this); - // if (clazz == Float.class || clazz == float.class) return (T)(Float)(float)toNumber(ext, this); - // if (clazz == Double.class || clazz == double.class) return (T)(Double)toNumber(ext, this); - - // if (clazz == Character.class || clazz == char.class) { - // if (this instanceof Number) return (T)(Character)(char)number(this); - // else { - // var res = toString(ext, this); - // if (res.length() == 0) throw new ConvertException("\"\"", "Character"); - // else return (T)(Character)res.charAt(0); - // } - // } - - // if (this == null) return null; - // if (clazz.isInstance(this)) return (T)this; - // if (clazz.isAssignableFrom(NativeWrapper.class)) { - // return (T)NativeWrapper.of(ext, this); - // } - - // throw new ConvertException(type(this), clazz.getSimpleName()); - // } - public Iterable toIterable(Environment env) { return () -> { if (!(this instanceof FunctionValue)) return Collections.emptyIterator(); @@ -518,7 +467,7 @@ public abstract class Value { private void loadNext() { if (supplier == null) value = null; else if (consumed) { - var curr = supplier.call(env, VoidValue.UNDEFINED); + var curr = supplier.call(env, Value.UNDEFINED); if (curr == null) { supplier = null; value = null; } if (curr.getMember(env, new StringValue("done")).toBoolean()) { supplier = null; value = null; } @@ -561,12 +510,12 @@ public abstract class Value { public void callWith(Environment env, Iterable it) { for (var el : it) { - this.call(env, VoidValue.UNDEFINED, el); + this.call(env, Value.UNDEFINED, el); } } public void callWithAsync(Environment env, Iterable it, boolean async) { for (var el : it) { - env.get(EventLoop.KEY).pushMsg(() -> this.call(env, VoidValue.UNDEFINED, el), true); + env.get(EventLoop.KEY).pushMsg(() -> this.call(env, Value.UNDEFINED, el), true); } } diff --git a/src/java/me/topchetoeu/jscript/runtime/values/functions/Arguments.java b/src/java/me/topchetoeu/jscript/runtime/values/functions/Arguments.java index d6f9604..1a7f276 100644 --- a/src/java/me/topchetoeu/jscript/runtime/values/functions/Arguments.java +++ b/src/java/me/topchetoeu/jscript/runtime/values/functions/Arguments.java @@ -1,9 +1,8 @@ package me.topchetoeu.jscript.runtime.values.functions; -import me.topchetoeu.jscript.runtime.environment.Environment; +import me.topchetoeu.jscript.common.environment.Environment; import me.topchetoeu.jscript.runtime.values.Value; -import me.topchetoeu.jscript.runtime.values.primitives.VoidValue; public class Arguments { public final Value self; @@ -23,7 +22,7 @@ public class Arguments { return get(-1); } public Value get(int i) { - if (i >= args.length || i < -1) return VoidValue.UNDEFINED; + if (i >= args.length || i < -1) return Value.UNDEFINED; else if (i == -1) return self; else return args[i]; } diff --git a/src/java/me/topchetoeu/jscript/runtime/values/functions/CodeFunction.java b/src/java/me/topchetoeu/jscript/runtime/values/functions/CodeFunction.java index 6c70cb3..b462e5f 100644 --- a/src/java/me/topchetoeu/jscript/runtime/values/functions/CodeFunction.java +++ b/src/java/me/topchetoeu/jscript/runtime/values/functions/CodeFunction.java @@ -1,8 +1,8 @@ package me.topchetoeu.jscript.runtime.values.functions; import me.topchetoeu.jscript.common.FunctionBody; +import me.topchetoeu.jscript.common.environment.Environment; import me.topchetoeu.jscript.runtime.Frame; -import me.topchetoeu.jscript.runtime.environment.Environment; import me.topchetoeu.jscript.runtime.scope.ValueVariable; import me.topchetoeu.jscript.runtime.values.Value; diff --git a/src/java/me/topchetoeu/jscript/runtime/values/functions/FunctionValue.java b/src/java/me/topchetoeu/jscript/runtime/values/functions/FunctionValue.java index 8e4c971..543a6d1 100644 --- a/src/java/me/topchetoeu/jscript/runtime/values/functions/FunctionValue.java +++ b/src/java/me/topchetoeu/jscript/runtime/values/functions/FunctionValue.java @@ -1,6 +1,6 @@ package me.topchetoeu.jscript.runtime.values.functions; -import me.topchetoeu.jscript.runtime.environment.Environment; +import me.topchetoeu.jscript.common.environment.Environment; import me.topchetoeu.jscript.runtime.values.KeyCache; import me.topchetoeu.jscript.runtime.values.Member; import me.topchetoeu.jscript.runtime.values.Value; @@ -82,7 +82,7 @@ public abstract class FunctionValue extends ObjectValue { } public FunctionValue(String name, int length) { - setPrototype(Environment.FUNCTION_PROTO); + setPrototype(FUNCTION_PROTO); if (name == null) name = ""; this.length = length; diff --git a/src/java/me/topchetoeu/jscript/runtime/values/functions/NativeFunction.java b/src/java/me/topchetoeu/jscript/runtime/values/functions/NativeFunction.java index d671efa..4615f8d 100644 --- a/src/java/me/topchetoeu/jscript/runtime/values/functions/NativeFunction.java +++ b/src/java/me/topchetoeu/jscript/runtime/values/functions/NativeFunction.java @@ -1,6 +1,6 @@ package me.topchetoeu.jscript.runtime.values.functions; -import me.topchetoeu.jscript.runtime.environment.Environment; +import me.topchetoeu.jscript.common.environment.Environment; import me.topchetoeu.jscript.runtime.values.Value; public class NativeFunction extends FunctionValue { diff --git a/src/java/me/topchetoeu/jscript/runtime/values/objects/ArrayValue.java b/src/java/me/topchetoeu/jscript/runtime/values/objects/ArrayValue.java index f754cbc..23299ce 100644 --- a/src/java/me/topchetoeu/jscript/runtime/values/objects/ArrayValue.java +++ b/src/java/me/topchetoeu/jscript/runtime/values/objects/ArrayValue.java @@ -7,7 +7,7 @@ import java.util.Iterator; import java.util.LinkedHashMap; import java.util.Map; -import me.topchetoeu.jscript.runtime.environment.Environment; +import me.topchetoeu.jscript.common.environment.Environment; import me.topchetoeu.jscript.runtime.values.KeyCache; import me.topchetoeu.jscript.runtime.values.Member; import me.topchetoeu.jscript.runtime.values.Member.FieldMember; @@ -73,7 +73,7 @@ public class ArrayValue extends ObjectValue implements Iterable { if (i < 0 || i >= size) return null; var res = values[i]; - if (res == null) return VoidValue.UNDEFINED; + if (res == null) return Value.UNDEFINED; else return res; } public void set(int i, Value val) { @@ -217,7 +217,7 @@ public class ArrayValue extends ObjectValue implements Iterable { this(16); } public ArrayValue(int cap) { - setPrototype(env -> env.get(Environment.ARRAY_PROTO)); + setPrototype(env -> env.get(ARRAY_PROTO)); values = new Value[Math.min(cap, 16)]; size = 0; } diff --git a/src/java/me/topchetoeu/jscript/runtime/values/objects/ObjectValue.java b/src/java/me/topchetoeu/jscript/runtime/values/objects/ObjectValue.java index 0fb7528..f1c81b8 100644 --- a/src/java/me/topchetoeu/jscript/runtime/values/objects/ObjectValue.java +++ b/src/java/me/topchetoeu/jscript/runtime/values/objects/ObjectValue.java @@ -4,8 +4,8 @@ import java.util.Collections; import java.util.LinkedHashMap; import java.util.Map; -import me.topchetoeu.jscript.runtime.environment.Environment; -import me.topchetoeu.jscript.runtime.environment.Key; +import me.topchetoeu.jscript.common.environment.Environment; +import me.topchetoeu.jscript.common.environment.Key; import me.topchetoeu.jscript.runtime.exceptions.EngineException; import me.topchetoeu.jscript.runtime.values.KeyCache; import me.topchetoeu.jscript.runtime.values.Member; diff --git a/src/java/me/topchetoeu/jscript/runtime/values/objects/ScopeValue.java b/src/java/me/topchetoeu/jscript/runtime/values/objects/ScopeValue.java index 38ba524..0d4ae0e 100644 --- a/src/java/me/topchetoeu/jscript/runtime/values/objects/ScopeValue.java +++ b/src/java/me/topchetoeu/jscript/runtime/values/objects/ScopeValue.java @@ -1,6 +1,6 @@ package me.topchetoeu.jscript.runtime.values.objects; -import me.topchetoeu.jscript.runtime.environment.Environment; +import me.topchetoeu.jscript.common.environment.Environment; import me.topchetoeu.jscript.runtime.scope.ValueVariable; import me.topchetoeu.jscript.runtime.values.Value; import me.topchetoeu.jscript.runtime.values.Member.FieldMember; diff --git a/src/java/me/topchetoeu/jscript/runtime/values/primitives/BoolValue.java b/src/java/me/topchetoeu/jscript/runtime/values/primitives/BoolValue.java index f4d32a6..a869252 100644 --- a/src/java/me/topchetoeu/jscript/runtime/values/primitives/BoolValue.java +++ b/src/java/me/topchetoeu/jscript/runtime/values/primitives/BoolValue.java @@ -1,6 +1,6 @@ package me.topchetoeu.jscript.runtime.values.primitives; -import me.topchetoeu.jscript.runtime.environment.Environment; +import me.topchetoeu.jscript.common.environment.Environment; import me.topchetoeu.jscript.runtime.values.Value; import me.topchetoeu.jscript.runtime.values.objects.ObjectValue; @@ -20,7 +20,7 @@ public final class BoolValue extends PrimitiveValue { @Override public StringValue toString(Environment ext) { return new StringValue(value ? "true" : "false"); } @Override public ObjectValue getPrototype(Environment env) { - return env.get(Environment.BOOL_PROTO); + return env.get(BOOL_PROTO); } @Override public boolean strictEquals(Environment ext, Value other) { diff --git a/src/java/me/topchetoeu/jscript/runtime/values/primitives/NumberValue.java b/src/java/me/topchetoeu/jscript/runtime/values/primitives/NumberValue.java index abcd8e1..bfd4aac 100644 --- a/src/java/me/topchetoeu/jscript/runtime/values/primitives/NumberValue.java +++ b/src/java/me/topchetoeu/jscript/runtime/values/primitives/NumberValue.java @@ -1,10 +1,10 @@ package me.topchetoeu.jscript.runtime.values.primitives; +import me.topchetoeu.jscript.common.environment.Environment; import me.topchetoeu.jscript.common.json.JSON; import me.topchetoeu.jscript.common.json.JSONElement; import me.topchetoeu.jscript.common.parsing.Parsing; import me.topchetoeu.jscript.common.parsing.Source; -import me.topchetoeu.jscript.runtime.environment.Environment; import me.topchetoeu.jscript.runtime.values.Value; import me.topchetoeu.jscript.runtime.values.objects.ObjectValue; @@ -22,7 +22,7 @@ public final class NumberValue extends PrimitiveValue { @Override public String toString() { return JSON.stringify(JSONElement.number(value)); } @Override public ObjectValue getPrototype(Environment env) { - return env.get(Environment.NUMBER_PROTO); + return env.get(NUMBER_PROTO); } @Override public CompareResult compare(Environment env, Value other) { diff --git a/src/java/me/topchetoeu/jscript/runtime/values/primitives/PrimitiveValue.java b/src/java/me/topchetoeu/jscript/runtime/values/primitives/PrimitiveValue.java index ccbe0ae..4d18f7a 100644 --- a/src/java/me/topchetoeu/jscript/runtime/values/primitives/PrimitiveValue.java +++ b/src/java/me/topchetoeu/jscript/runtime/values/primitives/PrimitiveValue.java @@ -2,7 +2,7 @@ package me.topchetoeu.jscript.runtime.values.primitives; import java.util.Map; -import me.topchetoeu.jscript.runtime.environment.Environment; +import me.topchetoeu.jscript.common.environment.Environment; import me.topchetoeu.jscript.runtime.values.KeyCache; import me.topchetoeu.jscript.runtime.values.Member; import me.topchetoeu.jscript.runtime.values.Value; diff --git a/src/java/me/topchetoeu/jscript/runtime/values/primitives/StringValue.java b/src/java/me/topchetoeu/jscript/runtime/values/primitives/StringValue.java index 315738e..0da0f7c 100644 --- a/src/java/me/topchetoeu/jscript/runtime/values/primitives/StringValue.java +++ b/src/java/me/topchetoeu/jscript/runtime/values/primitives/StringValue.java @@ -3,9 +3,9 @@ package me.topchetoeu.jscript.runtime.values.primitives; import java.util.Map; import java.util.Objects; +import me.topchetoeu.jscript.common.environment.Environment; import me.topchetoeu.jscript.common.parsing.Parsing; import me.topchetoeu.jscript.common.parsing.Source; -import me.topchetoeu.jscript.runtime.environment.Environment; import me.topchetoeu.jscript.runtime.values.Member; import me.topchetoeu.jscript.runtime.values.Value; import me.topchetoeu.jscript.runtime.values.objects.ObjectValue; @@ -38,7 +38,7 @@ public final class StringValue extends PrimitiveValue { @Override public boolean strictEquals(Environment ext, Value other) { return (other instanceof StringValue) && Objects.equals(((StringValue)other).value, value); } - @Override public ObjectValue getPrototype(Environment env) { return env.get(Environment.STRING_PROTO); } + @Override public ObjectValue getPrototype(Environment env) { return env.get(STRING_PROTO); } @Override public Map getOwnMembers(Environment env) { // TODO Auto-generated method stub diff --git a/src/java/me/topchetoeu/jscript/runtime/values/primitives/SymbolValue.java b/src/java/me/topchetoeu/jscript/runtime/values/primitives/SymbolValue.java index cc9b954..f6cabf8 100644 --- a/src/java/me/topchetoeu/jscript/runtime/values/primitives/SymbolValue.java +++ b/src/java/me/topchetoeu/jscript/runtime/values/primitives/SymbolValue.java @@ -2,7 +2,7 @@ package me.topchetoeu.jscript.runtime.values.primitives; import java.util.HashMap; -import me.topchetoeu.jscript.runtime.environment.Environment; +import me.topchetoeu.jscript.common.environment.Environment; import me.topchetoeu.jscript.runtime.exceptions.EngineException; import me.topchetoeu.jscript.runtime.values.Value; import me.topchetoeu.jscript.runtime.values.objects.ObjectValue; @@ -14,7 +14,7 @@ public final class SymbolValue extends PrimitiveValue { public final String value; public Value key() { - return registry.containsKey(value) && registry.get(value) == this ? new StringValue(value) : VoidValue.UNDEFINED; + return registry.containsKey(value) && registry.get(value) == this ? new StringValue(value) : Value.UNDEFINED; } @Override public StringValue type() { return typeString; } @@ -30,7 +30,7 @@ public final class SymbolValue extends PrimitiveValue { @Override public boolean strictEquals(Environment ext, Value other) { return other == this; } - @Override public ObjectValue getPrototype(Environment env) { return env.get(Environment.SYMBOL_PROTO); } + @Override public ObjectValue getPrototype(Environment env) { return env.get(SYMBOL_PROTO); } @Override public String toString() { if (value == null) return "Symbol()"; diff --git a/src/java/me/topchetoeu/jscript/runtime/values/primitives/VoidValue.java b/src/java/me/topchetoeu/jscript/runtime/values/primitives/VoidValue.java index 5f20d05..5c37052 100644 --- a/src/java/me/topchetoeu/jscript/runtime/values/primitives/VoidValue.java +++ b/src/java/me/topchetoeu/jscript/runtime/values/primitives/VoidValue.java @@ -2,7 +2,7 @@ package me.topchetoeu.jscript.runtime.values.primitives; import java.util.Map; -import me.topchetoeu.jscript.runtime.environment.Environment; +import me.topchetoeu.jscript.common.environment.Environment; import me.topchetoeu.jscript.runtime.exceptions.EngineException; import me.topchetoeu.jscript.runtime.values.KeyCache; import me.topchetoeu.jscript.runtime.values.Member; @@ -10,10 +10,7 @@ import me.topchetoeu.jscript.runtime.values.Value; import me.topchetoeu.jscript.runtime.values.objects.ObjectValue; public final class VoidValue extends PrimitiveValue { - public static final VoidValue UNDEFINED = new VoidValue("undefined", new StringValue("undefined")); - public static final VoidValue NULL = new VoidValue("null", new StringValue("object")); - - private final StringValue namestring; + private final StringValue nameString; public final String name; public final StringValue typeString; @@ -21,12 +18,12 @@ public final class VoidValue extends PrimitiveValue { @Override public StringValue type() { return typeString; } @Override public boolean toBoolean() { return false; } @Override public NumberValue toNumber(Environment ext) { return NumberValue.NAN; } - @Override public StringValue toString(Environment ext) { return namestring; } + @Override public StringValue toString(Environment ext) { return nameString; } @Override public Value add(Environment ext, Value other) { if (!other.isPrimitive()) other = other.toPrimitive(ext); - if (other instanceof StringValue) return namestring.add(ext, other); + if (other instanceof StringValue) return nameString.add(ext, other); else return NumberValue.NAN; } @@ -52,6 +49,6 @@ public final class VoidValue extends PrimitiveValue { public VoidValue(String name, StringValue type) { this.name = name; this.typeString = type; - this.namestring = new StringValue(name); + this.nameString = new StringValue(name); } }