refactor: make Value interface (again?)

This commit is contained in:
TopchetoEU 2025-01-24 23:04:05 +02:00
parent 1670b64aaf
commit e601749866
Signed by: topchetoeu
GPG Key ID: 6531B8583E5F6ED4
12 changed files with 138 additions and 140 deletions

View File

@ -20,7 +20,7 @@ import me.topchetoeu.j2s.runtime.values.primitives.StringValue;
import me.topchetoeu.j2s.runtime.values.primitives.SymbolValue; import me.topchetoeu.j2s.runtime.values.primitives.SymbolValue;
import me.topchetoeu.j2s.runtime.values.primitives.numbers.NumberValue; import me.topchetoeu.j2s.runtime.values.primitives.numbers.NumberValue;
public class ScopeObject extends Value { public class ScopeObject implements Value {
public static final class ScopeMember extends FieldMember { public static final class ScopeMember extends FieldMember {
public final Frame frame; public final Frame frame;
public final int i; public final int i;

View File

@ -29,7 +29,7 @@ import me.topchetoeu.j2s.runtime.values.primitives.SymbolValue;
import me.topchetoeu.j2s.runtime.values.primitives.VoidValue; import me.topchetoeu.j2s.runtime.values.primitives.VoidValue;
import me.topchetoeu.j2s.runtime.values.primitives.numbers.NumberValue; import me.topchetoeu.j2s.runtime.values.primitives.numbers.NumberValue;
public abstract class Value { public interface Value {
public static enum State { public static enum State {
NORMAL(true, true, true), NORMAL(true, true, true),
NON_EXTENDABLE(false, true, true), NON_EXTENDABLE(false, true, true),
@ -76,28 +76,43 @@ public abstract class Value {
public abstract StringValue type(); public abstract StringValue type();
public abstract boolean isPrimitive(); public abstract boolean isPrimitive();
public final boolean isNaN() { public default boolean isNaN() {
return this == NumberValue.NAN || this instanceof NumberValue num && Double.isNaN(num.getDouble()); return this == NumberValue.NAN || this instanceof NumberValue num && Double.isNaN(num.getDouble());
} }
public Value apply(Environment env, Value self, Value ...args) { public default Value apply(Environment env, Value self, Value ...args) {
throw EngineException.ofType("Value is not a function"); throw EngineException.ofType("Value is not a function");
} }
public Value construct(Environment env, Value target, Value ...args) { public default Value construct(Environment env, Value target, Value ...args) {
throw EngineException.ofType("Value is not a constructor"); throw EngineException.ofType("Value is not a constructor");
} }
public final Value constructNoSelf(Environment env, Value ...args) { public default Value constructNoSelf(Environment env, Value ...args) {
return this.construct(env, this, args); return this.construct(env, this, args);
} }
public Value toPrimitive(Environment env);
public NumberValue toNumber(Environment env);
public String toString(Environment env);
public boolean toBoolean();
public abstract Value toPrimitive(Environment env); public Member getOwnMember(Environment env, KeyCache key);
public abstract NumberValue toNumber(Environment env); public Set<String> getOwnMembers(Environment env, boolean onlyEnumerable);
public abstract String toString(Environment env); public Set<SymbolValue> getOwnSymbolMembers(Environment env, boolean onlyEnumerable);
public abstract boolean toBoolean(); public boolean defineOwnField(Environment env, KeyCache key, Value val, Boolean writable, Boolean enumerable, Boolean configurable);
public boolean defineOwnProperty(Environment env, KeyCache key, Optional<FunctionValue> get, Optional<FunctionValue> set, Boolean enumerable, Boolean configurable);
public boolean deleteOwnMember(Environment env, KeyCache key);
public final boolean isInstanceOf(Environment env, Value proto) { public ObjectValue getPrototype(Environment env);
public boolean setPrototype(Environment env, ObjectValue val);
public State getState();
public void preventExtensions();
public void seal();
public void freeze();
public default boolean isInstanceOf(Environment env, Value proto) {
for (var val = getPrototype(env); val != null; val = val.getPrototype(env)) { for (var val = getPrototype(env); val != null; val = val.getPrototype(env)) {
if (val.equals(proto)) return true; if (val.equals(proto)) return true;
} }
@ -105,91 +120,75 @@ public abstract class Value {
return false; return false;
} }
public abstract Member getOwnMember(Environment env, KeyCache key); public default Member getOwnMember(Environment env, Value key) {
public abstract Set<String> getOwnMembers(Environment env, boolean onlyEnumerable);
public abstract Set<SymbolValue> getOwnSymbolMembers(Environment env, boolean onlyEnumerable);
public abstract boolean defineOwnField(Environment env, KeyCache key, Value val, Boolean writable, Boolean enumerable, Boolean configurable);
public abstract boolean defineOwnProperty(Environment env, KeyCache key, Optional<FunctionValue> get, Optional<FunctionValue> set, Boolean enumerable, Boolean configurable);
public abstract boolean deleteOwnMember(Environment env, KeyCache key);
public abstract ObjectValue getPrototype(Environment env);
public abstract boolean setPrototype(Environment env, ObjectValue val);
public abstract State getState();
public abstract void preventExtensions();
public abstract void seal();
public abstract void freeze();
public final Member getOwnMember(Environment env, Value key) {
return getOwnMember(env, new KeyCache(key)); return getOwnMember(env, new KeyCache(key));
} }
public final Member getOwnMember(Environment env, String key) { public default Member getOwnMember(Environment env, String key) {
return getOwnMember(env, new KeyCache(key)); return getOwnMember(env, new KeyCache(key));
} }
public final Member getOwnMember(Environment env, int key) { public default Member getOwnMember(Environment env, int key) {
return getOwnMember(env, new KeyCache(key)); return getOwnMember(env, new KeyCache(key));
} }
public final Member getOwnMember(Environment env, double key) { public default Member getOwnMember(Environment env, double key) {
return getOwnMember(env, new KeyCache(key)); return getOwnMember(env, new KeyCache(key));
} }
public final boolean defineOwnProperty(Environment env, Value key, Optional<FunctionValue> get, Optional<FunctionValue> set, Boolean enumerable, Boolean configurable) { public default boolean defineOwnProperty(Environment env, Value key, Optional<FunctionValue> get, Optional<FunctionValue> set, Boolean enumerable, Boolean configurable) {
return defineOwnProperty(env, new KeyCache(key), get, set, enumerable, configurable); return defineOwnProperty(env, new KeyCache(key), get, set, enumerable, configurable);
} }
public final boolean defineOwnProperty(Environment env, String key, Optional<FunctionValue> get, Optional<FunctionValue> set, Boolean enumerable, Boolean configurable) { public default boolean defineOwnProperty(Environment env, String key, Optional<FunctionValue> get, Optional<FunctionValue> set, Boolean enumerable, Boolean configurable) {
return defineOwnProperty(env, new KeyCache(key), get, set, enumerable, configurable); return defineOwnProperty(env, new KeyCache(key), get, set, enumerable, configurable);
} }
public final boolean defineOwnProperty(Environment env, int key, Optional<FunctionValue> get, Optional<FunctionValue> set, Boolean enumerable, Boolean configurable) { public default boolean defineOwnProperty(Environment env, int key, Optional<FunctionValue> get, Optional<FunctionValue> set, Boolean enumerable, Boolean configurable) {
return defineOwnProperty(env, new KeyCache(key), get, set, enumerable, configurable); return defineOwnProperty(env, new KeyCache(key), get, set, enumerable, configurable);
} }
public final boolean defineOwnProperty(Environment env, double key, Optional<FunctionValue> get, Optional<FunctionValue> set, Boolean enumerable, Boolean configurable) { public default boolean defineOwnProperty(Environment env, double key, Optional<FunctionValue> get, Optional<FunctionValue> set, Boolean enumerable, Boolean configurable) {
return defineOwnProperty(env, new KeyCache(key), get, set, enumerable, configurable); return defineOwnProperty(env, new KeyCache(key), get, set, enumerable, configurable);
} }
public final boolean defineOwnField(Environment env, Value key, Value val, Boolean writable, Boolean enumerable, Boolean configurable) { public default boolean defineOwnField(Environment env, Value key, Value val, Boolean writable, Boolean enumerable, Boolean configurable) {
return defineOwnField(env, new KeyCache(key), val, writable, enumerable, configurable); return defineOwnField(env, new KeyCache(key), val, writable, enumerable, configurable);
} }
public final boolean defineOwnField(Environment env, String key, Value val, Boolean writable, Boolean enumerable, Boolean configurable) { public default boolean defineOwnField(Environment env, String key, Value val, Boolean writable, Boolean enumerable, Boolean configurable) {
return defineOwnField(env, new KeyCache(key), val, writable, enumerable, configurable); return defineOwnField(env, new KeyCache(key), val, writable, enumerable, configurable);
} }
public final boolean defineOwnField(Environment env, int key, Value val, Boolean writable, Boolean enumerable, Boolean configurable) { public default boolean defineOwnField(Environment env, int key, Value val, Boolean writable, Boolean enumerable, Boolean configurable) {
return defineOwnField(env, new KeyCache(key), val, writable, enumerable, configurable); return defineOwnField(env, new KeyCache(key), val, writable, enumerable, configurable);
} }
public final boolean defineOwnField(Environment env, double key, Value val, Boolean writable, Boolean enumerable, Boolean configurable) { public default boolean defineOwnField(Environment env, double key, Value val, Boolean writable, Boolean enumerable, Boolean configurable) {
return defineOwnField(env, new KeyCache(key), val, writable, enumerable, configurable); return defineOwnField(env, new KeyCache(key), val, writable, enumerable, configurable);
} }
public final boolean defineOwnField(Environment env, KeyCache key, Value val) { public default boolean defineOwnField(Environment env, KeyCache key, Value val) {
return defineOwnField(env, key, val, true, true, true); return defineOwnField(env, key, val, true, true, true);
} }
public final boolean defineOwnField(Environment env, Value key, Value val) { public default boolean defineOwnField(Environment env, Value key, Value val) {
return defineOwnField(env, new KeyCache(key), val); return defineOwnField(env, new KeyCache(key), val);
} }
public final boolean defineOwnField(Environment env, String key, Value val) { public default boolean defineOwnField(Environment env, String key, Value val) {
return defineOwnField(env, new KeyCache(key), val); return defineOwnField(env, new KeyCache(key), val);
} }
public final boolean defineOwnField(Environment env, int key, Value val) { public default boolean defineOwnField(Environment env, int key, Value val) {
return defineOwnField(env, new KeyCache(key), val); return defineOwnField(env, new KeyCache(key), val);
} }
public final boolean defineOwnField(Environment env, double key, Value val) { public default boolean defineOwnField(Environment env, double key, Value val) {
return defineOwnField(env, new KeyCache(key), val); return defineOwnField(env, new KeyCache(key), val);
} }
public final boolean deleteOwnMember(Environment env, Value key) { public default boolean deleteOwnMember(Environment env, Value key) {
return deleteOwnMember(env, new KeyCache(key)); return deleteOwnMember(env, new KeyCache(key));
} }
public final boolean deleteOwnMember(Environment env, String key) { public default boolean deleteOwnMember(Environment env, String key) {
return deleteOwnMember(env, new KeyCache(key)); return deleteOwnMember(env, new KeyCache(key));
} }
public final boolean deleteOwnMember(Environment env, int key) { public default boolean deleteOwnMember(Environment env, int key) {
return deleteOwnMember(env, new KeyCache(key)); return deleteOwnMember(env, new KeyCache(key));
} }
public final boolean deleteOwnMember(Environment env, double key) { public default boolean deleteOwnMember(Environment env, double key) {
return deleteOwnMember(env, new KeyCache(key)); return deleteOwnMember(env, new KeyCache(key));
} }
public final Value getMemberOrNull(Environment env, KeyCache key) { public default Value getMemberOrNull(Environment env, KeyCache key) {
for (Value obj = this; obj != null; obj = obj.getPrototype(env)) { for (Value obj = this; obj != null; obj = obj.getPrototype(env)) {
var member = obj.getOwnMember(env, key); var member = obj.getOwnMember(env, key);
if (member != null) return member.get(env, this); if (member != null) return member.get(env, this);
@ -197,38 +196,38 @@ public abstract class Value {
return null; return null;
} }
public final Value getMemberOrNull(Environment env, Value key) { public default Value getMemberOrNull(Environment env, Value key) {
return getMemberOrNull(env, new KeyCache(key)); return getMemberOrNull(env, new KeyCache(key));
} }
public final Value getMemberOrNull(Environment env, String key) { public default Value getMemberOrNull(Environment env, String key) {
return getMemberOrNull(env, new KeyCache(key)); return getMemberOrNull(env, new KeyCache(key));
} }
public final Value getMemberOrNull(Environment env, int key) { public default Value getMemberOrNull(Environment env, int key) {
return getMemberOrNull(env, new KeyCache(key)); return getMemberOrNull(env, new KeyCache(key));
} }
public final Value getMemberOrNull(Environment env, double key) { public default Value getMemberOrNull(Environment env, double key) {
return getMemberOrNull(env, new KeyCache(key)); return getMemberOrNull(env, new KeyCache(key));
} }
public final Value getMember(Environment env, KeyCache key) { public default Value getMember(Environment env, KeyCache key) {
var res = getMemberOrNull(env, key); var res = getMemberOrNull(env, key);
if (res != null) return res; if (res != null) return res;
else return Value.UNDEFINED; else return Value.UNDEFINED;
} }
public final Value getMember(Environment env, Value key) { public default Value getMember(Environment env, Value key) {
return getMember(env, new KeyCache(key)); return getMember(env, new KeyCache(key));
} }
public final Value getMember(Environment env, String key) { public default Value getMember(Environment env, String key) {
return getMember(env, new KeyCache(key)); return getMember(env, new KeyCache(key));
} }
public final Value getMember(Environment env, int key) { public default Value getMember(Environment env, int key) {
return getMember(env, new KeyCache(key)); return getMember(env, new KeyCache(key));
} }
public final Value getMember(Environment env, double key) { public default Value getMember(Environment env, double key) {
return getMember(env, new KeyCache(key)); return getMember(env, new KeyCache(key));
} }
public final boolean setMember(Environment env, KeyCache key, Value val) { public default boolean setMember(Environment env, KeyCache key, Value val) {
for (Value obj = this; obj != null; obj = obj.getPrototype(env)) { for (Value obj = this; obj != null; obj = obj.getPrototype(env)) {
var member = obj.getOwnMember(env, key); var member = obj.getOwnMember(env, key);
if (member != null && (member instanceof PropertyMember || obj == this)) { if (member != null && (member instanceof PropertyMember || obj == this)) {
@ -249,20 +248,20 @@ public abstract class Value {
} }
else return false; else return false;
} }
public final boolean setMember(Environment env, Value key, Value val) { public default boolean setMember(Environment env, Value key, Value val) {
return setMember(env, new KeyCache(key), val); return setMember(env, new KeyCache(key), val);
} }
public final boolean setMember(Environment env, String key, Value val) { public default boolean setMember(Environment env, String key, Value val) {
return setMember(env, new KeyCache(key), val); return setMember(env, new KeyCache(key), val);
} }
public final boolean setMember(Environment env, int key, Value val) { public default boolean setMember(Environment env, int key, Value val) {
return setMember(env, new KeyCache(key), val); return setMember(env, new KeyCache(key), val);
} }
public final boolean setMember(Environment env, double key, Value val) { public default boolean setMember(Environment env, double key, Value val) {
return setMember(env, new KeyCache(key), val); return setMember(env, new KeyCache(key), val);
} }
public final boolean setMemberIfExists(Environment env, KeyCache key, Value val) { public default boolean setMemberIfExists(Environment env, KeyCache key, Value val) {
for (Value obj = this; obj != null; obj = obj.getPrototype(env)) { for (Value obj = this; obj != null; obj = obj.getPrototype(env)) {
var member = obj.getOwnMember(env, key); var member = obj.getOwnMember(env, key);
if (member != null) { if (member != null) {
@ -276,20 +275,20 @@ public abstract class Value {
return false; return false;
} }
public final boolean setMemberIfExists(Environment env, Value key, Value val) { public default boolean setMemberIfExists(Environment env, Value key, Value val) {
return setMemberIfExists(env, new KeyCache(key), val); return setMemberIfExists(env, new KeyCache(key), val);
} }
public final boolean setMemberIfExists(Environment env, String key, Value val) { public default boolean setMemberIfExists(Environment env, String key, Value val) {
return setMemberIfExists(env, new KeyCache(key), val); return setMemberIfExists(env, new KeyCache(key), val);
} }
public final boolean setMemberIfExists(Environment env, int key, Value val) { public default boolean setMemberIfExists(Environment env, int key, Value val) {
return setMemberIfExists(env, new KeyCache(key), val); return setMemberIfExists(env, new KeyCache(key), val);
} }
public final boolean setMemberIfExists(Environment env, double key, Value val) { public default boolean setMemberIfExists(Environment env, double key, Value val) {
return setMemberIfExists(env, new KeyCache(key), val); return setMemberIfExists(env, new KeyCache(key), val);
} }
public final boolean hasMember(Environment env, KeyCache key, boolean own) { public default boolean hasMember(Environment env, KeyCache key, boolean own) {
for (Value obj = this; obj != null; obj = obj.getPrototype(env)) { for (Value obj = this; obj != null; obj = obj.getPrototype(env)) {
if (obj.getOwnMember(env, key) != null) return true; if (obj.getOwnMember(env, key) != null) return true;
if (own) return false; if (own) return false;
@ -297,37 +296,37 @@ public abstract class Value {
return false; return false;
} }
public final boolean hasMember(Environment env, Value key, boolean own) { public default boolean hasMember(Environment env, Value key, boolean own) {
return hasMember(env, new KeyCache(key), own); return hasMember(env, new KeyCache(key), own);
} }
public final boolean hasMember(Environment env, String key, boolean own) { public default boolean hasMember(Environment env, String key, boolean own) {
return hasMember(env, new KeyCache(key), own); return hasMember(env, new KeyCache(key), own);
} }
public final boolean hasMember(Environment env, int key, boolean own) { public default boolean hasMember(Environment env, int key, boolean own) {
return hasMember(env, new KeyCache(key), own); return hasMember(env, new KeyCache(key), own);
} }
public final boolean hasMember(Environment env, double key, boolean own) { public default boolean hasMember(Environment env, double key, boolean own) {
return hasMember(env, new KeyCache(key), own); return hasMember(env, new KeyCache(key), own);
} }
public final boolean deleteMember(Environment env, KeyCache key) { public default boolean deleteMember(Environment env, KeyCache key) {
if (!hasMember(env, key, true)) return true; if (!hasMember(env, key, true)) return true;
return deleteOwnMember(env, key); return deleteOwnMember(env, key);
} }
public final boolean deleteMember(Environment env, Value key) { public default boolean deleteMember(Environment env, Value key) {
return deleteMember(env, new KeyCache(key)); return deleteMember(env, new KeyCache(key));
} }
public final boolean deleteMember(Environment env, String key) { public default boolean deleteMember(Environment env, String key) {
return deleteMember(env, new KeyCache(key)); return deleteMember(env, new KeyCache(key));
} }
public final boolean deleteMember(Environment env, int key) { public default boolean deleteMember(Environment env, int key) {
return deleteMember(env, new KeyCache(key)); return deleteMember(env, new KeyCache(key));
} }
public final boolean deleteMember(Environment env, double key) { public default boolean deleteMember(Environment env, double key) {
return deleteMember(env, new KeyCache(key)); return deleteMember(env, new KeyCache(key));
} }
public final Set<String> getMembers(Environment env, boolean own, boolean onlyEnumerable) { public default Set<String> getMembers(Environment env, boolean own, boolean onlyEnumerable) {
var res = new LinkedHashSet<String>(); var res = new LinkedHashSet<String>();
var protos = new ArrayList<Value>(); var protos = new ArrayList<Value>();
@ -344,7 +343,7 @@ public abstract class Value {
return res; return res;
} }
public final Set<SymbolValue> getSymbolMembers(Environment env, boolean own, boolean onlyEnumerable) { public default Set<SymbolValue> getSymbolMembers(Environment env, boolean own, boolean onlyEnumerable) {
var res = new LinkedHashSet<SymbolValue>(); var res = new LinkedHashSet<SymbolValue>();
var protos = new ArrayList<Value>(); var protos = new ArrayList<Value>();
@ -362,24 +361,24 @@ public abstract class Value {
return res; return res;
} }
public final Value getMemberPath(Environment env, String ...path) { public default Value getMemberPath(Environment env, String ...path) {
var res = this; var res = this;
for (var key : path) res = res.getMember(env, key); for (var key : path) res = res.getMember(env, key);
return res; return res;
} }
public final Value getMemberPath(Environment env, Value ...path) { public default Value getMemberPath(Environment env, Value ...path) {
var res = this; var res = this;
for (var key : path) res = res.getMember(env, key); for (var key : path) res = res.getMember(env, key);
return res; return res;
} }
public final ObjectValue getMemberDescriptor(Environment env, Value key) { public default ObjectValue getMemberDescriptor(Environment env, Value key) {
var member = getOwnMember(env, new KeyCache(key)); var member = getOwnMember(env, new KeyCache(key));
if (member != null) return member.descriptor(env, this); if (member != null) return member.descriptor(env, this);
else return null; else return null;
} }
public Iterable<Object> toIterable(Environment env) { public default Iterable<Object> toIterable(Environment env) {
return () -> { return () -> {
if (!(this instanceof FunctionValue)) return Collections.emptyIterator(); if (!(this instanceof FunctionValue)) return Collections.emptyIterator();
var func = (FunctionValue)this; var func = (FunctionValue)this;
@ -418,29 +417,29 @@ public abstract class Value {
}; };
} }
public void callWith(Environment env, Iterable<? extends Value> it) { public default void callWith(Environment env, Iterable<? extends Value> it) {
for (var el : it) { for (var el : it) {
this.apply(env, Value.UNDEFINED, el); this.apply(env, Value.UNDEFINED, el);
} }
} }
public void callWithAsync(Environment env, Iterable<? extends Value> it, boolean async) { public default void callWithAsync(Environment env, Iterable<? extends Value> it, boolean async) {
for (var el : it) { for (var el : it) {
env.get(EventLoop.KEY).pushMsg(() -> this.apply(env, Value.UNDEFINED, el), true); env.get(EventLoop.KEY).pushMsg(() -> this.apply(env, Value.UNDEFINED, el), true);
} }
} }
public List<String> toReadableLines(Environment env, HashSet<ObjectValue> passed) { public default List<String> toReadableLines(Environment env, HashSet<ObjectValue> passed) {
return Arrays.asList(toString(env)); return Arrays.asList(toString(env));
} }
public final String toReadable(Environment ext) { public default String toReadable(Environment ext) {
return String.join("\n", toReadableLines(ext, new HashSet<>())); return String.join("\n", toReadableLines(ext, new HashSet<>()));
} }
public static final Value global(Environment env) { public static Value global(Environment env) {
return env.initFrom(GLOBAL, () -> new ObjectValue()); return env.initFrom(GLOBAL, () -> new ObjectValue());
} }
public static final Map<String, Value> intrinsics(Environment env) { public static Map<String, Value> intrinsics(Environment env) {
return env.initFrom(INTRINSICS, () -> new HashMap<>()); return env.initFrom(INTRINSICS, () -> new HashMap<>());
} }
@ -457,7 +456,7 @@ public abstract class Value {
}); });
} }
public static final boolean lessOrEqual(Environment env, Value a, Value b) { public static boolean lessOrEqual(Environment env, Value a, Value b) {
a = a.toPrimitive(env); a = a.toPrimitive(env);
b = b.toPrimitive(env); b = b.toPrimitive(env);
@ -472,7 +471,7 @@ public abstract class Value {
else return na.getDouble() <= nb.getDouble(); else return na.getDouble() <= nb.getDouble();
} }
} }
public static final boolean greaterOrEqual(Environment env, Value a, Value b) { public static boolean greaterOrEqual(Environment env, Value a, Value b) {
a = a.toPrimitive(env); a = a.toPrimitive(env);
b = b.toPrimitive(env); b = b.toPrimitive(env);
@ -487,7 +486,7 @@ public abstract class Value {
else return na.getDouble() >= nb.getDouble(); else return na.getDouble() >= nb.getDouble();
} }
} }
public static final boolean less(Environment env, Value a, Value b) { public static boolean less(Environment env, Value a, Value b) {
a = a.toPrimitive(env); a = a.toPrimitive(env);
b = b.toPrimitive(env); b = b.toPrimitive(env);
@ -502,7 +501,7 @@ public abstract class Value {
else return na.getDouble() < nb.getDouble(); else return na.getDouble() < nb.getDouble();
} }
} }
public static final boolean greater(Environment env, Value a, Value b) { public static boolean greater(Environment env, Value a, Value b) {
a = a.toPrimitive(env); a = a.toPrimitive(env);
b = b.toPrimitive(env); b = b.toPrimitive(env);
@ -518,7 +517,7 @@ public abstract class Value {
} }
} }
public static final Value add(Environment env, Value a, Value b) { public static Value add(Environment env, Value a, Value b) {
a = a.toPrimitive(env); a = a.toPrimitive(env);
b = b.toPrimitive(env); b = b.toPrimitive(env);
@ -534,21 +533,21 @@ public abstract class Value {
} }
} }
public static final NumberValue subtract(Environment env, Value a, Value b) { public static NumberValue subtract(Environment env, Value a, Value b) {
var na = a.toNumber(env); var na = a.toNumber(env);
var nb = b.toNumber(env); var nb = b.toNumber(env);
if (na.isInt() && nb.isInt()) return NumberValue.of(na.getInt() - nb.getInt()); if (na.isInt() && nb.isInt()) return NumberValue.of(na.getInt() - nb.getInt());
else return NumberValue.of(na.getDouble() - nb.getDouble()); else return NumberValue.of(na.getDouble() - nb.getDouble());
} }
public static final NumberValue multiply(Environment env, Value a, Value b) { public static NumberValue multiply(Environment env, Value a, Value b) {
var na = a.toNumber(env); var na = a.toNumber(env);
var nb = b.toNumber(env); var nb = b.toNumber(env);
if (na.isInt() && nb.isInt()) return NumberValue.of(na.getInt() * nb.getInt()); if (na.isInt() && nb.isInt()) return NumberValue.of(na.getInt() * nb.getInt());
else return NumberValue.of(na.getDouble() * nb.getDouble()); else return NumberValue.of(na.getDouble() * nb.getDouble());
} }
public static final NumberValue divide(Environment env, Value a, Value b) { public static NumberValue divide(Environment env, Value a, Value b) {
var na = a.toNumber(env); var na = a.toNumber(env);
var nb = b.toNumber(env); var nb = b.toNumber(env);
@ -566,7 +565,7 @@ public abstract class Value {
} }
else return NumberValue.of(na.getDouble() / nb.getDouble()); else return NumberValue.of(na.getDouble() / nb.getDouble());
} }
public static final NumberValue modulo(Environment env, Value a, Value b) { public static NumberValue modulo(Environment env, Value a, Value b) {
var na = a.toNumber(env); var na = a.toNumber(env);
var nb = b.toNumber(env); var nb = b.toNumber(env);
@ -579,33 +578,33 @@ public abstract class Value {
} }
else return NumberValue.of(na.getDouble() % nb.getDouble()); else return NumberValue.of(na.getDouble() % nb.getDouble());
} }
public static final NumberValue negative(Environment env, Value a) { public static NumberValue negative(Environment env, Value a) {
var na = a.toNumber(env); var na = a.toNumber(env);
if (na.isInt()) return NumberValue.of(-na.getInt()); if (na.isInt()) return NumberValue.of(-na.getInt());
else return NumberValue.of(-na.getDouble()); else return NumberValue.of(-na.getDouble());
} }
public static final NumberValue and(Environment env, Value a, Value b) { public static NumberValue and(Environment env, Value a, Value b) {
return NumberValue.of(a.toNumber(env).getInt() & b.toNumber(env).getInt()); return NumberValue.of(a.toNumber(env).getInt() & b.toNumber(env).getInt());
} }
public static final NumberValue or(Environment env, Value a, Value b) { public static NumberValue or(Environment env, Value a, Value b) {
return NumberValue.of(a.toNumber(env).getInt() | b.toNumber(env).getInt()); return NumberValue.of(a.toNumber(env).getInt() | b.toNumber(env).getInt());
} }
public static final NumberValue xor(Environment env, Value a, Value b) { public static NumberValue xor(Environment env, Value a, Value b) {
return NumberValue.of(a.toNumber(env).getInt() ^ b.toNumber(env).getInt()); return NumberValue.of(a.toNumber(env).getInt() ^ b.toNumber(env).getInt());
} }
public static final NumberValue bitwiseNot(Environment env, Value a) { public static NumberValue bitwiseNot(Environment env, Value a) {
return NumberValue.of(~a.toNumber(env).getInt()); return NumberValue.of(~a.toNumber(env).getInt());
} }
public static final NumberValue shiftLeft(Environment env, Value a, Value b) { public static NumberValue shiftLeft(Environment env, Value a, Value b) {
return NumberValue.of(a.toNumber(env).getInt() << b.toNumber(env).getInt()); return NumberValue.of(a.toNumber(env).getInt() << b.toNumber(env).getInt());
} }
public static final NumberValue shiftRight(Environment env, Value a, Value b) { public static NumberValue shiftRight(Environment env, Value a, Value b) {
return NumberValue.of(a.toNumber(env).getInt() >> b.toNumber(env).getInt()); return NumberValue.of(a.toNumber(env).getInt() >> b.toNumber(env).getInt());
} }
public static final NumberValue unsignedShiftRight(Environment env, Value a, Value b) { public static NumberValue unsignedShiftRight(Environment env, Value a, Value b) {
long _a = a.toNumber(env).getLong() & 0xFFFFFFFF; long _a = a.toNumber(env).getLong() & 0xFFFFFFFF;
long _b = b.toNumber(env).getLong() & 0xFFFFFFFF; long _b = b.toNumber(env).getLong() & 0xFFFFFFFF;
@ -615,7 +614,7 @@ public abstract class Value {
return NumberValue.of(_a >>> _b); return NumberValue.of(_a >>> _b);
} }
public static final boolean looseEqual(Environment env, Value a, Value b) { public static boolean looseEqual(Environment env, Value a, Value b) {
// In loose equality, null is equivalent to undefined // In loose equality, null is equivalent to undefined
if (a instanceof VoidValue || b instanceof VoidValue) return a instanceof VoidValue && b instanceof VoidValue; if (a instanceof VoidValue || b instanceof VoidValue) return a instanceof VoidValue && b instanceof VoidValue;
@ -637,7 +636,7 @@ public abstract class Value {
return a.toString(env).equals(b.toString(env)); return a.toString(env).equals(b.toString(env));
} }
public static final String errorToReadable(Environment env, RuntimeException err, String prefix) { public static String errorToReadable(Environment env, RuntimeException err, String prefix) {
prefix = prefix == null ? "Uncaught" : "Uncaught " + prefix; prefix = prefix == null ? "Uncaught" : "Uncaught " + prefix;
if (err instanceof EngineException ee) { if (err instanceof EngineException ee) {
if (env == null) env = ee.env; if (env == null) env = ee.env;

View File

@ -23,7 +23,7 @@ import me.topchetoeu.j2s.runtime.values.primitives.StringValue;
import me.topchetoeu.j2s.runtime.values.primitives.SymbolValue; import me.topchetoeu.j2s.runtime.values.primitives.SymbolValue;
import me.topchetoeu.j2s.runtime.values.primitives.numbers.NumberValue; import me.topchetoeu.j2s.runtime.values.primitives.numbers.NumberValue;
public class ObjectValue extends Value { public class ObjectValue implements Value {
public static interface PrototypeProvider { public static interface PrototypeProvider {
public ObjectValue get(Environment env); public ObjectValue get(Environment env);
} }

View File

@ -4,7 +4,7 @@ import me.topchetoeu.j2s.common.Environment;
import me.topchetoeu.j2s.runtime.values.objects.ObjectValue; import me.topchetoeu.j2s.runtime.values.objects.ObjectValue;
import me.topchetoeu.j2s.runtime.values.primitives.numbers.NumberValue; import me.topchetoeu.j2s.runtime.values.primitives.numbers.NumberValue;
public final class BoolValue extends PrimitiveValue { public final class BoolValue implements PrimitiveValue {
public static final BoolValue TRUE = new BoolValue(true); public static final BoolValue TRUE = new BoolValue(true);
public static final BoolValue FALSE = new BoolValue(false); public static final BoolValue FALSE = new BoolValue(false);

View File

@ -11,30 +11,29 @@ import me.topchetoeu.j2s.runtime.values.Value;
import me.topchetoeu.j2s.runtime.values.functions.FunctionValue; import me.topchetoeu.j2s.runtime.values.functions.FunctionValue;
import me.topchetoeu.j2s.runtime.values.objects.ObjectValue; import me.topchetoeu.j2s.runtime.values.objects.ObjectValue;
public abstract class PrimitiveValue extends Value { public interface PrimitiveValue extends Value {
@Override public boolean defineOwnField( public default boolean defineOwnField(
Environment env, KeyCache key, Value val, Environment env, KeyCache key, Value val,
Boolean writable, Boolean enumerable, Boolean configurable Boolean writable, Boolean enumerable, Boolean configurable
) { return false; } ) { return false; }
@Override public default boolean defineOwnProperty(
public boolean defineOwnProperty(
Environment env, KeyCache key, Optional<FunctionValue> get, Optional<FunctionValue> set, Environment env, KeyCache key, Optional<FunctionValue> get, Optional<FunctionValue> set,
Boolean enumerable, Boolean configurable Boolean enumerable, Boolean configurable
) { return false; } ) { return false; }
@Override public boolean deleteOwnMember(Environment env, KeyCache key) { return true; } public default boolean deleteOwnMember(Environment env, KeyCache key) { return true; }
@Override public final boolean isPrimitive() { return true; } public default boolean isPrimitive() { return true; }
@Override public final Value toPrimitive(Environment env) { return this; } public default Value toPrimitive(Environment env) { return this; }
@Override public final boolean setPrototype(Environment env, ObjectValue val) { return false; } public default boolean setPrototype(Environment env, ObjectValue val) { return false; }
@Override public Member getOwnMember(Environment env, KeyCache key) { return null; } public default Member getOwnMember(Environment env, KeyCache key) { return null; }
@Override public Set<String> getOwnMembers(Environment env, boolean onlyEnumerable) { return new HashSet<>(); } public default Set<String> getOwnMembers(Environment env, boolean onlyEnumerable) { return new HashSet<>(); }
@Override public Set<SymbolValue> getOwnSymbolMembers(Environment env, boolean onlyEnumerable) { return new HashSet<>(); } public default Set<SymbolValue> getOwnSymbolMembers(Environment env, boolean onlyEnumerable) { return new HashSet<>(); }
@Override public State getState() { return State.FROZEN; } public default State getState() { return State.FROZEN; }
@Override public void preventExtensions() {} public default void preventExtensions() {}
@Override public void seal() {} public default void seal() {}
@Override public void freeze() {} public default void freeze() {}
} }

View File

@ -15,7 +15,7 @@ import me.topchetoeu.j2s.runtime.values.Member.FieldMember;
import me.topchetoeu.j2s.runtime.values.objects.ObjectValue; import me.topchetoeu.j2s.runtime.values.objects.ObjectValue;
import me.topchetoeu.j2s.runtime.values.primitives.numbers.NumberValue; import me.topchetoeu.j2s.runtime.values.primitives.numbers.NumberValue;
public final class StringValue extends PrimitiveValue { public final class StringValue implements PrimitiveValue {
private static final WeakHashMap<String, StringValue> cache = new WeakHashMap<>(); private static final WeakHashMap<String, StringValue> cache = new WeakHashMap<>();
public final String value; public final String value;
@ -57,13 +57,13 @@ public final class StringValue extends PrimitiveValue {
} }
} }
return super.getOwnMember(env, key); return StringValue.this.getOwnMember(env, key);
} }
@Override public Set<String> getOwnMembers(Environment env, boolean onlyEnumerable) { @Override public Set<String> getOwnMembers(Environment env, boolean onlyEnumerable) {
var res = new LinkedHashSet<String>(); var res = new LinkedHashSet<String>();
res.addAll(super.getOwnMembers(env, onlyEnumerable)); res.addAll(StringValue.this.getOwnMembers(env, onlyEnumerable));
for (var i = 0; i < value.length(); i++) res.add(i + ""); for (var i = 0; i < value.length(); i++) res.add(i + "");

View File

@ -11,7 +11,7 @@ import me.topchetoeu.j2s.runtime.values.Value;
import me.topchetoeu.j2s.runtime.values.objects.ObjectValue; import me.topchetoeu.j2s.runtime.values.objects.ObjectValue;
import me.topchetoeu.j2s.runtime.values.primitives.numbers.NumberValue; import me.topchetoeu.j2s.runtime.values.primitives.numbers.NumberValue;
public final class SymbolValue extends PrimitiveValue { public final class SymbolValue implements PrimitiveValue {
private static final HashMap<String, SymbolValue> registry = new HashMap<>(); private static final HashMap<String, SymbolValue> registry = new HashMap<>();
public final String value; public final String value;

View File

@ -15,7 +15,7 @@ import me.topchetoeu.j2s.runtime.values.functions.FunctionValue;
import me.topchetoeu.j2s.runtime.values.objects.ObjectValue; import me.topchetoeu.j2s.runtime.values.objects.ObjectValue;
import me.topchetoeu.j2s.runtime.values.primitives.numbers.NumberValue; import me.topchetoeu.j2s.runtime.values.primitives.numbers.NumberValue;
public final class UserValue<T> extends Value { public final class UserValue<T> implements Value {
public final T value; public final T value;
public final ObjectValue prototype; public final ObjectValue prototype;

View File

@ -11,7 +11,7 @@ import me.topchetoeu.j2s.runtime.values.Member;
import me.topchetoeu.j2s.runtime.values.objects.ObjectValue; import me.topchetoeu.j2s.runtime.values.objects.ObjectValue;
import me.topchetoeu.j2s.runtime.values.primitives.numbers.NumberValue; import me.topchetoeu.j2s.runtime.values.primitives.numbers.NumberValue;
public final class VoidValue extends PrimitiveValue { public final class VoidValue implements PrimitiveValue {
public final String name; public final String name;
public final String type; public final String type;

View File

@ -2,7 +2,7 @@ package me.topchetoeu.j2s.runtime.values.primitives.numbers;
import me.topchetoeu.j2s.common.StringifyUtils; import me.topchetoeu.j2s.common.StringifyUtils;
public final class DoubleValue extends NumberValue { public final class DoubleValue implements NumberValue {
public final double value; public final double value;
@Override public boolean isInt() { @Override public boolean isInt() {

View File

@ -7,7 +7,7 @@ import java.util.List;
import me.topchetoeu.j2s.common.Environment; import me.topchetoeu.j2s.common.Environment;
import me.topchetoeu.j2s.runtime.values.objects.ObjectValue; import me.topchetoeu.j2s.runtime.values.objects.ObjectValue;
public final class IntValue extends NumberValue { public final class IntValue implements NumberValue {
public final long value; public final long value;
@Override public boolean isInt() { @Override public boolean isInt() {

View File

@ -5,10 +5,10 @@ import me.topchetoeu.j2s.runtime.values.objects.ObjectValue;
import me.topchetoeu.j2s.runtime.values.primitives.PrimitiveValue; import me.topchetoeu.j2s.runtime.values.primitives.PrimitiveValue;
import me.topchetoeu.j2s.runtime.values.primitives.StringValue; import me.topchetoeu.j2s.runtime.values.primitives.StringValue;
public abstract class NumberValue extends PrimitiveValue { public interface NumberValue extends PrimitiveValue {
public static final NumberValue NAN = new DoubleValue(Double.NaN); public static final NumberValue NAN = new DoubleValue(Double.NaN);
@Override public final StringValue type() { return StringValue.of("number"); } @Override public default StringValue type() { return StringValue.of("number"); }
public abstract double getDouble(); public abstract double getDouble();
public abstract int getInt(); public abstract int getInt();
@ -21,11 +21,11 @@ public abstract class NumberValue extends PrimitiveValue {
public abstract String toString(); public abstract String toString();
@Override public final boolean toBoolean() { return getDouble() != 0; } @Override public default boolean toBoolean() { return getDouble() != 0; }
@Override public final NumberValue toNumber(Environment ext) { return this; } @Override public default NumberValue toNumber(Environment ext) { return this; }
@Override public final String toString(Environment ext) { return toString(); } @Override public default String toString(Environment ext) { return toString(); }
@Override public final ObjectValue getPrototype(Environment env) { @Override public default ObjectValue getPrototype(Environment env) {
return env.get(NUMBER_PROTO); return env.get(NUMBER_PROTO);
} }