move JSON and parsing logic to compiler project, decouple JSON and parser from engine logic

This commit is contained in:
2025-01-12 04:27:43 +02:00
parent a115843351
commit cacffd01e8
89 changed files with 495 additions and 370 deletions

View File

@@ -2,10 +2,10 @@ package me.topchetoeu.j2s.runtime;
import java.util.function.Function;
import me.topchetoeu.j2s.common.Filename;
import me.topchetoeu.j2s.common.Location;
import me.topchetoeu.j2s.common.environment.Environment;
import me.topchetoeu.j2s.common.environment.Key;
import me.topchetoeu.j2s.common.parsing.Filename;
import me.topchetoeu.j2s.common.parsing.Location;
import me.topchetoeu.j2s.runtime.exceptions.EngineException;
import me.topchetoeu.j2s.runtime.values.functions.FunctionValue;

View File

@@ -3,9 +3,9 @@ package me.topchetoeu.j2s.runtime;
import java.util.concurrent.Future;
import java.util.function.Supplier;
import me.topchetoeu.j2s.common.Filename;
import me.topchetoeu.j2s.common.environment.Environment;
import me.topchetoeu.j2s.common.environment.Key;
import me.topchetoeu.j2s.common.parsing.Filename;
import me.topchetoeu.j2s.runtime.exceptions.EngineException;
import me.topchetoeu.j2s.runtime.values.Value;
import me.topchetoeu.j2s.runtime.values.functions.FunctionValue;

View File

@@ -1,86 +0,0 @@
package me.topchetoeu.j2s.runtime;
import java.util.HashSet;
import java.util.stream.Collectors;
import me.topchetoeu.j2s.common.environment.Environment;
import me.topchetoeu.j2s.common.json.JSONElement;
import me.topchetoeu.j2s.common.json.JSONList;
import me.topchetoeu.j2s.common.json.JSONMap;
import me.topchetoeu.j2s.runtime.exceptions.EngineException;
import me.topchetoeu.j2s.runtime.values.Value;
import me.topchetoeu.j2s.runtime.values.objects.ArrayValue;
import me.topchetoeu.j2s.runtime.values.objects.ObjectValue;
import me.topchetoeu.j2s.runtime.values.primitives.BoolValue;
import me.topchetoeu.j2s.runtime.values.primitives.StringValue;
import me.topchetoeu.j2s.runtime.values.primitives.VoidValue;
import me.topchetoeu.j2s.runtime.values.primitives.numbers.NumberValue;
public class JSONConverter {
public static Value toJs(JSONElement val) {
if (val.isBoolean()) return BoolValue.of(val.bool());
if (val.isString()) return StringValue.of(val.string());
if (val.isNumber()) return NumberValue.of(val.number());
if (val.isList()) return ArrayValue.of(val.list().stream().map(JSONConverter::toJs).collect(Collectors.toList()));
if (val.isMap()) {
var res = new ObjectValue();
for (var el : val.map().entrySet()) {
res.defineOwnField(null, el.getKey(), toJs(el.getValue()));
}
return res;
}
if (val.isNull()) return Value.NULL;
return Value.UNDEFINED;
}
public static JSONElement fromJs(Environment ext, Value val) {
var res = JSONConverter.fromJs(ext, val, new HashSet<>());
if (res == null) return JSONElement.NULL;
else return res;
}
public static JSONElement fromJs(Environment env, Value val, HashSet<Object> prev) {
if (val instanceof BoolValue) return JSONElement.bool(((BoolValue)val).value);
if (val instanceof NumberValue) return JSONElement.number(((NumberValue)val).getDouble());
if (val instanceof StringValue) return JSONElement.string(((StringValue)val).value);
if (val == Value.NULL) return JSONElement.NULL;
if (val instanceof VoidValue) return null;
if (val instanceof ArrayValue) {
if (prev.contains(val)) throw EngineException.ofError("Circular dependency in JSON.");
prev.add(val);
var res = new JSONList();
for (var el : ((ArrayValue)val).toArray()) {
var jsonEl = fromJs(env, el, prev);
if (jsonEl == null) continue;
res.add(jsonEl);
}
prev.remove(val);
return JSONElement.of(res);
}
if (val instanceof ObjectValue) {
if (prev.contains(val)) throw EngineException.ofError("Circular dependency in JSON.");
prev.add(val);
var res = new JSONMap();
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);
return JSONElement.of(res);
}
if (val == null) return null;
return null;
}
}

View File

@@ -3,12 +3,12 @@ package me.topchetoeu.j2s.runtime.debug;
import java.util.HashMap;
import java.util.WeakHashMap;
import me.topchetoeu.j2s.common.Filename;
import me.topchetoeu.j2s.common.FunctionBody;
import me.topchetoeu.j2s.common.Instruction;
import me.topchetoeu.j2s.common.environment.Environment;
import me.topchetoeu.j2s.common.environment.Key;
import me.topchetoeu.j2s.common.mapping.FunctionMap;
import me.topchetoeu.j2s.common.parsing.Filename;
import me.topchetoeu.j2s.runtime.Frame;
import me.topchetoeu.j2s.runtime.exceptions.EngineException;
import me.topchetoeu.j2s.runtime.values.Value;

