TopchetoEU/revert-ES5 #31

Merged
TopchetoEU merged 41 commits from TopchetoEU/revert-ES5 into master 2024-12-09 21:39:57 +00:00
7 changed files with 224 additions and 100 deletions
Showing only changes of commit 59e6f34a01 - Show all commits

View File

@ -3,27 +3,25 @@ package me.topchetoeu.jscript.runtime.values;
import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import me.topchetoeu.jscript.common.SyntaxException;
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.JSONElement;
import me.topchetoeu.jscript.runtime.EventLoop;
import me.topchetoeu.jscript.runtime.debug.DebugContext;
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.functions.FunctionValue;
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.StringValue;
@ -429,105 +427,13 @@ public abstract class Value {
}
}
private final String toReadable(Environment env, HashSet<Object> passed, int tab) {
if (passed.contains(this)) return "[circular]";
if (this instanceof ObjectValue obj) {
var res = new StringBuilder();
var dbg = DebugContext.get(env);
var printed = true;
var keys = this.getMembers(env, true, false);
if (this instanceof FunctionValue func) {
res.append(this.toString());
var loc = dbg.getMapOrEmpty(func).start();
if (loc != null) res.append(" @ " + loc);
if (
func.prototype instanceof ObjectValue objProto &&
objProto.getMember(env, "constructor") == func &&
objProto.getOwnMembers(env, true).size() + objProto.getOwnSymbolMembers(env, true).size() == 1
) { keys.remove("constructor"); }
}
else if (this instanceof ArrayValue) {
res.append("[");
var arr = (ArrayValue)this;
for (int i = 0; i < arr.size(); i++) {
if (i != 0) res.append(", ");
else res.append(" ");
if (arr.hasMember(env, i, true)) {
res.append(arr.getMember(env, i).toReadable(env, passed, tab));
keys.remove(i + "");
}
else res.append("<empty>");
}
res.append(" ] ");
}
else printed = false;
passed.add(this);
if (keys.size() + obj.getOwnSymbolMembers(env, true).size() == 0) {
if (!printed) res.append("{}");
}
else if (!printed) {
if (tab > 3) return "{...}";
res.append("{\n");
for (var entry : obj.getOwnSymbolMembers(env, true)) {
for (int i = 0; i < tab + 1; i++) res.append(" ");
res.append("[" + entry.value + "]" + ": ");
var member = obj.getOwnMember(env, entry);
if (member instanceof FieldMember field) res.append(field.get(env, obj).toReadable(env, passed, tab + 1));
else if (member instanceof PropertyMember prop) {
if (prop.getter == null && prop.setter == null) res.append("[No accessors]");
else if (prop.getter == null) res.append("[Setter]");
else if (prop.setter == null) res.append("[Getter]");
else res.append("[Getter/Setter]");
}
else res.append("[???]");
res.append(",\n");
}
for (var entry : obj.getOwnMembers(env, true)) {
for (int i = 0; i < tab + 1; i++) res.append(" ");
res.append(entry + ": ");
var member = obj.getOwnMember(env, entry);
if (member instanceof FieldMember field) res.append(field.get(env, obj).toReadable(env, passed, tab + 1));
else if (member instanceof PropertyMember prop) {
if (prop.getter == null && prop.setter == null) res.append("[No accessors]");
else if (prop.getter == null) res.append("[Setter]");
else if (prop.setter == null) res.append("[Getter]");
else res.append("[Getter/Setter]");
}
else res.append("[???]");
res.append(",\n");
}
for (int i = 0; i < tab; i++) res.append(" ");
res.append("}");
}
passed.remove(this);
return res.toString();
}
else if (this instanceof VoidValue) return ((VoidValue)this).name;
else if (this instanceof StringValue) return JSON.stringify(JSONElement.string(((StringValue)this).value));
else if (this instanceof SymbolValue) return this.toString();
else if (this instanceof NumberValue num && num.isLong()) return num.getLong() + "i";
else return this.toString(env);
/** @internal */
public List<String> toReadableLines(Environment env, HashSet<ObjectValue> passed) {
return Arrays.asList(toString(env));
}
public final String toReadable(Environment ext) {
return toReadable(ext, new HashSet<>(), 0);
return String.join("\n", toReadableLines(ext, new HashSet<>()));
}
public static final ObjectValue global(Environment env) {

View File

@ -1,6 +1,12 @@
package me.topchetoeu.jscript.runtime.values.functions;
import java.util.Arrays;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import me.topchetoeu.jscript.common.environment.Environment;
import me.topchetoeu.jscript.runtime.debug.DebugContext;
import me.topchetoeu.jscript.runtime.exceptions.EngineException;
import me.topchetoeu.jscript.runtime.values.KeyCache;
import me.topchetoeu.jscript.runtime.values.Member;
@ -83,6 +89,20 @@ public abstract class FunctionValue extends ObjectValue {
@Override public StringValue type() { return StringValue.of("function"); }
@Override public List<String> toReadableLines(Environment env, HashSet<ObjectValue> passed) {
var dbg = DebugContext.get(env);
var res = new StringBuilder(this.toString());
var loc = dbg.getMapOrEmpty(this).start();
if (loc != null) res.append(" @ " + loc);
var lines = new LinkedList<String>(super.toReadableLines(env, passed));
if (lines.size() == 1 && lines.getFirst().equals("{}")) return Arrays.asList(res.toString());
lines.set(0, res.toString() + " " + lines.getFirst());
return lines;
}
public void setName(String val) {
if (this.name == null || this.name.equals("")) this.name = val;
}

View File

@ -1,6 +1,10 @@
package me.topchetoeu.jscript.runtime.values.objects;
import java.util.Arrays;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import me.topchetoeu.jscript.common.environment.Environment;
@ -104,4 +108,90 @@ public abstract class ArrayLikeValue extends ObjectValue {
return res;
}
private LinkedList<String> toReadableBase(Environment env, HashSet<ObjectValue> passed, HashSet<String> ignoredKeys) {
var stringified = new LinkedList<LinkedList<String>>();
passed.add(this);
var emptyN = 0;
for (int i = 0; i < size(); i++) {
if (has(i)) {
String emptyStr = null;
if (emptyN == 1) emptyStr = "<empty>";
else if (emptyN > 1) emptyStr = "<empty x " + emptyN + ">";
if (emptyStr != null) stringified.add(new LinkedList<>(Arrays.asList(emptyStr + ",")));
emptyN = 0;
stringified.add(new LinkedList<>(get(i).toReadableLines(env, passed)));
ignoredKeys.add(i + "");
var entry = stringified.getLast();
entry.set(entry.size() - 1, entry.getLast() + ",");
}
else {
emptyN++;
}
}
String emptyStr = null;
if (emptyN == 1) emptyStr = "<empty>";
else if (emptyN > 1) emptyStr = "<empty x " + emptyN + ">";
if (emptyStr != null) stringified.add(new LinkedList<>(Arrays.asList(emptyStr)));
else if (stringified.size() > 0) {
var lastEntry = stringified.getLast();
lastEntry.set(lastEntry.size() - 1, lastEntry.getLast().substring(0, lastEntry.getLast().length() - 1));
}
passed.remove(this);
if (stringified.size() == 0) return new LinkedList<>(Arrays.asList("[]"));
var concat = new StringBuilder();
for (var entry : stringified) {
// We make a one-liner only when all members are one-liners
if (entry.size() != 1) {
concat = null;
break;
}
if (concat.length() != 0) concat.append(" ");
concat.append(entry.get(0));
}
// We don't want too long one-liners
if (concat != null && concat.length() < 160) return new LinkedList<>(Arrays.asList("[" + concat.toString() + "]"));
var res = new LinkedList<String>();
res.add("[");
for (var entry : stringified) {
for (var line : entry) {
res.add(" " + line);
}
}
res.set(res.size() - 1, res.getLast().substring(0, res.getLast().length() - 1));
res.add("]");
return res;
}
@Override public List<String> toReadableLines(Environment env, HashSet<ObjectValue> passed) {
var ignored = new HashSet<String>();
var lines = toReadableBase(env, passed, ignored);
var superLines = new LinkedList<String>(super.toReadableLines(env, passed, ignored));
if (superLines.size() == 1 && superLines.getFirst().equals("{}")) return lines;
lines.set(lines.size() - 1, lines.getLast() + " " + superLines.getFirst());
lines.addAll(superLines.subList(1, superLines.size()));
return lines;
}
}

View File

@ -1,7 +1,11 @@
package me.topchetoeu.jscript.runtime.values.objects;
import java.util.Arrays;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import me.topchetoeu.jscript.common.environment.Environment;
@ -10,6 +14,7 @@ import me.topchetoeu.jscript.runtime.exceptions.EngineException;
import me.topchetoeu.jscript.runtime.values.KeyCache;
import me.topchetoeu.jscript.runtime.values.Member;
import me.topchetoeu.jscript.runtime.values.Value;
import me.topchetoeu.jscript.runtime.values.Member.PropertyMember;
import me.topchetoeu.jscript.runtime.values.functions.FunctionValue;
import me.topchetoeu.jscript.runtime.values.primitives.StringValue;
import me.topchetoeu.jscript.runtime.values.primitives.SymbolValue;
@ -134,6 +139,81 @@ public class ObjectValue extends Value {
return setPrototype(_env -> val);
}
private final LinkedList<String> memberToReadable(Environment env, String key, Member member, HashSet<ObjectValue> passed) {
if (member instanceof PropertyMember prop) {
if (prop.getter == null && prop.setter == null) return new LinkedList<>(Arrays.asList(key + ": [No accessors]"));
else if (prop.getter == null) return new LinkedList<>(Arrays.asList(key + ": [Setter]"));
else if (prop.setter == null) return new LinkedList<>(Arrays.asList(key + ": [Getter]"));
else return new LinkedList<>(Arrays.asList(key + ": [Getter/Setter]"));
}
else {
var res = new LinkedList<String>();
var first = true;
for (var line : member.get(env, this).toReadableLines(env, passed)) {
if (first) res.add(key + ": " + line);
else res.add(line);
first = false;
}
return res;
}
}
public List<String> toReadableLines(Environment env, HashSet<ObjectValue> passed, HashSet<String> ignoredKeys) {
passed.add(this);
var stringified = new LinkedList<LinkedList<String>>();
for (var entry : getOwnSymbolMembers(env, true)) {
var member = getOwnMember(env, entry);
stringified.add(memberToReadable(env, "[" + entry.value + "]", member, passed));
}
for (var entry : getOwnMembers(env, true)) {
if (ignoredKeys.contains(entry)) continue;
var member = getOwnMember(env, entry);
stringified.add(memberToReadable(env, entry, member, passed));
}
passed.remove(this);
if (stringified.size() == 0) return Arrays.asList("{}");
var concat = new StringBuilder();
for (var entry : stringified) {
// We make a one-liner only when all members are one-liners
if (entry.size() != 1) {
concat = null;
break;
}
if (concat.length() != 0) concat.append(", ");
concat.append(entry.get(0));
}
// We don't want too long one-liners
if (concat != null && concat.length() < 80) return Arrays.asList("{ " + concat.toString() + " }");
var res = new LinkedList<String>();
res.add("{");
for (var entry : stringified) {
for (var line : entry) {
res.add(" " + line);
}
res.set(res.size() - 1, res.getLast() + ",");
}
res.set(res.size() - 1, res.getLast().substring(0, res.getLast().length() - 1));
res.add("}");
return res;
}
@Override public List<String> toReadableLines(Environment env, HashSet<ObjectValue> passed) {
return toReadableLines(env, passed, new HashSet<>());
}
public final boolean setPrototype(PrototypeProvider val) {
if (!getState().extendable) return false;
prototype = val;

View File

@ -1,10 +1,15 @@
package me.topchetoeu.jscript.runtime.values.primitives;
import java.util.Arrays;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import java.util.WeakHashMap;
import me.topchetoeu.jscript.common.environment.Environment;
import me.topchetoeu.jscript.common.json.JSON;
import me.topchetoeu.jscript.common.json.JSONElement;
import me.topchetoeu.jscript.common.parsing.Parsing;
import me.topchetoeu.jscript.common.parsing.Source;
import me.topchetoeu.jscript.runtime.values.KeyCache;
@ -67,6 +72,10 @@ public final class StringValue extends PrimitiveValue {
return res;
}
@Override public List<String> toReadableLines(Environment env, HashSet<ObjectValue> passed) {
return Arrays.asList(JSON.stringify(JSONElement.string(value)));
}
private StringValue(String value) {
this.value = value;
}

View File

@ -1,5 +1,9 @@
package me.topchetoeu.jscript.runtime.values.primitives;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import me.topchetoeu.jscript.common.environment.Environment;
import me.topchetoeu.jscript.runtime.exceptions.EngineException;
import me.topchetoeu.jscript.runtime.values.KeyCache;
@ -22,6 +26,10 @@ public final class VoidValue extends PrimitiveValue {
throw EngineException.ofError(String.format("Cannot read properties of %s (reading '%s')", name, key.toString(env)));
}
@Override public List<String> toReadableLines(Environment env, HashSet<ObjectValue> passed) {
return Arrays.asList(name);
}
public VoidValue(String name, String type) {
this.name = name;
this.type = type;

View File

@ -1,5 +1,12 @@
package me.topchetoeu.jscript.runtime.values.primitives.numbers;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import me.topchetoeu.jscript.common.environment.Environment;
import me.topchetoeu.jscript.runtime.values.objects.ObjectValue;
public final class IntValue extends NumberValue {
public final long value;
@ -26,6 +33,10 @@ public final class IntValue extends NumberValue {
else return false;
}
@Override public List<String> toReadableLines(Environment env, HashSet<ObjectValue> passed) {
return Arrays.asList(value + "i");
}
public IntValue(long value) {
this.value = value;
}