refactor: make Environment more reusable
This commit is contained in:
parent
4048d6ef1c
commit
62aba62a41
319
src/assets/lib/index.js
Normal file
319
src/assets/lib/index.js
Normal file
@ -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]);
|
@ -1,18 +1,18 @@
|
|||||||
package me.topchetoeu.jscript.common;
|
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.common.parsing.Filename;
|
||||||
import me.topchetoeu.jscript.compilation.CompileResult;
|
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.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.EngineException;
|
||||||
import me.topchetoeu.jscript.runtime.scope.ValueVariable;
|
import me.topchetoeu.jscript.runtime.scope.ValueVariable;
|
||||||
import me.topchetoeu.jscript.runtime.values.functions.CodeFunction;
|
import me.topchetoeu.jscript.runtime.values.functions.CodeFunction;
|
||||||
|
|
||||||
public interface Compiler {
|
public interface Compiler {
|
||||||
public static final Compiler DEFAULT = (env, filename, raw) -> {
|
public static final Compiler DEFAULT = (env, filename, raw) -> {
|
||||||
var res = ES5.compile(filename, raw);
|
var res = JavaScript.compile(filename, raw);
|
||||||
var body = res.body();
|
var body = res.body();
|
||||||
DebugContext.get(env).onSource(filename, raw);
|
DebugContext.get(env).onSource(filename, raw);
|
||||||
registerFunc(env, body, res);
|
registerFunc(env, body, res);
|
||||||
@ -20,7 +20,7 @@ public interface Compiler {
|
|||||||
return body;
|
return body;
|
||||||
};
|
};
|
||||||
|
|
||||||
public Key<Compiler> KEY = new Key<>();
|
public Key<Compiler> KEY = Key.of();
|
||||||
|
|
||||||
public FunctionBody compile(Environment env, Filename filename, String source);
|
public FunctionBody compile(Environment env, Filename filename, String source);
|
||||||
|
|
||||||
|
@ -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<Key<Object>, Object> map = new HashMap<>();
|
||||||
|
private final Set<Key<Object>> hidden = new HashSet<>();
|
||||||
|
|
||||||
|
private final Map<MultiKey<Object>, Set<Object>> multi = new HashMap<>();
|
||||||
|
private final Map<MultiKey<Object>, Set<Object>> multiHidden = new HashMap<>();
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
private <T> Set<T> getAll(MultiKey<T> key, boolean forceClone) {
|
||||||
|
Set<T> 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<T>)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> T getMulti(MultiKey<T> key) {
|
||||||
|
return key.of(getAll(key, false));
|
||||||
|
}
|
||||||
|
private boolean hasMulti(MultiKey<?> key) {
|
||||||
|
return getAll(key, false).size() > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("all")
|
||||||
|
private <T> Environment addMulti(MultiKey<T> 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> T get(Key<T> key) {
|
||||||
|
if (key instanceof MultiKey) return getMulti((MultiKey<T>)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> T get(Key<T> key, T defaultVal) {
|
||||||
|
if (has(key)) return get(key);
|
||||||
|
else return defaultVal;
|
||||||
|
}
|
||||||
|
public <T> T get(Key<T> key, Supplier<T> defaultVal) {
|
||||||
|
if (has(key)) return get(key);
|
||||||
|
else return defaultVal.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public <T> Environment add(Key<T> key, T val) {
|
||||||
|
if (key instanceof MultiKey) return add(key, val);
|
||||||
|
|
||||||
|
map.put((Key<Object>)key, val);
|
||||||
|
hidden.remove(key);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
public Environment add(Key<Void> key) {
|
||||||
|
return add(key, null);
|
||||||
|
}
|
||||||
|
@SuppressWarnings("all")
|
||||||
|
public Environment addAll(Map<Key<?>, ?> 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<Object>)pair.getKey(), val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else add((Key<Object>)pair.getKey(), pair.getValue());
|
||||||
|
}
|
||||||
|
map.putAll((Map)map);
|
||||||
|
hidden.removeAll(map.keySet());
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
public Environment addAll(Map<Key<?>, ?> 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<Object>)key);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
@SuppressWarnings("all")
|
||||||
|
public <T> Environment remove(MultiKey<T> 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 <T> Environment init(Key<T> key, T val) {
|
||||||
|
if (!has(key)) this.add(key, val);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
public <T> Environment init(Key<T> key, Supplier<T> 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();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,7 @@
|
|||||||
|
package me.topchetoeu.jscript.common.environment;
|
||||||
|
|
||||||
|
public interface Key<T> {
|
||||||
|
public static <T> Key<T> of() {
|
||||||
|
return new Key<>() { };
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,7 @@
|
|||||||
|
package me.topchetoeu.jscript.common.environment;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
public interface MultiKey<T> extends Key<T> {
|
||||||
|
public T of(Set<T> values);
|
||||||
|
}
|
@ -4,15 +4,15 @@ import java.util.concurrent.Future;
|
|||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
import me.topchetoeu.jscript.common.Compiler;
|
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.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.exceptions.EngineException;
|
||||||
import me.topchetoeu.jscript.runtime.values.Value;
|
import me.topchetoeu.jscript.runtime.values.Value;
|
||||||
import me.topchetoeu.jscript.runtime.values.functions.FunctionValue;
|
import me.topchetoeu.jscript.runtime.values.functions.FunctionValue;
|
||||||
|
|
||||||
public interface EventLoop {
|
public interface EventLoop {
|
||||||
public static final Key<EventLoop> KEY = new Key<>();
|
public static final Key<EventLoop> KEY = Key.of();
|
||||||
|
|
||||||
public static EventLoop get(Environment ext) {
|
public static EventLoop get(Environment ext) {
|
||||||
if (ext.hasNotNull(KEY)) return ext.get(KEY);
|
if (ext.hasNotNull(KEY)) return ext.get(KEY);
|
||||||
|
@ -6,9 +6,9 @@ import java.util.Map;
|
|||||||
import java.util.Stack;
|
import java.util.Stack;
|
||||||
|
|
||||||
import me.topchetoeu.jscript.common.Instruction;
|
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.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.EngineException;
|
||||||
import me.topchetoeu.jscript.runtime.exceptions.InterruptException;
|
import me.topchetoeu.jscript.runtime.exceptions.InterruptException;
|
||||||
import me.topchetoeu.jscript.runtime.scope.LocalScope;
|
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.functions.CodeFunction;
|
||||||
import me.topchetoeu.jscript.runtime.values.objects.ObjectValue;
|
import me.topchetoeu.jscript.runtime.values.objects.ObjectValue;
|
||||||
import me.topchetoeu.jscript.runtime.values.objects.ScopeValue;
|
import me.topchetoeu.jscript.runtime.values.objects.ScopeValue;
|
||||||
import me.topchetoeu.jscript.runtime.values.primitives.VoidValue;
|
|
||||||
|
|
||||||
public class Frame {
|
public class Frame {
|
||||||
public static final Key<Frame> KEY = new Key<>();
|
public static final Key<Frame> KEY = Key.of();
|
||||||
|
|
||||||
public static enum TryState {
|
public static enum TryState {
|
||||||
TRY,
|
TRY,
|
||||||
@ -127,7 +126,7 @@ public class Frame {
|
|||||||
else return stack[stackPtr - 1 - offset];
|
else return stack[stackPtr - 1 - offset];
|
||||||
}
|
}
|
||||||
public Value pop() {
|
public Value pop() {
|
||||||
if (stackPtr == 0) return VoidValue.UNDEFINED;
|
if (stackPtr == 0) return Value.UNDEFINED;
|
||||||
return stack[--stackPtr];
|
return stack[--stackPtr];
|
||||||
}
|
}
|
||||||
public Value[] take(int n) {
|
public Value[] take(int n) {
|
||||||
@ -138,7 +137,7 @@ public class Frame {
|
|||||||
int copyN = stackPtr - srcI;
|
int copyN = stackPtr - srcI;
|
||||||
|
|
||||||
Value[] res = new Value[n];
|
Value[] res = new Value[n];
|
||||||
Arrays.fill(res, VoidValue.UNDEFINED);
|
Arrays.fill(res, Value.UNDEFINED);
|
||||||
System.arraycopy(stack, srcI, res, dstI, copyN);
|
System.arraycopy(stack, srcI, res, dstI, copyN);
|
||||||
stackPtr -= copyN;
|
stackPtr -= copyN;
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ import java.util.Collections;
|
|||||||
|
|
||||||
import me.topchetoeu.jscript.common.Instruction;
|
import me.topchetoeu.jscript.common.Instruction;
|
||||||
import me.topchetoeu.jscript.common.Operation;
|
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.exceptions.EngineException;
|
||||||
import me.topchetoeu.jscript.runtime.scope.GlobalScope;
|
import me.topchetoeu.jscript.runtime.scope.GlobalScope;
|
||||||
import me.topchetoeu.jscript.runtime.scope.ValueVariable;
|
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.BoolValue;
|
||||||
import me.topchetoeu.jscript.runtime.values.primitives.NumberValue;
|
import me.topchetoeu.jscript.runtime.values.primitives.NumberValue;
|
||||||
import me.topchetoeu.jscript.runtime.values.primitives.StringValue;
|
import me.topchetoeu.jscript.runtime.values.primitives.StringValue;
|
||||||
import me.topchetoeu.jscript.runtime.values.primitives.VoidValue;
|
|
||||||
|
|
||||||
public class InstructionRunner {
|
public class InstructionRunner {
|
||||||
private static Value execReturn(Environment env, Instruction instr, Frame frame) {
|
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 callArgs = frame.take(instr.get(0));
|
||||||
var func = frame.pop();
|
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++;
|
frame.codePtr++;
|
||||||
return null;
|
return null;
|
||||||
@ -75,11 +74,11 @@ public class InstructionRunner {
|
|||||||
|
|
||||||
FunctionValue getter, setter;
|
FunctionValue getter, setter;
|
||||||
|
|
||||||
if (getterVal == VoidValue.UNDEFINED) getter = null;
|
if (getterVal == Value.UNDEFINED) getter = null;
|
||||||
else if (getterVal instanceof FunctionValue) getter = (FunctionValue)getterVal;
|
else if (getterVal instanceof FunctionValue) getter = (FunctionValue)getterVal;
|
||||||
else throw EngineException.ofType("Getter must be a function or undefined.");
|
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 if (setterVal instanceof FunctionValue) setter = (FunctionValue)setterVal;
|
||||||
else throw EngineException.ofType("Setter must be a function or undefined.");
|
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) {
|
private static Value execLoadValue(Environment env, Instruction instr, Frame frame) {
|
||||||
switch (instr.type) {
|
switch (instr.type) {
|
||||||
case PUSH_UNDEFINED: frame.push(VoidValue.UNDEFINED); break;
|
case PUSH_UNDEFINED: frame.push(Value.UNDEFINED); break;
|
||||||
case PUSH_NULL: frame.push(VoidValue.NULL); break;
|
case PUSH_NULL: frame.push(Value.NULL); break;
|
||||||
case PUSH_BOOL: frame.push(BoolValue.of(instr.get(0))); 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_NUMBER: frame.push(new NumberValue(instr.get(0))); break;
|
||||||
case PUSH_STRING: frame.push(new StringValue(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) {
|
private static Value execLoadObj(Environment env, Instruction instr, Frame frame) {
|
||||||
var obj = new ObjectValue();
|
var obj = new ObjectValue();
|
||||||
obj.setPrototype(Environment.OBJECT_PROTO);
|
obj.setPrototype(Value.OBJECT_PROTO);
|
||||||
frame.push(obj);
|
frame.push(obj);
|
||||||
frame.codePtr++;
|
frame.codePtr++;
|
||||||
return null;
|
return null;
|
||||||
@ -204,8 +203,8 @@ public class InstructionRunner {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
private static Value execLoadRegEx(Environment env, Instruction instr, Frame frame) {
|
private static Value execLoadRegEx(Environment env, Instruction instr, Frame frame) {
|
||||||
if (env.hasNotNull(Environment.REGEX_CONSTR)) {
|
if (env.hasNotNull(Value.REGEX_CONSTR)) {
|
||||||
frame.push(env.get(Environment.REGEX_CONSTR).callNew(env, instr.get(0), instr.get(1)));
|
frame.push(env.get(Value.REGEX_CONSTR).callNew(env, instr.get(0), instr.get(1)));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
throw EngineException.ofSyntax("Regex is not supported.");
|
throw EngineException.ofSyntax("Regex is not supported.");
|
||||||
|
@ -3,10 +3,10 @@ package me.topchetoeu.jscript.runtime;
|
|||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.stream.Collectors;
|
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.JSONElement;
|
||||||
import me.topchetoeu.jscript.common.json.JSONList;
|
import me.topchetoeu.jscript.common.json.JSONList;
|
||||||
import me.topchetoeu.jscript.common.json.JSONMap;
|
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.exceptions.EngineException;
|
||||||
import me.topchetoeu.jscript.runtime.values.Member.FieldMember;
|
import me.topchetoeu.jscript.runtime.values.Member.FieldMember;
|
||||||
import me.topchetoeu.jscript.runtime.values.Value;
|
import me.topchetoeu.jscript.runtime.values.Value;
|
||||||
@ -32,8 +32,8 @@ public class JSONConverter {
|
|||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
if (val.isNull()) return VoidValue.NULL;
|
if (val.isNull()) return Value.NULL;
|
||||||
return VoidValue.UNDEFINED;
|
return Value.UNDEFINED;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static JSONElement fromJs(Environment ext, Value val) {
|
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 BoolValue) return JSONElement.bool(((BoolValue)val).value);
|
||||||
if (val instanceof NumberValue) return JSONElement.number(((NumberValue)val).value);
|
if (val instanceof NumberValue) return JSONElement.number(((NumberValue)val).value);
|
||||||
if (val instanceof StringValue) return JSONElement.string(((StringValue)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 VoidValue) return null;
|
||||||
|
|
||||||
if (val instanceof ArrayValue) {
|
if (val instanceof ArrayValue) {
|
||||||
|
@ -9,16 +9,25 @@ import java.util.concurrent.ExecutionException;
|
|||||||
import me.topchetoeu.jscript.common.Compiler;
|
import me.topchetoeu.jscript.common.Compiler;
|
||||||
import me.topchetoeu.jscript.common.Metadata;
|
import me.topchetoeu.jscript.common.Metadata;
|
||||||
import me.topchetoeu.jscript.common.Reading;
|
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.common.parsing.Filename;
|
||||||
import me.topchetoeu.jscript.runtime.debug.DebugContext;
|
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.EngineException;
|
||||||
import me.topchetoeu.jscript.runtime.exceptions.InterruptException;
|
import me.topchetoeu.jscript.runtime.exceptions.InterruptException;
|
||||||
import me.topchetoeu.jscript.runtime.exceptions.SyntaxException;
|
import me.topchetoeu.jscript.runtime.exceptions.SyntaxException;
|
||||||
import me.topchetoeu.jscript.runtime.scope.GlobalScope;
|
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.Value;
|
||||||
|
import me.topchetoeu.jscript.runtime.values.functions.FunctionValue;
|
||||||
import me.topchetoeu.jscript.runtime.values.functions.NativeFunction;
|
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.StringValue;
|
||||||
|
import me.topchetoeu.jscript.runtime.values.primitives.SymbolValue;
|
||||||
import me.topchetoeu.jscript.runtime.values.primitives.VoidValue;
|
import me.topchetoeu.jscript.runtime.values.primitives.VoidValue;
|
||||||
|
|
||||||
public class SimpleRepl {
|
public class SimpleRepl {
|
||||||
@ -31,6 +40,11 @@ public class SimpleRepl {
|
|||||||
|
|
||||||
private static void reader() {
|
private static void reader() {
|
||||||
try {
|
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) {
|
for (var arg : args) {
|
||||||
try {
|
try {
|
||||||
var file = Path.of(arg);
|
var file = Path.of(arg);
|
||||||
@ -59,7 +73,7 @@ public class SimpleRepl {
|
|||||||
var res = engine.pushMsg(
|
var res = engine.pushMsg(
|
||||||
false, environment,
|
false, environment,
|
||||||
new Filename("jscript", "repl/" + i + ".js"), raw,
|
new Filename("jscript", "repl/" + i + ".js"), raw,
|
||||||
VoidValue.UNDEFINED
|
Value.UNDEFINED
|
||||||
).get();
|
).get();
|
||||||
System.err.println(res.toReadable(environment));
|
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() {
|
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(EventLoop.KEY, engine);
|
||||||
environment.add(GlobalScope.KEY, new GlobalScope());
|
environment.add(GlobalScope.KEY, new GlobalScope());
|
||||||
environment.add(DebugContext.KEY, new DebugContext());
|
environment.add(DebugContext.KEY, new DebugContext());
|
||||||
|
// environment.add(EventLoop.KEY, engine);
|
||||||
environment.add(Compiler.KEY, Compiler.DEFAULT);
|
environment.add(Compiler.KEY, Compiler.DEFAULT);
|
||||||
|
|
||||||
var glob = GlobalScope.get(environment);
|
var glob = GlobalScope.get(environment);
|
||||||
@ -101,7 +345,19 @@ public class SimpleRepl {
|
|||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
private static void initEngine() {
|
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();
|
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 {
|
public static void main(String args[]) throws InterruptedException {
|
||||||
|
@ -7,19 +7,19 @@ import java.util.WeakHashMap;
|
|||||||
|
|
||||||
import me.topchetoeu.jscript.common.FunctionBody;
|
import me.topchetoeu.jscript.common.FunctionBody;
|
||||||
import me.topchetoeu.jscript.common.Instruction;
|
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.mapping.FunctionMap;
|
||||||
import me.topchetoeu.jscript.common.parsing.Filename;
|
import me.topchetoeu.jscript.common.parsing.Filename;
|
||||||
import me.topchetoeu.jscript.common.parsing.Location;
|
import me.topchetoeu.jscript.common.parsing.Location;
|
||||||
import me.topchetoeu.jscript.runtime.Frame;
|
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.exceptions.EngineException;
|
||||||
import me.topchetoeu.jscript.runtime.values.functions.CodeFunction;
|
import me.topchetoeu.jscript.runtime.values.functions.CodeFunction;
|
||||||
import me.topchetoeu.jscript.runtime.values.functions.FunctionValue;
|
import me.topchetoeu.jscript.runtime.values.functions.FunctionValue;
|
||||||
|
|
||||||
public class DebugContext {
|
public class DebugContext {
|
||||||
public static final Key<DebugContext> KEY = new Key<>();
|
public static final Key<DebugContext> KEY = Key.of();
|
||||||
public static final Key<Void> IGNORE = new Key<>();
|
public static final Key<Void> IGNORE = Key.of();
|
||||||
|
|
||||||
private HashMap<Filename, String> sources;
|
private HashMap<Filename, String> sources;
|
||||||
private WeakHashMap<FunctionBody, FunctionMap> maps;
|
private WeakHashMap<FunctionBody, FunctionMap> maps;
|
||||||
|
@ -4,10 +4,10 @@ import java.util.List;
|
|||||||
|
|
||||||
import me.topchetoeu.jscript.common.FunctionBody;
|
import me.topchetoeu.jscript.common.FunctionBody;
|
||||||
import me.topchetoeu.jscript.common.Instruction;
|
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.mapping.FunctionMap;
|
||||||
import me.topchetoeu.jscript.common.parsing.Filename;
|
import me.topchetoeu.jscript.common.parsing.Filename;
|
||||||
import me.topchetoeu.jscript.runtime.Frame;
|
import me.topchetoeu.jscript.runtime.Frame;
|
||||||
import me.topchetoeu.jscript.runtime.environment.Environment;
|
|
||||||
import me.topchetoeu.jscript.runtime.exceptions.EngineException;
|
import me.topchetoeu.jscript.runtime.exceptions.EngineException;
|
||||||
|
|
||||||
public interface DebugHandler {
|
public interface DebugHandler {
|
||||||
|
@ -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<Compiler> COMPILE_FUNC = new Key<>();
|
|
||||||
|
|
||||||
public static final Key<FunctionValue> REGEX_CONSTR = new Key<>();
|
|
||||||
public static final Key<Integer> MAX_STACK_COUNT = new Key<>();
|
|
||||||
public static final Key<Boolean> HIDE_STACK = new Key<>();
|
|
||||||
|
|
||||||
public static final Key<ObjectValue> OBJECT_PROTO = new Key<>();
|
|
||||||
public static final Key<ObjectValue> FUNCTION_PROTO = new Key<>();
|
|
||||||
public static final Key<ObjectValue> ARRAY_PROTO = new Key<>();
|
|
||||||
public static final Key<ObjectValue> BOOL_PROTO = new Key<>();
|
|
||||||
public static final Key<ObjectValue> NUMBER_PROTO = new Key<>();
|
|
||||||
public static final Key<ObjectValue> STRING_PROTO = new Key<>();
|
|
||||||
public static final Key<ObjectValue> SYMBOL_PROTO = new Key<>();
|
|
||||||
public static final Key<ObjectValue> ERROR_PROTO = new Key<>();
|
|
||||||
public static final Key<ObjectValue> SYNTAX_ERR_PROTO = new Key<>();
|
|
||||||
public static final Key<ObjectValue> TYPE_ERR_PROTO = new Key<>();
|
|
||||||
public static final Key<ObjectValue> RANGE_ERR_PROTO = new Key<>();
|
|
||||||
|
|
||||||
public final Environment parent;
|
|
||||||
private final Map<Key<Object>, Object> map = new HashMap<>();
|
|
||||||
private final Set<Key<Object>> hidden = new HashSet<>();
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public <T> T get(Key<T> 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<Key<?>> 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> T get(Key<T> key, T defaultVal) {
|
|
||||||
if (has(key)) return get(key);
|
|
||||||
else return defaultVal;
|
|
||||||
}
|
|
||||||
public <T> T get(Key<T> key, Supplier<T> defaultVal) {
|
|
||||||
if (has(key)) return get(key);
|
|
||||||
else return defaultVal.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public <T> Environment add(Key<T> key, T val) {
|
|
||||||
map.put((Key<Object>)key, val);
|
|
||||||
hidden.remove(key);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public Environment add(Key<Void> key) {
|
|
||||||
map.put((Key<Object>)(Key<?>)key, null);
|
|
||||||
hidden.remove(key);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
@SuppressWarnings("all")
|
|
||||||
public Environment addAll(Map<Key<?>, ?> 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<Object>)key);
|
|
||||||
hidden.add((Key<Object>)key);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public <T> Environment init(Key<T> key, T val) {
|
|
||||||
if (!has(key)) this.add(key, val);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
public <T> Environment init(Key<T> key, Supplier<T> 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();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,5 +0,0 @@
|
|||||||
package me.topchetoeu.jscript.runtime.environment;
|
|
||||||
|
|
||||||
public class Key<T> {
|
|
||||||
|
|
||||||
}
|
|
@ -3,8 +3,8 @@ package me.topchetoeu.jscript.runtime.exceptions;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import me.topchetoeu.jscript.common.environment.Environment;
|
||||||
import me.topchetoeu.jscript.common.parsing.Location;
|
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.Value;
|
||||||
import me.topchetoeu.jscript.runtime.values.Member.FieldMember;
|
import me.topchetoeu.jscript.runtime.values.Member.FieldMember;
|
||||||
import me.topchetoeu.jscript.runtime.values.objects.ObjectValue;
|
import me.topchetoeu.jscript.runtime.values.objects.ObjectValue;
|
||||||
@ -19,7 +19,7 @@ public class EngineException extends RuntimeException {
|
|||||||
public final Environment ext;
|
public final Environment ext;
|
||||||
|
|
||||||
public boolean visible() {
|
public boolean visible() {
|
||||||
return ext == null || !ext.get(Environment.HIDE_STACK, false);
|
return ext == null || !ext.get(Value.HIDE_STACK, false);
|
||||||
}
|
}
|
||||||
public String toString() {
|
public String toString() {
|
||||||
var res = "";
|
var res = "";
|
||||||
@ -109,18 +109,18 @@ public class EngineException extends RuntimeException {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static EngineException ofError(String name, String msg) {
|
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) {
|
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) {
|
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) {
|
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) {
|
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)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,18 +3,17 @@ package me.topchetoeu.jscript.runtime.scope;
|
|||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import me.topchetoeu.jscript.runtime.environment.Environment;
|
import me.topchetoeu.jscript.common.environment.Environment;
|
||||||
import me.topchetoeu.jscript.runtime.environment.Key;
|
import me.topchetoeu.jscript.common.environment.Key;
|
||||||
import me.topchetoeu.jscript.runtime.exceptions.EngineException;
|
import me.topchetoeu.jscript.runtime.exceptions.EngineException;
|
||||||
import me.topchetoeu.jscript.runtime.values.Value;
|
import me.topchetoeu.jscript.runtime.values.Value;
|
||||||
import me.topchetoeu.jscript.runtime.values.Member.FieldMember;
|
import me.topchetoeu.jscript.runtime.values.Member.FieldMember;
|
||||||
import me.topchetoeu.jscript.runtime.values.functions.FunctionValue;
|
import me.topchetoeu.jscript.runtime.values.functions.FunctionValue;
|
||||||
import me.topchetoeu.jscript.runtime.values.objects.ObjectValue;
|
import me.topchetoeu.jscript.runtime.values.objects.ObjectValue;
|
||||||
import me.topchetoeu.jscript.runtime.values.primitives.StringValue;
|
import me.topchetoeu.jscript.runtime.values.primitives.StringValue;
|
||||||
import me.topchetoeu.jscript.runtime.values.primitives.VoidValue;
|
|
||||||
|
|
||||||
public class GlobalScope {
|
public class GlobalScope {
|
||||||
public static final Key<GlobalScope> KEY = new Key<>();
|
public static final Key<GlobalScope> KEY = Key.of();
|
||||||
|
|
||||||
public final ObjectValue object;
|
public final ObjectValue object;
|
||||||
|
|
||||||
@ -35,7 +34,7 @@ public class GlobalScope {
|
|||||||
object.defineOwnMember(ext, name, FieldMember.of(val, !readonly));
|
object.defineOwnMember(ext, name, FieldMember.of(val, !readonly));
|
||||||
}
|
}
|
||||||
public void define(Environment ext, boolean readonly, String ...names) {
|
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) {
|
public void define(Environment ext, boolean readonly, FunctionValue val) {
|
||||||
define(ext, readonly, val.name, val);
|
define(ext, readonly, val.name, val);
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
package me.topchetoeu.jscript.runtime.scope;
|
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.Value;
|
||||||
|
|
||||||
public class ValueVariable implements Variable {
|
public class ValueVariable implements Variable {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
package me.topchetoeu.jscript.runtime.scope;
|
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.Value;
|
||||||
import me.topchetoeu.jscript.runtime.values.Member.FieldMember;
|
import me.topchetoeu.jscript.runtime.values.Member.FieldMember;
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
package me.topchetoeu.jscript.runtime.values;
|
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.NumberValue;
|
||||||
import me.topchetoeu.jscript.runtime.values.primitives.StringValue;
|
import me.topchetoeu.jscript.runtime.values.primitives.StringValue;
|
||||||
import me.topchetoeu.jscript.runtime.values.primitives.SymbolValue;
|
import me.topchetoeu.jscript.runtime.values.primitives.SymbolValue;
|
||||||
|
@ -1,10 +1,9 @@
|
|||||||
package me.topchetoeu.jscript.runtime.values;
|
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.functions.FunctionValue;
|
||||||
import me.topchetoeu.jscript.runtime.values.objects.ObjectValue;
|
import me.topchetoeu.jscript.runtime.values.objects.ObjectValue;
|
||||||
import me.topchetoeu.jscript.runtime.values.primitives.BoolValue;
|
import me.topchetoeu.jscript.runtime.values.primitives.BoolValue;
|
||||||
import me.topchetoeu.jscript.runtime.values.primitives.VoidValue;
|
|
||||||
|
|
||||||
public interface Member {
|
public interface Member {
|
||||||
public static final class PropertyMember implements Member {
|
public static final class PropertyMember implements Member {
|
||||||
@ -15,7 +14,7 @@ public interface Member {
|
|||||||
|
|
||||||
@Override public Value get(Environment env, Value self) {
|
@Override public Value get(Environment env, Value self) {
|
||||||
if (getter != null) return getter.call(env, 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) {
|
@Override public boolean set(Environment env, Value val, Value self) {
|
||||||
if (setter == null) return false;
|
if (setter == null) return false;
|
||||||
@ -41,10 +40,10 @@ public interface Member {
|
|||||||
@Override public ObjectValue descriptor(Environment env, Value self) {
|
@Override public ObjectValue descriptor(Environment env, Value self) {
|
||||||
var res = new ObjectValue();
|
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));
|
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));
|
else res.defineOwnMember(env, "setter", FieldMember.of(setter));
|
||||||
|
|
||||||
res.defineOwnMember(env, "enumerable", FieldMember.of(BoolValue.of(enumerable)));
|
res.defineOwnMember(env, "enumerable", FieldMember.of(BoolValue.of(enumerable)));
|
||||||
|
@ -10,11 +10,12 @@ import java.util.LinkedHashMap;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import me.topchetoeu.jscript.common.Operation;
|
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.JSON;
|
||||||
import me.topchetoeu.jscript.common.json.JSONElement;
|
import me.topchetoeu.jscript.common.json.JSONElement;
|
||||||
import me.topchetoeu.jscript.runtime.EventLoop;
|
import me.topchetoeu.jscript.runtime.EventLoop;
|
||||||
import me.topchetoeu.jscript.runtime.debug.DebugContext;
|
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.EngineException;
|
||||||
import me.topchetoeu.jscript.runtime.exceptions.SyntaxException;
|
import me.topchetoeu.jscript.runtime.exceptions.SyntaxException;
|
||||||
import me.topchetoeu.jscript.runtime.values.Member.FieldMember;
|
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 Key<FunctionValue> REGEX_CONSTR = Key.of();
|
||||||
public static final Object NO_RETURN = new Object();
|
|
||||||
|
public static final Key<Integer> MAX_STACK_COUNT = Key.of();
|
||||||
|
public static final Key<Boolean> HIDE_STACK = Key.of();
|
||||||
|
public static final Key<ObjectValue> OBJECT_PROTO = Key.of();
|
||||||
|
public static final Key<ObjectValue> FUNCTION_PROTO = Key.of();
|
||||||
|
public static final Key<ObjectValue> ARRAY_PROTO = Key.of();
|
||||||
|
public static final Key<ObjectValue> BOOL_PROTO = Key.of();
|
||||||
|
public static final Key<ObjectValue> NUMBER_PROTO = Key.of();
|
||||||
|
public static final Key<ObjectValue> STRING_PROTO = Key.of();
|
||||||
|
public static final Key<ObjectValue> SYMBOL_PROTO = Key.of();
|
||||||
|
public static final Key<ObjectValue> ERROR_PROTO = Key.of();
|
||||||
|
public static final Key<ObjectValue> SYNTAX_ERR_PROTO = Key.of();
|
||||||
|
public static final Key<ObjectValue> TYPE_ERR_PROTO = Key.of();
|
||||||
|
public static final Key<ObjectValue> 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 StringValue type();
|
||||||
public abstract boolean isPrimitive();
|
public abstract boolean isPrimitive();
|
||||||
@ -267,7 +284,7 @@ public abstract class Value {
|
|||||||
if (member != null) return member.get(env, obj);
|
if (member != null) return member.get(env, obj);
|
||||||
}
|
}
|
||||||
|
|
||||||
return VoidValue.UNDEFINED;
|
return Value.UNDEFINED;
|
||||||
}
|
}
|
||||||
public final Value getMember(Environment env, Value key) {
|
public final Value getMember(Environment env, Value key) {
|
||||||
return getMember(env, new KeyCache(key));
|
return getMember(env, new KeyCache(key));
|
||||||
@ -437,74 +454,6 @@ public abstract class Value {
|
|||||||
return a.toString(env).strictEquals(env, b.toString(env));
|
return a.toString(env).strictEquals(env, b.toString(env));
|
||||||
}
|
}
|
||||||
|
|
||||||
// @SuppressWarnings("unchecked")
|
|
||||||
// public static <T> T convert(Environment ext, Class<T> 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<Object> toIterable(Environment env) {
|
public Iterable<Object> toIterable(Environment env) {
|
||||||
return () -> {
|
return () -> {
|
||||||
if (!(this instanceof FunctionValue)) return Collections.emptyIterator();
|
if (!(this instanceof FunctionValue)) return Collections.emptyIterator();
|
||||||
@ -518,7 +467,7 @@ public abstract class Value {
|
|||||||
private void loadNext() {
|
private void loadNext() {
|
||||||
if (supplier == null) value = null;
|
if (supplier == null) value = null;
|
||||||
else if (consumed) {
|
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 == null) { supplier = null; value = null; }
|
||||||
if (curr.getMember(env, new StringValue("done")).toBoolean()) { 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<? extends Value> it) {
|
public void callWith(Environment env, Iterable<? extends Value> it) {
|
||||||
for (var el : it) {
|
for (var el : it) {
|
||||||
this.call(env, VoidValue.UNDEFINED, el);
|
this.call(env, Value.UNDEFINED, el);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public void callWithAsync(Environment env, Iterable<? extends Value> it, boolean async) {
|
public void callWithAsync(Environment env, Iterable<? extends Value> it, boolean async) {
|
||||||
for (var el : it) {
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
package me.topchetoeu.jscript.runtime.values.functions;
|
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.Value;
|
||||||
import me.topchetoeu.jscript.runtime.values.primitives.VoidValue;
|
|
||||||
|
|
||||||
public class Arguments {
|
public class Arguments {
|
||||||
public final Value self;
|
public final Value self;
|
||||||
@ -23,7 +22,7 @@ public class Arguments {
|
|||||||
return get(-1);
|
return get(-1);
|
||||||
}
|
}
|
||||||
public Value get(int i) {
|
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 if (i == -1) return self;
|
||||||
else return args[i];
|
else return args[i];
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,8 @@
|
|||||||
package me.topchetoeu.jscript.runtime.values.functions;
|
package me.topchetoeu.jscript.runtime.values.functions;
|
||||||
|
|
||||||
import me.topchetoeu.jscript.common.FunctionBody;
|
import me.topchetoeu.jscript.common.FunctionBody;
|
||||||
|
import me.topchetoeu.jscript.common.environment.Environment;
|
||||||
import me.topchetoeu.jscript.runtime.Frame;
|
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.scope.ValueVariable;
|
||||||
import me.topchetoeu.jscript.runtime.values.Value;
|
import me.topchetoeu.jscript.runtime.values.Value;
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
package me.topchetoeu.jscript.runtime.values.functions;
|
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.KeyCache;
|
||||||
import me.topchetoeu.jscript.runtime.values.Member;
|
import me.topchetoeu.jscript.runtime.values.Member;
|
||||||
import me.topchetoeu.jscript.runtime.values.Value;
|
import me.topchetoeu.jscript.runtime.values.Value;
|
||||||
@ -82,7 +82,7 @@ public abstract class FunctionValue extends ObjectValue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public FunctionValue(String name, int length) {
|
public FunctionValue(String name, int length) {
|
||||||
setPrototype(Environment.FUNCTION_PROTO);
|
setPrototype(FUNCTION_PROTO);
|
||||||
|
|
||||||
if (name == null) name = "";
|
if (name == null) name = "";
|
||||||
this.length = length;
|
this.length = length;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
package me.topchetoeu.jscript.runtime.values.functions;
|
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.Value;
|
||||||
|
|
||||||
public class NativeFunction extends FunctionValue {
|
public class NativeFunction extends FunctionValue {
|
||||||
|
@ -7,7 +7,7 @@ import java.util.Iterator;
|
|||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.Map;
|
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.KeyCache;
|
||||||
import me.topchetoeu.jscript.runtime.values.Member;
|
import me.topchetoeu.jscript.runtime.values.Member;
|
||||||
import me.topchetoeu.jscript.runtime.values.Member.FieldMember;
|
import me.topchetoeu.jscript.runtime.values.Member.FieldMember;
|
||||||
@ -73,7 +73,7 @@ public class ArrayValue extends ObjectValue implements Iterable<Value> {
|
|||||||
if (i < 0 || i >= size) return null;
|
if (i < 0 || i >= size) return null;
|
||||||
var res = values[i];
|
var res = values[i];
|
||||||
|
|
||||||
if (res == null) return VoidValue.UNDEFINED;
|
if (res == null) return Value.UNDEFINED;
|
||||||
else return res;
|
else return res;
|
||||||
}
|
}
|
||||||
public void set(int i, Value val) {
|
public void set(int i, Value val) {
|
||||||
@ -217,7 +217,7 @@ public class ArrayValue extends ObjectValue implements Iterable<Value> {
|
|||||||
this(16);
|
this(16);
|
||||||
}
|
}
|
||||||
public ArrayValue(int cap) {
|
public ArrayValue(int cap) {
|
||||||
setPrototype(env -> env.get(Environment.ARRAY_PROTO));
|
setPrototype(env -> env.get(ARRAY_PROTO));
|
||||||
values = new Value[Math.min(cap, 16)];
|
values = new Value[Math.min(cap, 16)];
|
||||||
size = 0;
|
size = 0;
|
||||||
}
|
}
|
||||||
|
@ -4,8 +4,8 @@ import java.util.Collections;
|
|||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import me.topchetoeu.jscript.runtime.environment.Environment;
|
import me.topchetoeu.jscript.common.environment.Environment;
|
||||||
import me.topchetoeu.jscript.runtime.environment.Key;
|
import me.topchetoeu.jscript.common.environment.Key;
|
||||||
import me.topchetoeu.jscript.runtime.exceptions.EngineException;
|
import me.topchetoeu.jscript.runtime.exceptions.EngineException;
|
||||||
import me.topchetoeu.jscript.runtime.values.KeyCache;
|
import me.topchetoeu.jscript.runtime.values.KeyCache;
|
||||||
import me.topchetoeu.jscript.runtime.values.Member;
|
import me.topchetoeu.jscript.runtime.values.Member;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
package me.topchetoeu.jscript.runtime.values.objects;
|
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.scope.ValueVariable;
|
||||||
import me.topchetoeu.jscript.runtime.values.Value;
|
import me.topchetoeu.jscript.runtime.values.Value;
|
||||||
import me.topchetoeu.jscript.runtime.values.Member.FieldMember;
|
import me.topchetoeu.jscript.runtime.values.Member.FieldMember;
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
package me.topchetoeu.jscript.runtime.values.primitives;
|
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.Value;
|
||||||
import me.topchetoeu.jscript.runtime.values.objects.ObjectValue;
|
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 StringValue toString(Environment ext) { return new StringValue(value ? "true" : "false"); }
|
||||||
|
|
||||||
@Override public ObjectValue getPrototype(Environment env) {
|
@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) {
|
@Override public boolean strictEquals(Environment ext, Value other) {
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
package me.topchetoeu.jscript.runtime.values.primitives;
|
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.JSON;
|
||||||
import me.topchetoeu.jscript.common.json.JSONElement;
|
import me.topchetoeu.jscript.common.json.JSONElement;
|
||||||
import me.topchetoeu.jscript.common.parsing.Parsing;
|
import me.topchetoeu.jscript.common.parsing.Parsing;
|
||||||
import me.topchetoeu.jscript.common.parsing.Source;
|
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.Value;
|
||||||
import me.topchetoeu.jscript.runtime.values.objects.ObjectValue;
|
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 String toString() { return JSON.stringify(JSONElement.number(value)); }
|
||||||
|
|
||||||
@Override public ObjectValue getPrototype(Environment env) {
|
@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) {
|
@Override public CompareResult compare(Environment env, Value other) {
|
||||||
|
@ -2,7 +2,7 @@ package me.topchetoeu.jscript.runtime.values.primitives;
|
|||||||
|
|
||||||
import java.util.Map;
|
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.KeyCache;
|
||||||
import me.topchetoeu.jscript.runtime.values.Member;
|
import me.topchetoeu.jscript.runtime.values.Member;
|
||||||
import me.topchetoeu.jscript.runtime.values.Value;
|
import me.topchetoeu.jscript.runtime.values.Value;
|
||||||
|
@ -3,9 +3,9 @@ package me.topchetoeu.jscript.runtime.values.primitives;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
|
import me.topchetoeu.jscript.common.environment.Environment;
|
||||||
import me.topchetoeu.jscript.common.parsing.Parsing;
|
import me.topchetoeu.jscript.common.parsing.Parsing;
|
||||||
import me.topchetoeu.jscript.common.parsing.Source;
|
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.Member;
|
||||||
import me.topchetoeu.jscript.runtime.values.Value;
|
import me.topchetoeu.jscript.runtime.values.Value;
|
||||||
import me.topchetoeu.jscript.runtime.values.objects.ObjectValue;
|
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) {
|
@Override public boolean strictEquals(Environment ext, Value other) {
|
||||||
return (other instanceof StringValue) && Objects.equals(((StringValue)other).value, value);
|
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<String, Member> getOwnMembers(Environment env) {
|
@Override public Map<String, Member> getOwnMembers(Environment env) {
|
||||||
// TODO Auto-generated method stub
|
// TODO Auto-generated method stub
|
||||||
|
@ -2,7 +2,7 @@ package me.topchetoeu.jscript.runtime.values.primitives;
|
|||||||
|
|
||||||
import java.util.HashMap;
|
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.exceptions.EngineException;
|
||||||
import me.topchetoeu.jscript.runtime.values.Value;
|
import me.topchetoeu.jscript.runtime.values.Value;
|
||||||
import me.topchetoeu.jscript.runtime.values.objects.ObjectValue;
|
import me.topchetoeu.jscript.runtime.values.objects.ObjectValue;
|
||||||
@ -14,7 +14,7 @@ public final class SymbolValue extends PrimitiveValue {
|
|||||||
public final String value;
|
public final String value;
|
||||||
|
|
||||||
public Value key() {
|
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; }
|
@Override public StringValue type() { return typeString; }
|
||||||
@ -30,7 +30,7 @@ public final class SymbolValue extends PrimitiveValue {
|
|||||||
@Override public boolean strictEquals(Environment ext, Value other) {
|
@Override public boolean strictEquals(Environment ext, Value other) {
|
||||||
return other == this;
|
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() {
|
@Override public String toString() {
|
||||||
if (value == null) return "Symbol()";
|
if (value == null) return "Symbol()";
|
||||||
|
@ -2,7 +2,7 @@ package me.topchetoeu.jscript.runtime.values.primitives;
|
|||||||
|
|
||||||
import java.util.Map;
|
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.exceptions.EngineException;
|
||||||
import me.topchetoeu.jscript.runtime.values.KeyCache;
|
import me.topchetoeu.jscript.runtime.values.KeyCache;
|
||||||
import me.topchetoeu.jscript.runtime.values.Member;
|
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;
|
import me.topchetoeu.jscript.runtime.values.objects.ObjectValue;
|
||||||
|
|
||||||
public final class VoidValue extends PrimitiveValue {
|
public final class VoidValue extends PrimitiveValue {
|
||||||
public static final VoidValue UNDEFINED = new VoidValue("undefined", new StringValue("undefined"));
|
private final StringValue nameString;
|
||||||
public static final VoidValue NULL = new VoidValue("null", new StringValue("object"));
|
|
||||||
|
|
||||||
private final StringValue namestring;
|
|
||||||
|
|
||||||
public final String name;
|
public final String name;
|
||||||
public final StringValue typeString;
|
public final StringValue typeString;
|
||||||
@ -21,12 +18,12 @@ public final class VoidValue extends PrimitiveValue {
|
|||||||
@Override public StringValue type() { return typeString; }
|
@Override public StringValue type() { return typeString; }
|
||||||
@Override public boolean toBoolean() { return false; }
|
@Override public boolean toBoolean() { return false; }
|
||||||
@Override public NumberValue toNumber(Environment ext) { return NumberValue.NAN; }
|
@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) {
|
@Override public Value add(Environment ext, Value other) {
|
||||||
if (!other.isPrimitive()) other = other.toPrimitive(ext);
|
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;
|
else return NumberValue.NAN;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -52,6 +49,6 @@ public final class VoidValue extends PrimitiveValue {
|
|||||||
public VoidValue(String name, StringValue type) {
|
public VoidValue(String name, StringValue type) {
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.typeString = type;
|
this.typeString = type;
|
||||||
this.namestring = new StringValue(name);
|
this.nameString = new StringValue(name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user