View File

@@ -1,10 +1,10 @@
package me.topchetoeu.j2s.runtime.debug;
import me.topchetoeu.j2s.common.Filename;
import me.topchetoeu.j2s.common.FunctionBody;
import me.topchetoeu.j2s.common.Instruction;
import me.topchetoeu.j2s.common.environment.Environment;
import me.topchetoeu.j2s.common.mapping.FunctionMap;
import me.topchetoeu.j2s.common.parsing.Filename;
import me.topchetoeu.j2s.runtime.Frame;
import me.topchetoeu.j2s.runtime.exceptions.EngineException;
import me.topchetoeu.j2s.runtime.values.Value;

View File

@@ -3,8 +3,8 @@ package me.topchetoeu.j2s.runtime.exceptions;
import java.util.ArrayList;
import java.util.List;
import me.topchetoeu.j2s.common.Location;
import me.topchetoeu.j2s.common.environment.Environment;
import me.topchetoeu.j2s.common.parsing.Location;
import me.topchetoeu.j2s.runtime.values.Value;
import me.topchetoeu.j2s.runtime.values.objects.ObjectValue;
import me.topchetoeu.j2s.runtime.values.objects.ObjectValue.PrototypeProvider;

View File

@@ -7,11 +7,8 @@ import java.util.List;
import java.util.Set;
import java.util.WeakHashMap;
import me.topchetoeu.j2s.common.StringifyUtils;
import me.topchetoeu.j2s.common.environment.Environment;
import me.topchetoeu.j2s.common.json.JSON;
import me.topchetoeu.j2s.common.json.JSONElement;
import me.topchetoeu.j2s.common.parsing.Parsing;
import me.topchetoeu.j2s.common.parsing.Source;
import me.topchetoeu.j2s.runtime.values.KeyCache;
import me.topchetoeu.j2s.runtime.values.Member;
import me.topchetoeu.j2s.runtime.values.Member.FieldMember;
@@ -29,10 +26,7 @@ public final class StringValue extends PrimitiveValue {
@Override public NumberValue toNumber(Environment ext) {
var val = value.trim();
if (val.equals("")) return NumberValue.of(0);
var res = Parsing.parseNumber(new Source(val), 0, true);
if (res.isSuccess() && res.n == val.length()) return NumberValue.of(res.result);
else return NumberValue.NAN;
return NumberValue.of(StringifyUtils.unqoteNumber(val));
}
@Override public String toString(Environment ext) { return value; }
@@ -79,7 +73,7 @@ public final class StringValue extends PrimitiveValue {
}
@Override public List<String> toReadableLines(Environment env, HashSet<ObjectValue> passed) {
return Arrays.asList(JSON.stringify(JSONElement.string(value)));
return Arrays.asList(StringifyUtils.quoteString(value));
}
private StringValue(String value) {

View File

@@ -1,7 +1,6 @@
package me.topchetoeu.j2s.runtime.values.primitives.numbers;
import me.topchetoeu.j2s.common.json.JSON;
import me.topchetoeu.j2s.common.json.JSONElement;
import me.topchetoeu.j2s.common.StringifyUtils;
public final class DoubleValue extends NumberValue {
public final double value;
@@ -22,7 +21,7 @@ public final class DoubleValue extends NumberValue {
return value;
}
@Override public String toString() { return JSON.stringify(JSONElement.number(value)); }
@Override public String toString() { return StringifyUtils.quoteNumber(value); }
@Override public int hashCode() {
return Double.hashCode(value);

View File

@@ -1,8 +1,6 @@
package me.topchetoeu.j2s.runtime.values.primitives.numbers;
import me.topchetoeu.j2s.common.environment.Environment;
import me.topchetoeu.j2s.common.parsing.Parsing;
import me.topchetoeu.j2s.common.parsing.Source;
import me.topchetoeu.j2s.runtime.values.objects.ObjectValue;
import me.topchetoeu.j2s.runtime.values.primitives.PrimitiveValue;
import me.topchetoeu.j2s.runtime.values.primitives.StringValue;
@@ -31,25 +29,6 @@ public abstract class NumberValue extends PrimitiveValue {
return env.get(NUMBER_PROTO);
}
public static NumberValue parseInt(String str, int radix, boolean relaxed) {
if (radix < 2 || radix > 36) return NumberValue.NAN;
str = str.trim();
var res = Parsing.parseInt(new Source(str), 0, "0123456789abcdefghijklmnopqrstuvwxyz".substring(0, radix), true);
if (res.isSuccess()) {
if (relaxed || res.n == str.length()) return of(res.result);
}
return NumberValue.NAN;
}
public static NumberValue parseFloat(String str, boolean relaxed) {
str = str.trim();
var res = Parsing.parseFloat(new Source(str), 0, true);
if (res.isSuccess()) {
if (relaxed || res.n == str.length()) return of(res.result);
}
return NumberValue.NAN;
}
public static NumberValue of(double value) {
if (Double.isNaN(value)) return NAN;
else if ((int)value == value) return new IntValue((int)value);