refactor: improve meber listing system
This commit is contained in:
parent
b6f04aa177
commit
515011b3ef
@ -1,8 +1,8 @@
|
||||
package me.topchetoeu.jscript.runtime;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
import java.util.Stack;
|
||||
|
||||
import me.topchetoeu.jscript.common.Instruction;
|
||||
@ -402,19 +402,11 @@ public final class Frame {
|
||||
}
|
||||
};
|
||||
}
|
||||
@Override public Map<String, Member> getOwnMembers(Environment env) {
|
||||
var res = new LinkedHashMap<String, Member>();
|
||||
@Override public Set<String> getOwnMembers(Environment env, boolean onlyEnumerable) {
|
||||
var res = new LinkedHashSet<String>();
|
||||
res.addAll(super.getOwnMembers(env, onlyEnumerable));
|
||||
|
||||
for (var i = 0; i < stackPtr; i++) {
|
||||
var _i = i;
|
||||
res.put(i + "", new FieldMember(false, true, true) {
|
||||
@Override public Value get(Environment env, Value self) { return stack[_i]; }
|
||||
@Override public boolean set(Environment env, Value val, Value self) {
|
||||
stack[_i] = val;
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
for (var i = 0; i < stackPtr; i++) res.add(i + "");
|
||||
|
||||
return res;
|
||||
}
|
||||
|
@ -7,7 +7,6 @@ import me.topchetoeu.jscript.common.Instruction;
|
||||
import me.topchetoeu.jscript.common.Operation;
|
||||
import me.topchetoeu.jscript.common.environment.Environment;
|
||||
import me.topchetoeu.jscript.runtime.exceptions.EngineException;
|
||||
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.functions.CodeFunction;
|
||||
@ -83,14 +82,14 @@ public class InstructionRunner {
|
||||
private static Value execKeys(Environment env, Instruction instr, Frame frame) {
|
||||
var val = frame.pop();
|
||||
|
||||
var members = new ArrayList<>(val.getMembers(env, false, true).keySet());
|
||||
var members = new ArrayList<>(val.getMembers(env, false, true));
|
||||
Collections.reverse(members);
|
||||
|
||||
frame.push(null);
|
||||
|
||||
for (var el : members) {
|
||||
var obj = new ObjectValue();
|
||||
obj.defineOwnMember(env, "value", FieldMember.of(new StringValue(el)));
|
||||
obj.defineOwnMember(env, "value", new StringValue(el));
|
||||
frame.push(obj);
|
||||
}
|
||||
|
||||
|
@ -70,10 +70,11 @@ public class JSONConverter {
|
||||
|
||||
var res = new JSONMap();
|
||||
|
||||
for (var el : val.getMembers(env, true, true).entrySet()) {
|
||||
var jsonEl = fromJs(env, el.getValue().get(env, val), prev);
|
||||
if (jsonEl == null) continue;
|
||||
res.put(el.getKey(), jsonEl);
|
||||
for (var key : val.getOwnMembers(env, true)) {
|
||||
var el = fromJs(env, val.getMember(env, key), prev);
|
||||
if (el == null) continue;
|
||||
|
||||
res.put(key, el);
|
||||
}
|
||||
|
||||
prev.remove(val);
|
||||
|
@ -7,8 +7,9 @@ import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import me.topchetoeu.jscript.common.environment.Environment;
|
||||
import me.topchetoeu.jscript.common.environment.Key;
|
||||
@ -119,8 +120,8 @@ public abstract class Value {
|
||||
}
|
||||
|
||||
public abstract Member getOwnMember(Environment env, KeyCache key);
|
||||
public abstract Map<String, Member> getOwnMembers(Environment env);
|
||||
public abstract Map<SymbolValue, Member> getOwnSymbolMembers(Environment env);
|
||||
public abstract Set<String> getOwnMembers(Environment env, boolean onlyEnumerable);
|
||||
public abstract Set<SymbolValue> getOwnSymbolMembers(Environment env, boolean onlyEnumerable);
|
||||
public abstract boolean defineOwnMember(Environment env, KeyCache key, Member member);
|
||||
public abstract boolean deleteOwnMember(Environment env, KeyCache key);
|
||||
|
||||
@ -317,8 +318,8 @@ public abstract class Value {
|
||||
return deleteMember(env, new KeyCache(key));
|
||||
}
|
||||
|
||||
public final Map<String, Member> getMembers(Environment env, boolean own, boolean onlyEnumerable) {
|
||||
var res = new LinkedHashMap<String, Member>();
|
||||
public final Set<String> getMembers(Environment env, boolean own, boolean onlyEnumerable) {
|
||||
var res = new LinkedHashSet<String>();
|
||||
var protos = new ArrayList<Value>();
|
||||
|
||||
for (var proto = this; proto != null; proto = proto.getPrototype(env)) {
|
||||
@ -329,19 +330,13 @@ public abstract class Value {
|
||||
Collections.reverse(protos);
|
||||
|
||||
for (var proto : protos) {
|
||||
if (onlyEnumerable) {
|
||||
for (var el : proto.getOwnMembers(env).entrySet()) {
|
||||
if (!el.getValue().enumerable()) continue;
|
||||
res.put(el.getKey(), el.getValue());
|
||||
}
|
||||
}
|
||||
else res.putAll(proto.getOwnMembers(env));
|
||||
res.addAll(proto.getOwnMembers(env, onlyEnumerable));
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
public final Map<SymbolValue, Member> getSymbolMembers(Environment env, boolean own, boolean onlyEnumerable) {
|
||||
var res = new LinkedHashMap<SymbolValue, Member>();
|
||||
public final Set<SymbolValue> getSymbolMembers(Environment env, boolean own, boolean onlyEnumerable) {
|
||||
var res = new LinkedHashSet<SymbolValue>();
|
||||
var protos = new ArrayList<Value>();
|
||||
|
||||
for (var proto = this; proto != null; proto = proto.getPrototype(env)) {
|
||||
@ -352,13 +347,7 @@ public abstract class Value {
|
||||
Collections.reverse(protos);
|
||||
|
||||
for (var proto : protos) {
|
||||
if (onlyEnumerable) {
|
||||
for (var el : proto.getOwnSymbolMembers(env).entrySet()) {
|
||||
if (!el.getValue().enumerable()) continue;
|
||||
res.put(el.getKey(), el.getValue());
|
||||
}
|
||||
}
|
||||
else res.putAll(proto.getOwnSymbolMembers(env));
|
||||
res.addAll(proto.getOwnSymbolMembers(env, onlyEnumerable));
|
||||
}
|
||||
|
||||
return res;
|
||||
@ -444,7 +433,7 @@ public abstract class Value {
|
||||
if (
|
||||
func.prototype instanceof ObjectValue objProto &&
|
||||
objProto.getMember(env, "constructor") == func &&
|
||||
objProto.getOwnMembers(env).size() + objProto.getOwnSymbolMembers(env).size() == 1
|
||||
objProto.getOwnMembers(env, true).size() + objProto.getOwnSymbolMembers(env, true).size() == 1
|
||||
) { keys.remove("constructor"); }
|
||||
}
|
||||
else if (this instanceof ArrayValue) {
|
||||
@ -469,29 +458,29 @@ public abstract class Value {
|
||||
|
||||
passed.add(this);
|
||||
|
||||
if (keys.size() + obj.getOwnSymbolMembers(env).size() == 0) {
|
||||
if (keys.size() + obj.getOwnSymbolMembers(env, true).size() == 0) {
|
||||
if (!printed) res.append("{}\n");
|
||||
}
|
||||
else if (!printed) {
|
||||
if (tab > 3) return "{...}";
|
||||
res.append("{\n");
|
||||
|
||||
for (var entry : obj.getOwnSymbolMembers(env).entrySet()) {
|
||||
for (var entry : obj.getOwnSymbolMembers(env, true)) {
|
||||
for (int i = 0; i < tab + 1; i++) res.append(" ");
|
||||
res.append("[" + entry.getKey().value + "]" + ": ");
|
||||
res.append("[" + entry.value + "]" + ": ");
|
||||
|
||||
var member = entry.getValue();
|
||||
if (member instanceof FieldMember) res.append(((FieldMember)member).get(env, obj).toReadable(env, passed, tab + 1));
|
||||
var member = obj.getOwnMember(env, entry);
|
||||
if (member instanceof FieldMember field) res.append(field.get(env, obj).toReadable(env, passed, tab + 1));
|
||||
else res.append("[property]");
|
||||
|
||||
res.append(",\n");
|
||||
}
|
||||
for (var entry : obj.getOwnMembers(env).entrySet()) {
|
||||
for (var entry : obj.getOwnMembers(env, true)) {
|
||||
for (int i = 0; i < tab + 1; i++) res.append(" ");
|
||||
res.append(entry.getKey() + ": ");
|
||||
res.append(entry + ": ");
|
||||
|
||||
var member = entry.getValue();
|
||||
if (member instanceof FieldMember) res.append(((FieldMember)member).get(env, obj).toReadable(env, passed, tab + 1));
|
||||
var member = obj.getOwnMember(env, entry);
|
||||
if (member instanceof FieldMember field) res.append(field.get(env, obj).toReadable(env, passed, tab + 1));
|
||||
else res.append("[property]");
|
||||
|
||||
res.append(",\n");
|
||||
|
@ -4,8 +4,8 @@ import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Comparator;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import me.topchetoeu.jscript.common.environment.Environment;
|
||||
import me.topchetoeu.jscript.runtime.values.KeyCache;
|
||||
@ -183,17 +183,16 @@ public class ArrayValue extends ObjectValue implements Iterable<Value> {
|
||||
else return true;
|
||||
}
|
||||
|
||||
@Override public Map<String, Member> getOwnMembers(Environment env) {
|
||||
var res = new LinkedHashMap<String, Member>();
|
||||
@Override public Set<String> getOwnMembers(Environment env, boolean onlyEnumerable) {
|
||||
var res = new LinkedHashSet<String>();
|
||||
|
||||
res.addAll(super.getOwnMembers(env, onlyEnumerable));
|
||||
|
||||
for (var i = 0; i < size; i++) {
|
||||
var member = getOwnMember(env, i);
|
||||
if (member != null) res.put(i + "", member);
|
||||
if (has(i)) res.add(i + "");
|
||||
}
|
||||
|
||||
res.put("length", lengthField);
|
||||
|
||||
res.putAll(super.getOwnMembers(env));
|
||||
if (!onlyEnumerable) res.add("length");
|
||||
|
||||
return res;
|
||||
}
|
||||
|
@ -1,8 +1,8 @@
|
||||
package me.topchetoeu.jscript.runtime.values.objects;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import me.topchetoeu.jscript.common.environment.Environment;
|
||||
import me.topchetoeu.jscript.common.environment.Key;
|
||||
@ -100,11 +100,29 @@ public class ObjectValue extends Value {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override public Map<String, Member> getOwnMembers(Environment env) {
|
||||
return members;
|
||||
@Override public Set<String> getOwnMembers(Environment env, boolean onlyEnumerable) {
|
||||
if (onlyEnumerable) {
|
||||
var res = new LinkedHashSet<String>();
|
||||
|
||||
for (var el : members.entrySet()) {
|
||||
if (el.getValue().enumerable()) res.add(el.getKey());
|
||||
}
|
||||
@Override public Map<SymbolValue, Member> getOwnSymbolMembers(Environment env) {
|
||||
return Collections.unmodifiableMap(symbolMembers);
|
||||
|
||||
return res;
|
||||
}
|
||||
else return members.keySet();
|
||||
}
|
||||
@Override public Set<SymbolValue> getOwnSymbolMembers(Environment env, boolean onlyEnumerable) {
|
||||
if (onlyEnumerable) {
|
||||
var res = new LinkedHashSet<SymbolValue>();
|
||||
|
||||
for (var el : symbolMembers.entrySet()) {
|
||||
if (el.getValue().enumerable()) res.add(el.getKey());
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
else return symbolMembers.keySet();
|
||||
}
|
||||
|
||||
@Override public ObjectValue getPrototype(Environment env) {
|
||||
|
@ -1,6 +1,6 @@
|
||||
package me.topchetoeu.jscript.runtime.values.primitives;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import me.topchetoeu.jscript.common.environment.Environment;
|
||||
import me.topchetoeu.jscript.runtime.values.KeyCache;
|
||||
@ -17,6 +17,6 @@ public abstract class PrimitiveValue extends Value {
|
||||
@Override public final boolean setPrototype(Environment env, ObjectValue val) { return false; }
|
||||
|
||||
@Override public Member getOwnMember(Environment env, KeyCache key) { return null; }
|
||||
@Override public Map<String, Member> getOwnMembers(Environment env) { return Map.of(); }
|
||||
@Override public Map<SymbolValue, Member> getOwnSymbolMembers(Environment env) { return Map.of(); }
|
||||
@Override public Set<String> getOwnMembers(Environment env, boolean onlyEnumerable) { return Set.of(); }
|
||||
@Override public Set<SymbolValue> getOwnSymbolMembers(Environment env, boolean onlyEnumerable) { return Set.of(); }
|
||||
}
|
||||
|
@ -1,11 +1,14 @@
|
||||
package me.topchetoeu.jscript.runtime.values.primitives;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import me.topchetoeu.jscript.common.environment.Environment;
|
||||
import me.topchetoeu.jscript.common.parsing.Parsing;
|
||||
import me.topchetoeu.jscript.common.parsing.Source;
|
||||
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.objects.ObjectValue;
|
||||
|
||||
public final class StringValue extends PrimitiveValue {
|
||||
@ -32,9 +35,29 @@ public final class StringValue extends PrimitiveValue {
|
||||
|
||||
@Override public ObjectValue getPrototype(Environment env) { return env.get(STRING_PROTO); }
|
||||
|
||||
@Override public Map<String, Member> getOwnMembers(Environment env) {
|
||||
// TODO Auto-generated method stub
|
||||
return super.getOwnMembers(env);
|
||||
@Override public Member getOwnMember(Environment env, KeyCache key) {
|
||||
var num = key.toNumber(env);
|
||||
var i = key.toInt(env);
|
||||
|
||||
if (i == num && i >= 0 && i < value.length()) {
|
||||
return FieldMember.of(new StringValue(value.charAt(i) + ""), false, true, false);
|
||||
}
|
||||
else if (key.toString(env).equals("length")) {
|
||||
return FieldMember.of(new NumberValue(value.length()), false, false, false);
|
||||
}
|
||||
else return super.getOwnMember(env, key);
|
||||
}
|
||||
|
||||
@Override public Set<String> getOwnMembers(Environment env, boolean onlyEnumerable) {
|
||||
var res = new LinkedHashSet<String>();
|
||||
|
||||
res.addAll(super.getOwnMembers(env, onlyEnumerable));
|
||||
|
||||
for (var i = 0; i < value.length(); i++) res.add(i + "");
|
||||
|
||||
if (!onlyEnumerable) res.add("length");
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
public StringValue(String value) {
|
||||
|
@ -1,6 +1,6 @@
|
||||
package me.topchetoeu.jscript.runtime.values.primitives;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import me.topchetoeu.jscript.common.environment.Environment;
|
||||
import me.topchetoeu.jscript.runtime.exceptions.EngineException;
|
||||
@ -24,17 +24,13 @@ public final class VoidValue extends PrimitiveValue {
|
||||
@Override public Member getOwnMember(Environment env, KeyCache key) {
|
||||
throw EngineException.ofError(String.format("Cannot read properties of %s (reading '%s')", name, key.toString(env)));
|
||||
}
|
||||
@Override public Map<String, Member> getOwnMembers(Environment env) {
|
||||
@Override public Set<String> getOwnMembers(Environment env, boolean onlyEnumerable) {
|
||||
throw EngineException.ofError(String.format("Cannot read properties of %s (listing all members)", name));
|
||||
}
|
||||
@Override public Map<SymbolValue, Member> getOwnSymbolMembers(Environment env) {
|
||||
@Override public Set<SymbolValue> getOwnSymbolMembers(Environment env, boolean onlyEnumerable) {
|
||||
throw EngineException.ofError(String.format("Cannot read properties of %s (listing all symbol members)", name));
|
||||
}
|
||||
|
||||
// @Override public Value call(Environment env, Value self, Value... args) {
|
||||
// throw EngineException.ofType(String.format("Tried to call a value of %s", name));
|
||||
// }
|
||||
|
||||
public VoidValue(String name, StringValue type) {
|
||||
this.name = name;
|
||||
this.typeString = type;
|
||||
|
Loading…
Reference in New Issue
Block a user