ES6 Support Groundwork + Fixes #26

Merged
TopchetoEU merged 49 commits from ES6 into master 2024-09-05 14:26:07 +00:00
34 changed files with 886 additions and 310 deletions
Showing only changes of commit 62aba62a41 - Show all commits

319
src/assets/lib/index.js Normal file
View 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]);

View File

@ -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);

View File

@ -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();
}
}

View File

@ -0,0 +1,7 @@
package me.topchetoeu.jscript.common.environment;
public interface Key<T> {
public static <T> Key<T> of() {
return new Key<>() { };
}
}

View File

@ -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);
}

View File

@ -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);

View File

@ -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;

View File

@ -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.");

View File

@ -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) {

View File

@ -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 {

View File

@ -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;

View File

@ -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 {

View File

@ -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();
}
}

View File

@ -1,5 +0,0 @@
package me.topchetoeu.jscript.runtime.environment;
public class Key<T> {
}

View File

@ -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)));
} }
} }

View File

@ -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);

View File

@ -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 {

View File

@ -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;

View File

@ -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;

View File

@ -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)));

View File

@ -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);
} }
} }

View File

@ -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];
} }

View File

@ -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;

View File

@ -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;

View File

@ -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 {

View File

@ -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;
} }

View File

@ -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;

View File

@ -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;

View File

@ -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) {

View File

@ -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) {

View File

@ -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;

View File

@ -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

View File

@ -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()";

View File

@ -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);
} }
} }