From d87e53264db1e8d1bb5f28b6521379d1370549f6 Mon Sep 17 00:00:00 2001 From: TopchetoEU <36534413+TopchetoEU@users.noreply.github.com> Date: Sat, 14 Sep 2024 14:22:31 +0300 Subject: [PATCH] refactor: split array logic --- .../values/objects/ArrayLikeValue.java | 97 +++++++++++++++++++ .../runtime/values/objects/ArrayValue.java | 93 ++---------------- 2 files changed, 103 insertions(+), 87 deletions(-) create mode 100644 src/main/java/me/topchetoeu/jscript/runtime/values/objects/ArrayLikeValue.java diff --git a/src/main/java/me/topchetoeu/jscript/runtime/values/objects/ArrayLikeValue.java b/src/main/java/me/topchetoeu/jscript/runtime/values/objects/ArrayLikeValue.java new file mode 100644 index 0000000..6b4caf3 --- /dev/null +++ b/src/main/java/me/topchetoeu/jscript/runtime/values/objects/ArrayLikeValue.java @@ -0,0 +1,97 @@ +package me.topchetoeu.jscript.runtime.values.objects; + +import java.util.LinkedHashSet; +import java.util.Set; + +import me.topchetoeu.jscript.common.environment.Environment; +import me.topchetoeu.jscript.runtime.values.KeyCache; +import me.topchetoeu.jscript.runtime.values.Member; +import me.topchetoeu.jscript.runtime.values.Member.FieldMember; +import me.topchetoeu.jscript.runtime.values.Value; +import me.topchetoeu.jscript.runtime.values.primitives.NumberValue; + +public abstract class ArrayLikeValue extends ObjectValue { + private static class IndexField extends FieldMember { + private int i; + private ArrayLikeValue arr; + + @Override public Value get(Environment env, Value self) { + return arr.get(i); + } + @Override public boolean set(Environment env, Value val, Value self) { + arr.set(i, val); + return true; + } + public IndexField(int i, ArrayLikeValue arr) { + super(arr, true, true, true); + this.arr = arr; + this.i = i; + } + } + + private final FieldMember lengthField = new FieldMember(this, false, false, true) { + @Override public Value get(Environment env, Value self) { + return new NumberValue(size()); + } + @Override public boolean set(Environment env, Value val, Value self) { + return setSize(val.toInt(env)); + } + }; + + public abstract int size(); + public abstract boolean setSize(int val); + + public abstract Value get(int i); + public abstract void set(int i, Value val); + public abstract boolean has(int i); + public abstract void remove(int i); + + @Override public Member getOwnMember(Environment env, KeyCache key) { + var res = super.getOwnMember(env, key); + if (res != null) return res; + + var num = key.toNumber(env); + var i = key.toInt(env); + + if (i == num && i >= 0 && i < size() && has(i)) return new IndexField(i, this); + else if (key.toString(env).equals("length")) return lengthField; + else return null; + } + @Override public boolean defineOwnMember(Environment env, KeyCache key, Member member) { + if (!(member instanceof FieldMember) || super.getOwnMember(env, key) != null) return super.defineOwnMember(env, key, member); + if (!getState().writable) return false; + + var num = key.toNumber(env); + var i = key.toInt(env); + + if (i == num && i >= 0) { + if (!getState().extendable && !has(i)) return false; + set(i, ((FieldMember)member).get(env, this)); + return true; + } + else return super.defineOwnMember(env, key, member); + } + @Override public boolean deleteOwnMember(Environment env, KeyCache key) { + if (!super.deleteOwnMember(env, key)) return false; + + var num = key.toNumber(env); + var i = key.toInt(env); + + if (i == num && i >= 0 && i < size()) return super.deleteOwnMember(env, key); + else return true; + } + + @Override public Set getOwnMembers(Environment env, boolean onlyEnumerable) { + var res = new LinkedHashSet(); + + res.addAll(super.getOwnMembers(env, onlyEnumerable)); + + for (var i = 0; i < size(); i++) { + if (has(i)) res.add(i + ""); + } + + if (!onlyEnumerable) res.add("length"); + + return res; + } +} diff --git a/src/main/java/me/topchetoeu/jscript/runtime/values/objects/ArrayValue.java b/src/main/java/me/topchetoeu/jscript/runtime/values/objects/ArrayValue.java index 397ab5b..5ad0b56 100644 --- a/src/main/java/me/topchetoeu/jscript/runtime/values/objects/ArrayValue.java +++ b/src/main/java/me/topchetoeu/jscript/runtime/values/objects/ArrayValue.java @@ -4,50 +4,15 @@ import java.util.Arrays; import java.util.Collection; import java.util.Comparator; import java.util.Iterator; -import java.util.LinkedHashSet; -import java.util.Set; -import me.topchetoeu.jscript.common.environment.Environment; -import me.topchetoeu.jscript.runtime.values.KeyCache; -import me.topchetoeu.jscript.runtime.values.Member; -import me.topchetoeu.jscript.runtime.values.Member.FieldMember; import me.topchetoeu.jscript.runtime.values.Value; -import me.topchetoeu.jscript.runtime.values.primitives.NumberValue; import me.topchetoeu.jscript.runtime.values.primitives.VoidValue; // TODO: Make methods generic -public class ArrayValue extends ObjectValue implements Iterable { +public class ArrayValue extends ArrayLikeValue implements Iterable { private Value[] values; private int size; - private final FieldMember lengthField = new FieldMember(false, false, true) { - @Override public Value get(Environment env, Value self) { - return new NumberValue(size); - } - @Override public boolean set(Environment env, Value val, Value self) { - size = val.toInt(env); - return true; - } - }; - - private class IndexField extends FieldMember { - private int i; - private ArrayValue arr; - - @Override public Value get(Environment env, Value self) { - return arr.get(i); - } - @Override public boolean set(Environment env, Value val, Value self) { - arr.set(i, val); - return true; - } - public IndexField(int i, ArrayValue arr) { - super(true, true, true); - this.arr = arr; - this.i = i; - } - } - private Value[] alloc(int index) { index++; if (index < values.length) return values; @@ -69,26 +34,27 @@ public class ArrayValue extends ObjectValue implements Iterable { return true; } - public Value get(int i) { + @Override public Value get(int i) { if (i < 0 || i >= size) return null; var res = values[i]; if (res == null) return Value.UNDEFINED; else return res; } - public void set(int i, Value val) { + @Override public void set(int i, Value val) { if (i < 0) return; alloc(i)[i] = val; if (i >= size) size = i + 1; } - public boolean has(int i) { + @Override public boolean has(int i) { return i >= 0 && i < size && values[i] != null; } - public void remove(int i) { + @Override public void remove(int i) { if (i < 0 || i >= values.length) return; values[i] = null; } + public void shrink(int n) { if (n >= values.length) { values = new Value[16]; @@ -149,53 +115,6 @@ public class ArrayValue extends ObjectValue implements Iterable { }); } - @Override public Member getOwnMember(Environment env, KeyCache key) { - var res = super.getOwnMember(env, key); - if (res != null) return res; - - var num = key.toNumber(env); - var i = key.toInt(env); - - if (i == num && i >= 0 && i < size && has(i)) return new IndexField(i, this); - else if (key.toString(env).equals("length")) return lengthField; - else return null; - } - @Override public boolean defineOwnMember(Environment env, KeyCache key, Member member) { - if (!(member instanceof FieldMember) || hasMember(env, key, true)) return super.defineOwnMember(env, key, member); - if (!extensible) return false; - - var num = key.toNumber(env); - var i = key.toInt(env); - - if (i == num && i >= 0) { - set(i, ((FieldMember)member).get(env, this)); - return true; - } - else return super.defineOwnMember(env, key, member); - } - @Override public boolean deleteOwnMember(Environment env, KeyCache key) { - if (!super.deleteOwnMember(env, key)) return false; - - var num = key.toNumber(env); - var i = key.toInt(env); - - if (i == num && i >= 0 && i < size) return super.deleteOwnMember(env, key); - else return true; - } - - @Override public Set getOwnMembers(Environment env, boolean onlyEnumerable) { - var res = new LinkedHashSet(); - - res.addAll(super.getOwnMembers(env, onlyEnumerable)); - - for (var i = 0; i < size; i++) { - if (has(i)) res.add(i + ""); - } - - if (!onlyEnumerable) res.add("length"); - - return res; - } @Override public Iterator iterator() { return new Iterator<>() { private int i = 0;