diff --git a/runtime/src/main/java/me/topchetoeu/j2s/runtime/ArgumentsValue.java b/runtime/src/main/java/me/topchetoeu/j2s/runtime/ArgumentsValue.java index 6e3050b..375f2ee 100644 --- a/runtime/src/main/java/me/topchetoeu/j2s/runtime/ArgumentsValue.java +++ b/runtime/src/main/java/me/topchetoeu/j2s/runtime/ArgumentsValue.java @@ -1,13 +1,53 @@ package me.topchetoeu.j2s.runtime; +import me.topchetoeu.j2s.common.Environment; import me.topchetoeu.j2s.runtime.values.Value; -import me.topchetoeu.j2s.runtime.values.objects.ArrayValue; +import me.topchetoeu.j2s.runtime.values.objects.ArrayLikeValue; -public class ArgumentsValue extends ArrayValue { +public class ArgumentsValue extends ArrayLikeValue { public final Frame frame; + private Value[] args; + private boolean shadowed; - public ArgumentsValue(Frame frame, Value... args) { - super(args); + private void shadow() { + if (!shadowed) { + var newArgs = new Value[args.length]; + System.arraycopy(args, 0, newArgs, 0, args.length); + args = newArgs; + shadowed = true; + } + } + + @Override public Value get(int i) { + return args[i]; + } + @Override public boolean has(int i) { + if (i < 0 || i >= size()) return false; + + if (shadowed) return args[i] != null; + else return true; + } + @Override public boolean remove(int i) { + shadow(); + args[i] = null; + return true; + } + @Override public boolean set(Environment env, int i, Value val) { + shadow(); + args[i] = val; + return true; + } + @Override public boolean setSize(int val) { + return false; + } + @Override public int size() { + return args.length; + } + + public ArgumentsValue(Frame frame) { this.frame = frame; + this.args = frame.args; + this.shadowed = false; + setPrototype(e -> null); } } diff --git a/runtime/src/main/java/me/topchetoeu/j2s/runtime/Frame.java b/runtime/src/main/java/me/topchetoeu/j2s/runtime/Frame.java index 62ba300..b84cea4 100644 --- a/runtime/src/main/java/me/topchetoeu/j2s/runtime/Frame.java +++ b/runtime/src/main/java/me/topchetoeu/j2s/runtime/Frame.java @@ -383,7 +383,7 @@ public final class Frame { this.self = self; this.args = args; - this.argsVal = new ArgumentsValue(this, args); + this.argsVal = new ArgumentsValue(this); this.argsLen = new IntValue(args.length); this.captures = func.captures; diff --git a/runtime/src/main/java/me/topchetoeu/j2s/runtime/values/objects/ArrayLikeValue.java b/runtime/src/main/java/me/topchetoeu/j2s/runtime/values/objects/ArrayLikeValue.java index 78d8192..b6eea39 100644 --- a/runtime/src/main/java/me/topchetoeu/j2s/runtime/values/objects/ArrayLikeValue.java +++ b/runtime/src/main/java/me/topchetoeu/j2s/runtime/values/objects/ArrayLikeValue.java @@ -56,6 +56,17 @@ public abstract class ArrayLikeValue extends ObjectValue { public abstract boolean has(int i); public abstract boolean remove(int i); + public Value[] toArray() { + var n = size(); + var res = new Value[n]; + + for (var i = 0; i < n; i++) { + if (has(i)) res[i] = get(i); + } + + return res; + } + @Override public Member getOwnMember(Environment env, KeyCache key) { var res = super.getOwnMember(env, key); if (res != null) return res; diff --git a/runtime/src/main/java/me/topchetoeu/j2s/runtime/values/objects/ArrayValue.java b/runtime/src/main/java/me/topchetoeu/j2s/runtime/values/objects/ArrayValue.java index f8a954e..7d7deac 100644 --- a/runtime/src/main/java/me/topchetoeu/j2s/runtime/values/objects/ArrayValue.java +++ b/runtime/src/main/java/me/topchetoeu/j2s/runtime/values/objects/ArrayValue.java @@ -68,7 +68,7 @@ public class ArrayValue extends ArrayLikeValue implements Iterable { } } - public Value[] toArray() { + @Override public Value[] toArray() { var res = new Value[size]; copyTo(res, 0, 0, size); return res;