diff options
author | Piotr Fusik <piotr@fusion-lang.org> | 2024-02-27 16:38:20 +0100 |
---|---|---|
committer | Piotr Fusik <piotr@fusion-lang.org> | 2024-02-27 16:38:20 +0100 |
commit | 1b5d9a44bb1bdec54c20201c6f70a49822a34501 (patch) | |
tree | 7a40deacd99916bbdb36f56d594987d6f4be56c3 | |
parent | 6ab069f177ebcbfd067940be42349bd03a2ceb26 (diff) |
[json] Replace JsonValueKind enum with JsonElement.IsXXX methods.
#140
-rw-r--r-- | AST.fu | 41 | ||||
-rw-r--r-- | GenCs.fu | 36 | ||||
-rw-r--r-- | GenD.fu | 67 | ||||
-rw-r--r-- | GenJs.fu | 73 | ||||
-rw-r--r-- | GenPy.fu | 73 | ||||
-rw-r--r-- | Sema.fu | 2 | ||||
-rw-r--r-- | libfut.cpp | 331 | ||||
-rw-r--r-- | libfut.cs | 293 | ||||
-rw-r--r-- | libfut.hpp | 21 | ||||
-rw-r--r-- | libfut.js | 545 | ||||
-rw-r--r-- | test/JsonElement.fu | 34 |
11 files changed, 785 insertions, 731 deletions
@@ -97,7 +97,6 @@ public enum FuId RegexOptionsEnum, RegexClass, MatchClass, - JsonValueKindEnum, JsonElementClass, LockClass, StringLength, @@ -109,14 +108,6 @@ public enum FuId MatchEnd, MatchLength, MatchValue, - JsonValueKindObject, - JsonValueKindArray, - JsonValueKindString, - JsonValueKindNumber, - JsonValueKindTrue, - JsonValueKindFalse, - JsonValueKindNull, - JsonElementValueKind, MathNaN, MathNegativeInfinity, MathPositiveInfinity, @@ -211,7 +202,12 @@ public enum FuId MatchFindRegex, MatchGetCapture, JsonElementParse, - JsonElementTryParse, + JsonElementIsObject, + JsonElementIsArray, + JsonElementIsString, + JsonElementIsNumber, + JsonElementIsBoolean, + JsonElementIsNull, JsonElementGetObject, JsonElementGetArray, JsonElementGetString, @@ -1058,7 +1054,7 @@ public abstract class FuNamedValue : FuSymbol { internal FuExpr#? TypeExpr; internal FuExpr#? Value; - public bool IsAssignableStorage() => this.Type is FuStorageType storage && !(this.Type is FuArrayStorageType) && (this.Value is FuLiteralNull || storage.Class.Id == FuId.JsonElementClass); + public bool IsAssignableStorage() => this.Type is FuStorageType storage && !(this.Type is FuArrayStorageType) && this.Value is FuLiteralNull; } public abstract class FuMember : FuNamedValue @@ -1670,28 +1666,20 @@ public class FuSystem : FuScope matchClass.Add(FuProperty.New(UIntType, FuId.MatchLength, "Length")); matchClass.Add(FuProperty.New(StringStorageType, FuId.MatchValue, "Value")); Add(matchClass); - FuEnum# jsonValueKindEnum = NewEnum(false); - jsonValueKindEnum.IsPublic = true; - jsonValueKindEnum.Id = FuId.JsonValueKindEnum; - jsonValueKindEnum.Name = "JsonValueKind"; - AddEnumValue(jsonValueKindEnum, new FuConst { Visibility = FuVisibility.Public, Id = FuId.JsonValueKindObject, Name = "Object", VisitStatus = FuVisitStatus.Done }); - AddEnumValue(jsonValueKindEnum, new FuConst { Visibility = FuVisibility.Public, Id = FuId.JsonValueKindArray, Name = "Array", VisitStatus = FuVisitStatus.Done }); - AddEnumValue(jsonValueKindEnum, new FuConst { Visibility = FuVisibility.Public, Id = FuId.JsonValueKindString, Name = "String", VisitStatus = FuVisitStatus.Done }); - AddEnumValue(jsonValueKindEnum, new FuConst { Visibility = FuVisibility.Public, Id = FuId.JsonValueKindNumber, Name = "Number", VisitStatus = FuVisitStatus.Done }); - AddEnumValue(jsonValueKindEnum, new FuConst { Visibility = FuVisibility.Public, Id = FuId.JsonValueKindTrue, Name = "True", VisitStatus = FuVisitStatus.Done }); - AddEnumValue(jsonValueKindEnum, new FuConst { Visibility = FuVisibility.Public, Id = FuId.JsonValueKindFalse, Name = "False", VisitStatus = FuVisitStatus.Done }); - AddEnumValue(jsonValueKindEnum, new FuConst { Visibility = FuVisibility.Public, Id = FuId.JsonValueKindNull, Name = "Null", VisitStatus = FuVisitStatus.Done }); - Add(jsonValueKindEnum); FuClass# jsonElementClass = FuClass.New(FuCallType.Sealed, FuId.JsonElementClass, "JsonElement"); - jsonElementClass.Add(FuMethod.New(null, FuVisibility.Public, FuCallType.Normal, VoidType, FuId.JsonElementParse, "Parse", true, FuVar.New(StringPtrType, "value"))); - jsonElementClass.Add(FuMethod.New(null, FuVisibility.Public, FuCallType.Normal, BoolType, FuId.JsonElementTryParse, "TryParse", true, FuVar.New(StringPtrType, "value"))); FuDynamicPtrType# jsonElementPtr = new FuDynamicPtrType { Class = jsonElementClass }; + jsonElementClass.Add(FuMethod.New(null, FuVisibility.Public, FuCallType.Static, jsonElementPtr, FuId.JsonElementParse, "Parse", false, FuVar.New(StringPtrType, "value"))); + jsonElementClass.Add(FuMethod.New(null, FuVisibility.Public, FuCallType.Normal, BoolType, FuId.JsonElementIsObject, "IsObject", false)); + jsonElementClass.Add(FuMethod.New(null, FuVisibility.Public, FuCallType.Normal, BoolType, FuId.JsonElementIsArray, "IsArray", false)); + jsonElementClass.Add(FuMethod.New(null, FuVisibility.Public, FuCallType.Normal, BoolType, FuId.JsonElementIsString, "IsString", false)); + jsonElementClass.Add(FuMethod.New(null, FuVisibility.Public, FuCallType.Normal, BoolType, FuId.JsonElementIsNumber, "IsNumber", false)); + jsonElementClass.Add(FuMethod.New(null, FuVisibility.Public, FuCallType.Normal, BoolType, FuId.JsonElementIsBoolean, "IsBoolean", false)); + jsonElementClass.Add(FuMethod.New(null, FuVisibility.Public, FuCallType.Normal, BoolType, FuId.JsonElementIsNull, "IsNull", false)); jsonElementClass.Add(FuMethod.New(null, FuVisibility.Public, FuCallType.Normal, new FuClassType { Class = dictionaryClass, TypeArg0 = StringStorageType, TypeArg1 = jsonElementPtr }, FuId.JsonElementGetObject, "GetObject", false)); jsonElementClass.Add(FuMethod.New(null, FuVisibility.Public, FuCallType.Normal, new FuClassType { Class = listClass, TypeArg0 = jsonElementPtr }, FuId.JsonElementGetArray, "GetArray", false)); jsonElementClass.Add(FuMethod.New(null, FuVisibility.Public, FuCallType.Normal, StringPtrType, FuId.JsonElementGetString, "GetString", false)); jsonElementClass.Add(FuMethod.New(null, FuVisibility.Public, FuCallType.Normal, DoubleType, FuId.JsonElementGetDouble, "GetDouble", false)); jsonElementClass.Add(FuMethod.New(null, FuVisibility.Public, FuCallType.Normal, BoolType, FuId.JsonElementGetBoolean, "GetBoolean", false)); - jsonElementClass.Add(FuProperty.New(jsonValueKindEnum, FuId.JsonElementValueKind, "ValueKind")); Add(jsonElementClass); FuFloatingType# floatIntType = new FuFloatingType { Id = FuId.FloatIntType, Name = "float" }; @@ -1756,5 +1744,4 @@ public class FuProgram : FuScope internal FuMethod? Main = null; internal SortedDictionary<string(), List<byte>()>() Resources; internal bool RegexOptionsEnum = false; - internal bool JsonValueKindEnum = false; } @@ -438,6 +438,16 @@ public class GenCs : GenTyped } } + void WriteJsonElementIs!(FuExpr obj, string name, FuPriority parent) + { + if (parent > FuPriority.Equality) + WriteChar('('); + WritePostfix(obj, ".ValueKind == JsonValueKind."); + Write(name); + if (parent > FuPriority.Equality) + WriteChar(')'); + } + protected override void WriteCallExpr!(FuExpr? obj, FuMethod method, List<FuExpr#> args, FuPriority parent) { switch (method.Id) { @@ -664,11 +674,33 @@ public class GenCs : GenTyped Write("].Value"); break; case FuId.JsonElementParse: - obj.Accept(this, FuPriority.Assign); - Write(" = JsonDocument.Parse("); + Write("JsonDocument.Parse("); args[0].Accept(this, FuPriority.Argument); Write(").RootElement"); break; + case FuId.JsonElementIsObject: + WriteJsonElementIs(obj, "Object", parent); + break; + case FuId.JsonElementIsArray: + WriteJsonElementIs(obj, "Array", parent); + break; + case FuId.JsonElementIsString: + WriteJsonElementIs(obj, "String", parent); + break; + case FuId.JsonElementIsNumber: + WriteJsonElementIs(obj, "Number", parent); + break; + case FuId.JsonElementIsBoolean: + if (parent > FuPriority.CondOr) + WriteChar('('); + WritePostfix(obj, ".ValueKind == JsonValueKind.True || "); + WritePostfix(obj, ".ValueKind == JsonValueKind.False"); // FIXME: side effect + if (parent > FuPriority.CondOr) + WriteChar(')'); + break; + case FuId.JsonElementIsNull: + WriteJsonElementIs(obj, "Null", parent); + break; case FuId.JsonElementGetObject: Include("System.Linq"); WritePostfix(obj, ".EnumerateObject().ToDictionary(p => p.Name, p => p.Value)"); @@ -490,12 +490,7 @@ public class GenD : GenCCppD } break; default: - if (type.Id == FuId.JsonValueKindEnum) { - Include("std.json"); - Write("JSONType"); - } - else - Write(type.Name); + Write(type.Name); break; } } @@ -698,30 +693,6 @@ public class GenD : GenCCppD case FuId.MatchValue: WritePostfix(expr.Left, ".hit"); break; - case FuId.JsonElementValueKind: - WritePostfix(expr.Left, ".type"); - break; - case FuId.JsonValueKindObject: - Write("JSONType.object"); - break; - case FuId.JsonValueKindArray: - Write("JSONType.array"); - break; - case FuId.JsonValueKindString: - Write("JSONType.string"); - break; - case FuId.JsonValueKindNumber: - Write("JSONType.float_"); - break; - case FuId.JsonValueKindTrue: - Write("JSONType.true_"); - break; - case FuId.JsonValueKindFalse: - Write("JSONType.false_"); - break; - case FuId.JsonValueKindNull: - Write("JSONType.null_"); - break; case FuId.MathNaN: Write("double.nan"); break; @@ -783,6 +754,16 @@ public class GenD : GenCCppD WriteChar(')'); } + void WriteJsonElementIs!(FuExpr obj, string name, FuPriority parent) + { + if (parent > FuPriority.Equality) + WriteChar('('); + WritePostfix(obj, ".type == JSONType."); + Write(name); + if (parent > FuPriority.Equality) + WriteChar(')'); + } + protected override void WriteCallExpr!(FuExpr? obj, FuMethod method, List<FuExpr#> args, FuPriority parent) { switch (method.Id) { @@ -1122,8 +1103,30 @@ public class GenD : GenCCppD WriteIndexing(obj, args[0]); break; case FuId.JsonElementParse: - obj.Accept(this, FuPriority.Assign); - WriteCall(" = parseJSON", args[0]); + WriteCall("parseJSON", args[0]); + break; + case FuId.JsonElementIsObject: + WriteJsonElementIs(obj, "object", parent); + break; + case FuId.JsonElementIsArray: + WriteJsonElementIs(obj, "array", parent); + break; + case FuId.JsonElementIsString: + WriteJsonElementIs(obj, "string", parent); + break; + case FuId.JsonElementIsNumber: + WriteJsonElementIs(obj, "float_", parent); + break; + case FuId.JsonElementIsBoolean: + if (parent > FuPriority.CondOr) + WriteChar('('); + WritePostfix(obj, ".type == JSONType.true_ || "); + WritePostfix(obj, ".type == JSONType.false_"); // FIXME: side effect + if (parent > FuPriority.CondOr) + WriteChar(')'); + break; + case FuId.JsonElementIsNull: + WriteJsonElementIs(obj, "null_", parent); break; case FuId.JsonElementGetObject: WritePostfix(obj, ".object"); @@ -406,9 +406,6 @@ public class GenJsNoModule : GenBase case FuId.MatchValue: WritePostfix(expr.Left, "[0]"); break; - case FuId.JsonElementValueKind: - WriteCall("JsonValueKind.get", expr.Left); - break; case FuId.MathNaN: Write("NaN"); break; @@ -506,6 +503,19 @@ public class GenJsNoModule : GenBase } } + void WriteTypeofEquals!(FuExpr obj, string name, FuPriority parent) + { + if (parent > FuPriority.Equality) + WriteChar('('); + Write("typeof("); + obj.Accept(this, FuPriority.Argument); + Write(") == \""); + Write(name); + WriteChar('"'); + if (parent > FuPriority.Equality) + WriteChar(')'); + } + static bool HasLong(List<FuExpr#> args) => args.Any(arg => arg.Type.Id == FuId.LongType); void WriteMathMaxMin!(FuMethod method, string name, int op, List<FuExpr#> args) @@ -851,8 +861,34 @@ public class GenJsNoModule : GenBase WriteIndexing(obj, args[0]); break; case FuId.JsonElementParse: - obj.Accept(this, FuPriority.Assign); - WriteCall(" = JSON.parse", args[0]); + WriteCall("JSON.parse", args[0]); + break; + case FuId.JsonElementIsObject: + if (parent > FuPriority.Equality) + WriteChar('('); + WritePostfix(obj, "?.constructor == Object"); + if (parent > FuPriority.Equality) + WriteChar(')'); + break; + case FuId.JsonElementIsArray: + WriteCall("Array.isArray", obj); + break; + case FuId.JsonElementIsString: + WriteTypeofEquals(obj, "string", parent); + break; + case FuId.JsonElementIsNumber: + WriteTypeofEquals(obj, "number", parent); + break; + case FuId.JsonElementIsBoolean: + WriteTypeofEquals(obj, "boolean", parent); + break; + case FuId.JsonElementIsNull: + if (parent > FuPriority.Equality) + WriteChar('('); + obj.Accept(this, FuPriority.Equality); + Write(" === null"); + if (parent > FuPriority.Equality) + WriteChar(')'); break; case FuId.JsonElementGetObject: case FuId.JsonElementGetArray: @@ -1332,33 +1368,6 @@ public class GenJsNoModule : GenBase protected void WriteLib!(FuProgram program) { - if (program.JsonValueKindEnum) { - WriteNewLine(); - Write("const JsonValueKind = "); - OpenBlock(); - WriteLine("OBJECT : 1,"); - WriteLine("ARRAY : 2,"); - WriteLine("STRING : 3,"); - WriteLine("NUMBER : 4,"); - WriteLine("TRUE : 5,"); - WriteLine("FALSE : 6,"); - WriteLine("NULL : 7,"); - Write("get : e => "); - OpenBlock(); - Write("switch (typeof(e)) "); - OpenBlock(); - WriteLine("case \"string\":"); - WriteLine("\treturn JsonValueKind.STRING;"); - WriteLine("case \"number\":"); - WriteLine("\treturn JsonValueKind.NUMBER;"); - WriteLine("case \"boolean\":"); - WriteLine("\treturn e ? JsonValueKind.TRUE : JsonValueKind.FALSE;"); - WriteLine("default:"); - WriteLine("\treturn Array.isArray(e) ? JsonValueKind.ARRAY: e === null ? JsonValueKind.NULL : JsonValueKind.OBJECT;"); - CloseBlock(); - CloseBlock(); - CloseBlock(); - } if (this.StringWriter) { WriteNewLine(); WriteLine("class StringWriter"); @@ -484,9 +484,6 @@ public class GenPy : GenPySwift case FuId.OrderedDictionaryCount: WriteStringLength(expr.Left); break; - case FuId.JsonElementValueKind: - WriteCall("JsonValueKind.get", expr.Left); - break; case FuId.MathNaN: Include("math"); Write("math.nan"); @@ -795,6 +792,15 @@ public class GenPy : GenPySwift WriteChar(')'); } + void WriteJsonElementIs!(FuExpr obj, string name) + { + Write("isinstance("); + obj.Accept(this, FuPriority.Argument); + Write(", "); + Write(name); + WriteChar(')'); + } + protected override void WriteCallExpr!(FuExpr? obj, FuMethod method, List<FuExpr#> args, FuPriority parent) { switch (method.Id) { @@ -1066,8 +1072,30 @@ public class GenPy : GenPySwift break; case FuId.JsonElementParse: Include("json"); - obj.Accept(this, FuPriority.Assign); - WriteCall(" = json.loads", args[0]); + WriteCall("json.loads", args[0]); + break; + case FuId.JsonElementIsObject: + WriteJsonElementIs(obj, "dict"); + break; + case FuId.JsonElementIsArray: + WriteJsonElementIs(obj, "list"); + break; + case FuId.JsonElementIsString: + WriteJsonElementIs(obj, "str"); + break; + case FuId.JsonElementIsNumber: + WriteJsonElementIs(obj, "float"); + break; + case FuId.JsonElementIsBoolean: + WriteJsonElementIs(obj, "bool"); + break; + case FuId.JsonElementIsNull: + if (parent > FuPriority.Equality) + WriteChar('('); + obj.Accept(this, FuPriority.Equality); + Write(" is None"); + if (parent > FuPriority.Equality) + WriteChar(')'); break; case FuId.JsonElementGetObject: case FuId.JsonElementGetArray: @@ -1590,41 +1618,6 @@ public class GenPy : GenPySwift this.WrittenTypes.Clear(); this.SwitchBreak = false; OpenStringWriter(); - if (program.JsonValueKindEnum) { - WriteNewLine(); - Include("enum"); - Write("class JsonValueKind(enum.Enum)"); - OpenChild(); - WriteLine("OBJECT = 1"); - WriteLine("ARRAY = 2"); - WriteLine("STRING = 3"); - WriteLine("NUMBER = 4"); - WriteLine("TRUE = 5"); - WriteLine("FALSE = 6"); - WriteLine("NULL = 7"); - WriteLine("@staticmethod"); - Write("def get(e)"); - OpenChild(); - Write("match e"); - OpenChild(); - WriteLine("case dict():"); - WriteLine("\treturn JsonValueKind.OBJECT"); - WriteLine("case list():"); - WriteLine("\treturn JsonValueKind.ARRAY"); - WriteLine("case str():"); - WriteLine("\treturn JsonValueKind.STRING"); - WriteLine("case float():"); - WriteLine("\treturn JsonValueKind.NUMBER"); - WriteLine("case True:"); - WriteLine("\treturn JsonValueKind.TRUE"); - WriteLine("case False:"); - WriteLine("\treturn JsonValueKind.FALSE"); - WriteLine("case None:"); - WriteLine("\treturn JsonValueKind.NULL"); - CloseChild(); - CloseChild(); - CloseChild(); - } WriteTypes(program); CreateOutputFile(); WriteTopLevelNatives(program); @@ -234,8 +234,6 @@ public class FuSema } else if (symbol.Symbol.Id == FuId.RegexOptionsEnum) this.Program.RegexOptionsEnum = true; - else if (symbol.Symbol.Id == FuId.JsonValueKindEnum) - this.Program.JsonValueKindEnum = true; } return resolved; } @@ -1962,7 +1962,7 @@ bool FuFloatingType::isAssignableFrom(const FuType * right) const bool FuNamedValue::isAssignableStorage() const { const FuStorageType * storage; - return (storage = dynamic_cast<const FuStorageType *>(this->type.get())) && !dynamic_cast<const FuArrayStorageType *>(this->type.get()) && (dynamic_cast<const FuLiteralNull *>(this->value.get()) || storage->class_->id == FuId::jsonElementClass); + return (storage = dynamic_cast<const FuStorageType *>(this->type.get())) && !dynamic_cast<const FuArrayStorageType *>(this->type.get()) && dynamic_cast<const FuLiteralNull *>(this->value.get()); } FuMember::FuMember() { @@ -2593,71 +2593,28 @@ FuSystem::FuSystem() matchClass->add(FuProperty::new_(this->uIntType, FuId::matchLength, "Length")); matchClass->add(FuProperty::new_(this->stringStorageType, FuId::matchValue, "Value")); add(matchClass); - std::shared_ptr<FuEnum> jsonValueKindEnum = newEnum(false); - jsonValueKindEnum->isPublic = true; - jsonValueKindEnum->id = FuId::jsonValueKindEnum; - jsonValueKindEnum->name = "JsonValueKind"; - std::shared_ptr<FuConst> futemp9 = std::make_shared<FuConst>(); - futemp9->visibility = FuVisibility::public_; - futemp9->id = FuId::jsonValueKindObject; - futemp9->name = "Object"; - futemp9->visitStatus = FuVisitStatus::done; - addEnumValue(jsonValueKindEnum, futemp9); - std::shared_ptr<FuConst> futemp10 = std::make_shared<FuConst>(); - futemp10->visibility = FuVisibility::public_; - futemp10->id = FuId::jsonValueKindArray; - futemp10->name = "Array"; - futemp10->visitStatus = FuVisitStatus::done; - addEnumValue(jsonValueKindEnum, futemp10); - std::shared_ptr<FuConst> futemp11 = std::make_shared<FuConst>(); - futemp11->visibility = FuVisibility::public_; - futemp11->id = FuId::jsonValueKindString; - futemp11->name = "String"; - futemp11->visitStatus = FuVisitStatus::done; - addEnumValue(jsonValueKindEnum, futemp11); - std::shared_ptr<FuConst> futemp12 = std::make_shared<FuConst>(); - futemp12->visibility = FuVisibility::public_; - futemp12->id = FuId::jsonValueKindNumber; - futemp12->name = "Number"; - futemp12->visitStatus = FuVisitStatus::done; - addEnumValue(jsonValueKindEnum, futemp12); - std::shared_ptr<FuConst> futemp13 = std::make_shared<FuConst>(); - futemp13->visibility = FuVisibility::public_; - futemp13->id = FuId::jsonValueKindTrue; - futemp13->name = "True"; - futemp13->visitStatus = FuVisitStatus::done; - addEnumValue(jsonValueKindEnum, futemp13); - std::shared_ptr<FuConst> futemp14 = std::make_shared<FuConst>(); - futemp14->visibility = FuVisibility::public_; - futemp14->id = FuId::jsonValueKindFalse; - futemp14->name = "False"; - futemp14->visitStatus = FuVisitStatus::done; - addEnumValue(jsonValueKindEnum, futemp14); - std::shared_ptr<FuConst> futemp15 = std::make_shared<FuConst>(); - futemp15->visibility = FuVisibility::public_; - futemp15->id = FuId::jsonValueKindNull; - futemp15->name = "Null"; - futemp15->visitStatus = FuVisitStatus::done; - addEnumValue(jsonValueKindEnum, futemp15); - add(jsonValueKindEnum); std::shared_ptr<FuClass> jsonElementClass = FuClass::new_(FuCallType::sealed, FuId::jsonElementClass, "JsonElement"); - jsonElementClass->add(FuMethod::new_(nullptr, FuVisibility::public_, FuCallType::normal, this->voidType, FuId::jsonElementParse, "Parse", true, FuVar::new_(this->stringPtrType, "value"))); - jsonElementClass->add(FuMethod::new_(nullptr, FuVisibility::public_, FuCallType::normal, this->boolType, FuId::jsonElementTryParse, "TryParse", true, FuVar::new_(this->stringPtrType, "value"))); std::shared_ptr<FuDynamicPtrType> jsonElementPtr = std::make_shared<FuDynamicPtrType>(); jsonElementPtr->class_ = jsonElementClass.get(); - std::shared_ptr<FuClassType> futemp16 = std::make_shared<FuClassType>(); - futemp16->class_ = dictionaryClass; - futemp16->typeArg0 = this->stringStorageType; - futemp16->typeArg1 = jsonElementPtr; - jsonElementClass->add(FuMethod::new_(nullptr, FuVisibility::public_, FuCallType::normal, futemp16, FuId::jsonElementGetObject, "GetObject", false)); - std::shared_ptr<FuClassType> futemp17 = std::make_shared<FuClassType>(); - futemp17->class_ = listClass; - futemp17->typeArg0 = jsonElementPtr; - jsonElementClass->add(FuMethod::new_(nullptr, FuVisibility::public_, FuCallType::normal, futemp17, FuId::jsonElementGetArray, "GetArray", false)); + jsonElementClass->add(FuMethod::new_(nullptr, FuVisibility::public_, FuCallType::static_, jsonElementPtr, FuId::jsonElementParse, "Parse", false, FuVar::new_(this->stringPtrType, "value"))); + jsonElementClass->add(FuMethod::new_(nullptr, FuVisibility::public_, FuCallType::normal, this->boolType, FuId::jsonElementIsObject, "IsObject", false)); + jsonElementClass->add(FuMethod::new_(nullptr, FuVisibility::public_, FuCallType::normal, this->boolType, FuId::jsonElementIsArray, "IsArray", false)); + jsonElementClass->add(FuMethod::new_(nullptr, FuVisibility::public_, FuCallType::normal, this->boolType, FuId::jsonElementIsString, "IsString", false)); + jsonElementClass->add(FuMethod::new_(nullptr, FuVisibility::public_, FuCallType::normal, this->boolType, FuId::jsonElementIsNumber, "IsNumber", false)); + jsonElementClass->add(FuMethod::new_(nullptr, FuVisibility::public_, FuCallType::normal, this->boolType, FuId::jsonElementIsBoolean, "IsBoolean", false)); + jsonElementClass->add(FuMethod::new_(nullptr, FuVisibility::public_, FuCallType::normal, this->boolType, FuId::jsonElementIsNull, "IsNull", false)); + std::shared_ptr<FuClassType> futemp9 = std::make_shared<FuClassType>(); + futemp9->class_ = dictionaryClass; + futemp9->typeArg0 = this->stringStorageType; + futemp9->typeArg1 = jsonElementPtr; + jsonElementClass->add(FuMethod::new_(nullptr, FuVisibility::public_, FuCallType::normal, futemp9, FuId::jsonElementGetObject, "GetObject", false)); + std::shared_ptr<FuClassType> futemp10 = std::make_shared<FuClassType>(); + futemp10->class_ = listClass; + futemp10->typeArg0 = jsonElementPtr; + jsonElementClass->add(FuMethod::new_(nullptr, FuVisibility::public_, FuCallType::normal, futemp10, FuId::jsonElementGetArray, "GetArray", false)); jsonElementClass->add(FuMethod::new_(nullptr, FuVisibility::public_, FuCallType::normal, this->stringPtrType, FuId::jsonElementGetString, "GetString", false)); jsonElementClass->add(FuMethod::new_(nullptr, FuVisibility::public_, FuCallType::normal, this->doubleType, FuId::jsonElementGetDouble, "GetDouble", false)); jsonElementClass->add(FuMethod::new_(nullptr, FuVisibility::public_, FuCallType::normal, this->boolType, FuId::jsonElementGetBoolean, "GetBoolean", false)); - jsonElementClass->add(FuProperty::new_(jsonValueKindEnum, FuId::jsonElementValueKind, "ValueKind")); add(jsonElementClass); std::shared_ptr<FuFloatingType> floatIntType = std::make_shared<FuFloatingType>(); floatIntType->id = FuId::floatIntType; @@ -4304,8 +4261,6 @@ std::shared_ptr<FuExpr> FuSema::visitSymbolReference(std::shared_ptr<FuSymbolRef } else if (symbol->symbol->id == FuId::regexOptionsEnum) this->program->regexOptionsEnum = true; - else if (symbol->symbol->id == FuId::jsonValueKindEnum) - this->program->jsonValueKindEnum = true; } return resolved; } @@ -15395,6 +15350,16 @@ void GenCs::visitSymbolReference(const FuSymbolReference * expr, FuPriority pare } } +void GenCs::writeJsonElementIs(const FuExpr * obj, std::string_view name, FuPriority parent) +{ + if (parent > FuPriority::equality) + writeChar('('); + writePostfix(obj, ".ValueKind == JsonValueKind."); + write(name); + if (parent > FuPriority::equality) + writeChar(')'); +} + void GenCs::writeCallExpr(const FuExpr * obj, const FuMethod * method, const std::vector<std::shared_ptr<FuExpr>> * args, FuPriority parent) { switch (method->id) { @@ -15629,11 +15594,33 @@ void GenCs::writeCallExpr(const FuExpr * obj, const FuMethod * method, const std write("].Value"); break; case FuId::jsonElementParse: - obj->accept(this, FuPriority::assign); - write(" = JsonDocument.Parse("); + write("JsonDocument.Parse("); (*args)[0]->accept(this, FuPriority::argument); write(").RootElement"); break; + case FuId::jsonElementIsObject: + writeJsonElementIs(obj, "Object", parent); + break; + case FuId::jsonElementIsArray: + writeJsonElementIs(obj, "Array", parent); + break; + case FuId::jsonElementIsString: + writeJsonElementIs(obj, "String", parent); + break; + case FuId::jsonElementIsNumber: + writeJsonElementIs(obj, "Number", parent); + break; + case FuId::jsonElementIsBoolean: + if (parent > FuPriority::condOr) + writeChar('('); + writePostfix(obj, ".ValueKind == JsonValueKind.True || "); + writePostfix(obj, ".ValueKind == JsonValueKind.False"); + if (parent > FuPriority::condOr) + writeChar(')'); + break; + case FuId::jsonElementIsNull: + writeJsonElementIs(obj, "Null", parent); + break; case FuId::jsonElementGetObject: include("System.Linq"); writePostfix(obj, ".EnumerateObject().ToDictionary(p => p.Name, p => p.Value)"); @@ -16239,14 +16226,8 @@ void GenD::writeType(const FuType * type, bool promote) break; } } - else { - if (type->id == FuId::jsonValueKindEnum) { - include("std.json"); - write("JSONType"); - } - else - write(type->name); - } + else + write(type->name); } void GenD::writeTypeAndName(const FuNamedValue * value) @@ -16447,30 +16428,6 @@ void GenD::visitSymbolReference(const FuSymbolReference * expr, FuPriority paren case FuId::matchValue: writePostfix(expr->left.get(), ".hit"); break; - case FuId::jsonElementValueKind: - writePostfix(expr->left.get(), ".type"); - break; - case FuId::jsonValueKindObject: - write("JSONType.object"); - break; - case FuId::jsonValueKindArray: - write("JSONType.array"); - break; - case FuId::jsonValueKindString: - write("JSONType.string"); - break; - case FuId::jsonValueKindNumber: - write("JSONType.float_"); - break; - case FuId::jsonValueKindTrue: - write("JSONType.true_"); - break; - case FuId::jsonValueKindFalse: - write("JSONType.false_"); - break; - case FuId::jsonValueKindNull: - write("JSONType.null_"); - break; case FuId::mathNaN: write("double.nan"); break; @@ -16529,6 +16486,16 @@ void GenD::writeInsertedArg(const FuType * type, const std::vector<std::shared_p writeChar(')'); } +void GenD::writeJsonElementIs(const FuExpr * obj, std::string_view name, FuPriority parent) +{ + if (parent > FuPriority::equality) + writeChar('('); + writePostfix(obj, ".type == JSONType."); + write(name); + if (parent > FuPriority::equality) + writeChar(')'); +} + void GenD::writeCallExpr(const FuExpr * obj, const FuMethod * method, const std::vector<std::shared_ptr<FuExpr>> * args, FuPriority parent) { switch (method->id) { @@ -16868,8 +16835,30 @@ void GenD::writeCallExpr(const FuExpr * obj, const FuMethod * method, const std: writeIndexing(obj, (*args)[0].get()); break; case FuId::jsonElementParse: - obj->accept(this, FuPriority::assign); - writeCall(" = parseJSON", (*args)[0].get()); + writeCall("parseJSON", (*args)[0].get()); + break; + case FuId::jsonElementIsObject: + writeJsonElementIs(obj, "object", parent); + break; + case FuId::jsonElementIsArray: + writeJsonElementIs(obj, "array", parent); + break; + case FuId::jsonElementIsString: + writeJsonElementIs(obj, "string", parent); + break; + case FuId::jsonElementIsNumber: + writeJsonElementIs(obj, "float_", parent); + break; + case FuId::jsonElementIsBoolean: + if (parent > FuPriority::condOr) + writeChar('('); + writePostfix(obj, ".type == JSONType.true_ || "); + writePostfix(obj, ".type == JSONType.false_"); + if (parent > FuPriority::condOr) + writeChar(')'); + break; + case FuId::jsonElementIsNull: + writeJsonElementIs(obj, "null_", parent); break; case FuId::jsonElementGetObject: writePostfix(obj, ".object"); @@ -19053,9 +19042,6 @@ void GenJsNoModule::visitSymbolReference(const FuSymbolReference * expr, FuPrior case FuId::matchValue: writePostfix(expr->left.get(), "[0]"); break; - case FuId::jsonElementValueKind: - writeCall("JsonValueKind.get", expr->left.get()); - break; case FuId::mathNaN: write("NaN"); break; @@ -19153,6 +19139,19 @@ void GenJsNoModule::writeNewRegex(const std::vector<std::shared_ptr<FuExpr>> * a } } +void GenJsNoModule::writeTypeofEquals(const FuExpr * obj, std::string_view name, FuPriority parent) +{ + if (parent > FuPriority::equality) + writeChar('('); + write("typeof("); + obj->accept(this, FuPriority::argument); + write(") == \""); + write(name); + writeChar('"'); + if (parent > FuPriority::equality) + writeChar(')'); +} + bool GenJsNoModule::hasLong(const std::vector<std::shared_ptr<FuExpr>> * args) { return std::any_of(args->begin(), args->end(), [](const std::shared_ptr<FuExpr> &arg) { return arg->type->id == FuId::longType; }); @@ -19503,8 +19502,34 @@ void GenJsNoModule::writeCallExpr(const FuExpr * obj, const FuMethod * method, c writeIndexing(obj, (*args)[0].get()); break; case FuId::jsonElementParse: - obj->accept(this, FuPriority::assign); - writeCall(" = JSON.parse", (*args)[0].get()); + writeCall("JSON.parse", (*args)[0].get()); + break; + case FuId::jsonElementIsObject: + if (parent > FuPriority::equality) + writeChar('('); + writePostfix(obj, "?.constructor == Object"); + if (parent > FuPriority::equality) + writeChar(')'); + break; + case FuId::jsonElementIsArray: + writeCall("Array.isArray", obj); + break; + case FuId::jsonElementIsString: + writeTypeofEquals(obj, "string", parent); + break; + case FuId::jsonElementIsNumber: + writeTypeofEquals(obj, "number", parent); + break; + case FuId::jsonElementIsBoolean: + writeTypeofEquals(obj, "boolean", parent); + break; + case FuId::jsonElementIsNull: + if (parent > FuPriority::equality) + writeChar('('); + obj->accept(this, FuPriority::equality); + write(" === null"); + if (parent > FuPriority::equality) + writeChar(')'); break; case FuId::jsonElementGetObject: case FuId::jsonElementGetArray: @@ -19970,33 +19995,6 @@ void GenJsNoModule::writeMain(const FuMethod * main) void GenJsNoModule::writeLib(const FuProgram * program) { - if (program->jsonValueKindEnum) { - writeNewLine(); - write("const JsonValueKind = "); - openBlock(); - writeLine("OBJECT : 1,"); - writeLine("ARRAY : 2,"); - writeLine("STRING : 3,"); - writeLine("NUMBER : 4,"); - writeLine("TRUE : 5,"); - writeLine("FALSE : 6,"); - writeLine("NULL : 7,"); - write("get : e => "); - openBlock(); - write("switch (typeof(e)) "); - openBlock(); - writeLine("case \"string\":"); - writeLine("\treturn JsonValueKind.STRING;"); - writeLine("case \"number\":"); - writeLine("\treturn JsonValueKind.NUMBER;"); - writeLine("case \"boolean\":"); - writeLine("\treturn e ? JsonValueKind.TRUE : JsonValueKind.FALSE;"); - writeLine("default:"); - writeLine("\treturn Array.isArray(e) ? JsonValueKind.ARRAY: e === null ? JsonValueKind.NULL : JsonValueKind.OBJECT;"); - closeBlock(); - closeBlock(); - closeBlock(); - } if (this->stringWriter) { writeNewLine(); writeLine("class StringWriter"); @@ -22823,9 +22821,6 @@ void GenPy::visitSymbolReference(const FuSymbolReference * expr, FuPriority pare case FuId::orderedDictionaryCount: writeStringLength(expr->left.get()); break; - case FuId::jsonElementValueKind: - writeCall("JsonValueKind.get", expr->left.get()); - break; case FuId::mathNaN: include("math"); write("math.nan"); @@ -23132,6 +23127,15 @@ void GenPy::writeRegexSearch(const std::vector<std::shared_ptr<FuExpr>> * args) writeChar(')'); } +void GenPy::writeJsonElementIs(const FuExpr * obj, std::string_view name) +{ + write("isinstance("); + obj->accept(this, FuPriority::argument); + write(", "); + write(name); + writeChar(')'); +} + void GenPy::writeCallExpr(const FuExpr * obj, const FuMethod * method, const std::vector<std::shared_ptr<FuExpr>> * args, FuPriority parent) { switch (method->id) { @@ -23406,8 +23410,30 @@ void GenPy::writeCallExpr(const FuExpr * obj, const FuMethod * method, const std break; case FuId::jsonElementParse: include("json"); - obj->accept(this, FuPriority::assign); - writeCall(" = json.loads", (*args)[0].get()); + writeCall("json.loads", (*args)[0].get()); + break; + case FuId::jsonElementIsObject: + writeJsonElementIs(obj, "dict"); + break; + case FuId::jsonElementIsArray: + writeJsonElementIs(obj, "list"); + break; + case FuId::jsonElementIsString: + writeJsonElementIs(obj, "str"); + break; + case FuId::jsonElementIsNumber: + writeJsonElementIs(obj, "float"); + break; + case FuId::jsonElementIsBoolean: + writeJsonElementIs(obj, "bool"); + break; + case FuId::jsonElementIsNull: + if (parent > FuPriority::equality) + writeChar('('); + obj->accept(this, FuPriority::equality); + write(" is None"); + if (parent > FuPriority::equality) + writeChar(')'); break; case FuId::jsonElementGetObject: case FuId::jsonElementGetArray: @@ -23932,41 +23958,6 @@ void GenPy::writeProgram(const FuProgram * program) this->writtenTypes.clear(); this->switchBreak = false; openStringWriter(); - if (program->jsonValueKindEnum) { - writeNewLine(); - include("enum"); - write("class JsonValueKind(enum.Enum)"); - openChild(); - writeLine("OBJECT = 1"); - writeLine("ARRAY = 2"); - writeLine("STRING = 3"); - writeLine("NUMBER = 4"); - writeLine("TRUE = 5"); - writeLine("FALSE = 6"); - writeLine("NULL = 7"); - writeLine("@staticmethod"); - write("def get(e)"); - openChild(); - write("match e"); - openChild(); - writeLine("case dict():"); - writeLine("\treturn JsonValueKind.OBJECT"); - writeLine("case list():"); - writeLine("\treturn JsonValueKind.ARRAY"); - writeLine("case str():"); - writeLine("\treturn JsonValueKind.STRING"); - writeLine("case float():"); - writeLine("\treturn JsonValueKind.NUMBER"); - writeLine("case True:"); - writeLine("\treturn JsonValueKind.TRUE"); - writeLine("case False:"); - writeLine("\treturn JsonValueKind.FALSE"); - writeLine("case None:"); - writeLine("\treturn JsonValueKind.NULL"); - closeChild(); - closeChild(); - closeChild(); - } writeTypes(program); createOutputFile(); writeTopLevelNatives(program); @@ -1316,7 +1316,6 @@ namespace Fusion RegexOptionsEnum, RegexClass, MatchClass, - JsonValueKindEnum, JsonElementClass, LockClass, StringLength, @@ -1328,14 +1327,6 @@ namespace Fusion MatchEnd, MatchLength, MatchValue, - JsonValueKindObject, - JsonValueKindArray, - JsonValueKindString, - JsonValueKindNumber, - JsonValueKindTrue, - JsonValueKindFalse, - JsonValueKindNull, - JsonElementValueKind, MathNaN, MathNegativeInfinity, MathPositiveInfinity, @@ -1430,7 +1421,12 @@ namespace Fusion MatchFindRegex, MatchGetCapture, JsonElementParse, - JsonElementTryParse, + JsonElementIsObject, + JsonElementIsArray, + JsonElementIsString, + JsonElementIsNumber, + JsonElementIsBoolean, + JsonElementIsNull, JsonElementGetObject, JsonElementGetArray, JsonElementGetString, @@ -2558,7 +2554,7 @@ namespace Fusion internal FuExpr Value; - public bool IsAssignableStorage() => this.Type is FuStorageType storage && !(this.Type is FuArrayStorageType) && (this.Value is FuLiteralNull || storage.Class.Id == FuId.JsonElementClass); + public bool IsAssignableStorage() => this.Type is FuStorageType storage && !(this.Type is FuArrayStorageType) && this.Value is FuLiteralNull; } public abstract class FuMember : FuNamedValue @@ -3127,28 +3123,20 @@ namespace Fusion matchClass.Add(FuProperty.New(this.UIntType, FuId.MatchLength, "Length")); matchClass.Add(FuProperty.New(this.StringStorageType, FuId.MatchValue, "Value")); Add(matchClass); - FuEnum jsonValueKindEnum = NewEnum(false); - jsonValueKindEnum.IsPublic = true; - jsonValueKindEnum.Id = FuId.JsonValueKindEnum; - jsonValueKindEnum.Name = "JsonValueKind"; - AddEnumValue(jsonValueKindEnum, new FuConst { Visibility = FuVisibility.Public, Id = FuId.JsonValueKindObject, Name = "Object", VisitStatus = FuVisitStatus.Done }); - AddEnumValue(jsonValueKindEnum, new FuConst { Visibility = FuVisibility.Public, Id = FuId.JsonValueKindArray, Name = "Array", VisitStatus = FuVisitStatus.Done }); - AddEnumValue(jsonValueKindEnum, new FuConst { Visibility = FuVisibility.Public, Id = FuId.JsonValueKindString, Name = "String", VisitStatus = FuVisitStatus.Done }); - AddEnumValue(jsonValueKindEnum, new FuConst { Visibility = FuVisibility.Public, Id = FuId.JsonValueKindNumber, Name = "Number", VisitStatus = FuVisitStatus.Done }); - AddEnumValue(jsonValueKindEnum, new FuConst { Visibility = FuVisibility.Public, Id = FuId.JsonValueKindTrue, Name = "True", VisitStatus = FuVisitStatus.Done }); - AddEnumValue(jsonValueKindEnum, new FuConst { Visibility = FuVisibility.Public, Id = FuId.JsonValueKindFalse, Name = "False", VisitStatus = FuVisitStatus.Done }); - AddEnumValue(jsonValueKindEnum, new FuConst { Visibility = FuVisibility.Public, Id = FuId.JsonValueKindNull, Name = "Null", VisitStatus = FuVisitStatus.Done }); - Add(jsonValueKindEnum); FuClass jsonElementClass = FuClass.New(FuCallType.Sealed, FuId.JsonElementClass, "JsonElement"); - jsonElementClass.Add(FuMethod.New(null, FuVisibility.Public, FuCallType.Normal, this.VoidType, FuId.JsonElementParse, "Parse", true, FuVar.New(this.StringPtrType, "value"))); - jsonElementClass.Add(FuMethod.New(null, FuVisibility.Public, FuCallType.Normal, this.BoolType, FuId.JsonElementTryParse, "TryParse", true, FuVar.New(this.StringPtrType, "value"))); FuDynamicPtrType jsonElementPtr = new FuDynamicPtrType { Class = jsonElementClass }; + jsonElementClass.Add(FuMethod.New(null, FuVisibility.Public, FuCallType.Static, jsonElementPtr, FuId.JsonElementParse, "Parse", false, FuVar.New(this.StringPtrType, "value"))); + jsonElementClass.Add(FuMethod.New(null, FuVisibility.Public, FuCallType.Normal, this.BoolType, FuId.JsonElementIsObject, "IsObject", false)); + jsonElementClass.Add(FuMethod.New(null, FuVisibility.Public, FuCallType.Normal, this.BoolType, FuId.JsonElementIsArray, "IsArray", false)); + jsonElementClass.Add(FuMethod.New(null, FuVisibility.Public, FuCallType.Normal, this.BoolType, FuId.JsonElementIsString, "IsString", false)); + jsonElementClass.Add(FuMethod.New(null, FuVisibility.Public, FuCallType.Normal, this.BoolType, FuId.JsonElementIsNumber, "IsNumber", false)); + jsonElementClass.Add(FuMethod.New(null, FuVisibility.Public, FuCallType.Normal, this.BoolType, FuId.JsonElementIsBoolean, "IsBoolean", false)); + jsonElementClass.Add(FuMethod.New(null, FuVisibility.Public, FuCallType.Normal, this.BoolType, FuId.JsonElementIsNull, "IsNull", false)); jsonElementClass.Add(FuMethod.New(null, FuVisibility.Public, FuCallType.Normal, new FuClassType { Class = dictionaryClass, TypeArg0 = this.StringStorageType, TypeArg1 = jsonElementPtr }, FuId.JsonElementGetObject, "GetObject", false)); jsonElementClass.Add(FuMethod.New(null, FuVisibility.Public, FuCallType.Normal, new FuClassType { Class = listClass, TypeArg0 = jsonElementPtr }, FuId.JsonElementGetArray, "GetArray", false)); jsonElementClass.Add(FuMethod.New(null, FuVisibility.Public, FuCallType.Normal, this.StringPtrType, FuId.JsonElementGetString, "GetString", false)); jsonElementClass.Add(FuMethod.New(null, FuVisibility.Public, FuCallType.Normal, this.DoubleType, FuId.JsonElementGetDouble, "GetDouble", false)); jsonElementClass.Add(FuMethod.New(null, FuVisibility.Public, FuCallType.Normal, this.BoolType, FuId.JsonElementGetBoolean, "GetBoolean", false)); - jsonElementClass.Add(FuProperty.New(jsonValueKindEnum, FuId.JsonElementValueKind, "ValueKind")); Add(jsonElementClass); FuFloatingType floatIntType = new FuFloatingType { Id = FuId.FloatIntType, Name = "float" }; FuClass mathClass = FuClass.New(FuCallType.Static, FuId.None, "Math"); @@ -3333,8 +3321,6 @@ namespace Fusion internal readonly SortedDictionary<string, List<byte>> Resources = new SortedDictionary<string, List<byte>>(); internal bool RegexOptionsEnum = false; - - internal bool JsonValueKindEnum = false; } public class FuParser : FuLexer @@ -4600,8 +4586,6 @@ namespace Fusion } else if (symbol.Symbol.Id == FuId.RegexOptionsEnum) this.Program.RegexOptionsEnum = true; - else if (symbol.Symbol.Id == FuId.JsonValueKindEnum) - this.Program.JsonValueKindEnum = true; } return resolved; } @@ -15789,6 +15773,16 @@ namespace Fusion } } + void WriteJsonElementIs(FuExpr obj, string name, FuPriority parent) + { + if (parent > FuPriority.Equality) + WriteChar('('); + WritePostfix(obj, ".ValueKind == JsonValueKind."); + Write(name); + if (parent > FuPriority.Equality) + WriteChar(')'); + } + protected override void WriteCallExpr(FuExpr obj, FuMethod method, List<FuExpr> args, FuPriority parent) { switch (method.Id) { @@ -16014,11 +16008,33 @@ namespace Fusion Write("].Value"); break; case FuId.JsonElementParse: - obj.Accept(this, FuPriority.Assign); - Write(" = JsonDocument.Parse("); + Write("JsonDocument.Parse("); args[0].Accept(this, FuPriority.Argument); Write(").RootElement"); break; + case FuId.JsonElementIsObject: + WriteJsonElementIs(obj, "Object", parent); + break; + case FuId.JsonElementIsArray: + WriteJsonElementIs(obj, "Array", parent); + break; + case FuId.JsonElementIsString: + WriteJsonElementIs(obj, "String", parent); + break; + case FuId.JsonElementIsNumber: + WriteJsonElementIs(obj, "Number", parent); + break; + case FuId.JsonElementIsBoolean: + if (parent > FuPriority.CondOr) + WriteChar('('); + WritePostfix(obj, ".ValueKind == JsonValueKind.True || "); + WritePostfix(obj, ".ValueKind == JsonValueKind.False"); + if (parent > FuPriority.CondOr) + WriteChar(')'); + break; + case FuId.JsonElementIsNull: + WriteJsonElementIs(obj, "Null", parent); + break; case FuId.JsonElementGetObject: Include("System.Linq"); WritePostfix(obj, ".EnumerateObject().ToDictionary(p => p.Name, p => p.Value)"); @@ -16807,12 +16823,7 @@ namespace Fusion } break; default: - if (type.Id == FuId.JsonValueKindEnum) { - Include("std.json"); - Write("JSONType"); - } - else - Write(type.Name); + Write(type.Name); break; } } @@ -17015,30 +17026,6 @@ namespace Fusion case FuId.MatchValue: WritePostfix(expr.Left, ".hit"); break; - case FuId.JsonElementValueKind: - WritePostfix(expr.Left, ".type"); - break; - case FuId.JsonValueKindObject: - Write("JSONType.object"); - break; - case FuId.JsonValueKindArray: - Write("JSONType.array"); - break; - case FuId.JsonValueKindString: - Write("JSONType.string"); - break; - case FuId.JsonValueKindNumber: - Write("JSONType.float_"); - break; - case FuId.JsonValueKindTrue: - Write("JSONType.true_"); - break; - case FuId.JsonValueKindFalse: - Write("JSONType.false_"); - break; - case FuId.JsonValueKindNull: - Write("JSONType.null_"); - break; case FuId.MathNaN: Write("double.nan"); break; @@ -17097,6 +17084,16 @@ namespace Fusion WriteChar(')'); } + void WriteJsonElementIs(FuExpr obj, string name, FuPriority parent) + { + if (parent > FuPriority.Equality) + WriteChar('('); + WritePostfix(obj, ".type == JSONType."); + Write(name); + if (parent > FuPriority.Equality) + WriteChar(')'); + } + protected override void WriteCallExpr(FuExpr obj, FuMethod method, List<FuExpr> args, FuPriority parent) { switch (method.Id) { @@ -17436,8 +17433,30 @@ namespace Fusion WriteIndexing(obj, args[0]); break; case FuId.JsonElementParse: - obj.Accept(this, FuPriority.Assign); - WriteCall(" = parseJSON", args[0]); + WriteCall("parseJSON", args[0]); + break; + case FuId.JsonElementIsObject: + WriteJsonElementIs(obj, "object", parent); + break; + case FuId.JsonElementIsArray: + WriteJsonElementIs(obj, "array", parent); + break; + case FuId.JsonElementIsString: + WriteJsonElementIs(obj, "string", parent); + break; + case FuId.JsonElementIsNumber: + WriteJsonElementIs(obj, "float_", parent); + break; + case FuId.JsonElementIsBoolean: + if (parent > FuPriority.CondOr) + WriteChar('('); + WritePostfix(obj, ".type == JSONType.true_ || "); + WritePostfix(obj, ".type == JSONType.false_"); + if (parent > FuPriority.CondOr) + WriteChar(')'); + break; + case FuId.JsonElementIsNull: + WriteJsonElementIs(obj, "null_", parent); break; case FuId.JsonElementGetObject: WritePostfix(obj, ".object"); @@ -19701,9 +19720,6 @@ namespace Fusion case FuId.MatchValue: WritePostfix(expr.Left, "[0]"); break; - case FuId.JsonElementValueKind: - WriteCall("JsonValueKind.get", expr.Left); - break; case FuId.MathNaN: Write("NaN"); break; @@ -19801,6 +19817,19 @@ namespace Fusion } } + void WriteTypeofEquals(FuExpr obj, string name, FuPriority parent) + { + if (parent > FuPriority.Equality) + WriteChar('('); + Write("typeof("); + obj.Accept(this, FuPriority.Argument); + Write(") == \""); + Write(name); + WriteChar('"'); + if (parent > FuPriority.Equality) + WriteChar(')'); + } + static bool HasLong(List<FuExpr> args) => args.Exists(arg => arg.Type.Id == FuId.LongType); void WriteMathMaxMin(FuMethod method, string name, int op, List<FuExpr> args) @@ -20145,8 +20174,34 @@ namespace Fusion WriteIndexing(obj, args[0]); break; case FuId.JsonElementParse: - obj.Accept(this, FuPriority.Assign); - WriteCall(" = JSON.parse", args[0]); + WriteCall("JSON.parse", args[0]); + break; + case FuId.JsonElementIsObject: + if (parent > FuPriority.Equality) + WriteChar('('); + WritePostfix(obj, "?.constructor == Object"); + if (parent > FuPriority.Equality) + WriteChar(')'); + break; + case FuId.JsonElementIsArray: + WriteCall("Array.isArray", obj); + break; + case FuId.JsonElementIsString: + WriteTypeofEquals(obj, "string", parent); + break; + case FuId.JsonElementIsNumber: + WriteTypeofEquals(obj, "number", parent); + break; + case FuId.JsonElementIsBoolean: + WriteTypeofEquals(obj, "boolean", parent); + break; + case FuId.JsonElementIsNull: + if (parent > FuPriority.Equality) + WriteChar('('); + obj.Accept(this, FuPriority.Equality); + Write(" === null"); + if (parent > FuPriority.Equality) + WriteChar(')'); break; case FuId.JsonElementGetObject: case FuId.JsonElementGetArray: @@ -20622,33 +20677,6 @@ namespace Fusion protected void WriteLib(FuProgram program) { - if (program.JsonValueKindEnum) { - WriteNewLine(); - Write("const JsonValueKind = "); - OpenBlock(); - WriteLine("OBJECT : 1,"); - WriteLine("ARRAY : 2,"); - WriteLine("STRING : 3,"); - WriteLine("NUMBER : 4,"); - WriteLine("TRUE : 5,"); - WriteLine("FALSE : 6,"); - WriteLine("NULL : 7,"); - Write("get : e => "); - OpenBlock(); - Write("switch (typeof(e)) "); - OpenBlock(); - WriteLine("case \"string\":"); - WriteLine("\treturn JsonValueKind.STRING;"); - WriteLine("case \"number\":"); - WriteLine("\treturn JsonValueKind.NUMBER;"); - WriteLine("case \"boolean\":"); - WriteLine("\treturn e ? JsonValueKind.TRUE : JsonValueKind.FALSE;"); - WriteLine("default:"); - WriteLine("\treturn Array.isArray(e) ? JsonValueKind.ARRAY: e === null ? JsonValueKind.NULL : JsonValueKind.OBJECT;"); - CloseBlock(); - CloseBlock(); - CloseBlock(); - } if (this.StringWriter) { WriteNewLine(); WriteLine("class StringWriter"); @@ -23692,9 +23720,6 @@ namespace Fusion case FuId.OrderedDictionaryCount: WriteStringLength(expr.Left); break; - case FuId.JsonElementValueKind: - WriteCall("JsonValueKind.get", expr.Left); - break; case FuId.MathNaN: Include("math"); Write("math.nan"); @@ -23998,6 +24023,15 @@ namespace Fusion WriteChar(')'); } + void WriteJsonElementIs(FuExpr obj, string name) + { + Write("isinstance("); + obj.Accept(this, FuPriority.Argument); + Write(", "); + Write(name); + WriteChar(')'); + } + protected override void WriteCallExpr(FuExpr obj, FuMethod method, List<FuExpr> args, FuPriority parent) { switch (method.Id) { @@ -24269,8 +24303,30 @@ namespace Fusion break; case FuId.JsonElementParse: Include("json"); - obj.Accept(this, FuPriority.Assign); - WriteCall(" = json.loads", args[0]); + WriteCall("json.loads", args[0]); + break; + case FuId.JsonElementIsObject: + WriteJsonElementIs(obj, "dict"); + break; + case FuId.JsonElementIsArray: + WriteJsonElementIs(obj, "list"); + break; + case FuId.JsonElementIsString: + WriteJsonElementIs(obj, "str"); + break; + case FuId.JsonElementIsNumber: + WriteJsonElementIs(obj, "float"); + break; + case FuId.JsonElementIsBoolean: + WriteJsonElementIs(obj, "bool"); + break; + case FuId.JsonElementIsNull: + if (parent > FuPriority.Equality) + WriteChar('('); + obj.Accept(this, FuPriority.Equality); + Write(" is None"); + if (parent > FuPriority.Equality) + WriteChar(')'); break; case FuId.JsonElementGetObject: case FuId.JsonElementGetArray: @@ -24788,41 +24844,6 @@ namespace Fusion this.WrittenTypes.Clear(); this.SwitchBreak = false; OpenStringWriter(); - if (program.JsonValueKindEnum) { - WriteNewLine(); - Include("enum"); - Write("class JsonValueKind(enum.Enum)"); - OpenChild(); - WriteLine("OBJECT = 1"); - WriteLine("ARRAY = 2"); - WriteLine("STRING = 3"); - WriteLine("NUMBER = 4"); - WriteLine("TRUE = 5"); - WriteLine("FALSE = 6"); - WriteLine("NULL = 7"); - WriteLine("@staticmethod"); - Write("def get(e)"); - OpenChild(); - Write("match e"); - OpenChild(); - WriteLine("case dict():"); - WriteLine("\treturn JsonValueKind.OBJECT"); - WriteLine("case list():"); - WriteLine("\treturn JsonValueKind.ARRAY"); - WriteLine("case str():"); - WriteLine("\treturn JsonValueKind.STRING"); - WriteLine("case float():"); - WriteLine("\treturn JsonValueKind.NUMBER"); - WriteLine("case True:"); - WriteLine("\treturn JsonValueKind.TRUE"); - WriteLine("case False:"); - WriteLine("\treturn JsonValueKind.FALSE"); - WriteLine("case None:"); - WriteLine("\treturn JsonValueKind.NULL"); - CloseChild(); - CloseChild(); - CloseChild(); - } WriteTypes(program); CreateOutputFile(); WriteTopLevelNatives(program); @@ -225,7 +225,6 @@ enum class FuId regexOptionsEnum, regexClass, matchClass, - jsonValueKindEnum, jsonElementClass, lockClass, stringLength, @@ -237,14 +236,6 @@ enum class FuId matchEnd, matchLength, matchValue, - jsonValueKindObject, - jsonValueKindArray, - jsonValueKindString, - jsonValueKindNumber, - jsonValueKindTrue, - jsonValueKindFalse, - jsonValueKindNull, - jsonElementValueKind, mathNaN, mathNegativeInfinity, mathPositiveInfinity, @@ -339,7 +330,12 @@ enum class FuId matchFindRegex, matchGetCapture, jsonElementParse, - jsonElementTryParse, + jsonElementIsObject, + jsonElementIsArray, + jsonElementIsString, + jsonElementIsNumber, + jsonElementIsBoolean, + jsonElementIsNull, jsonElementGetObject, jsonElementGetArray, jsonElementGetString, @@ -1510,7 +1506,6 @@ public: const FuMethod * main = nullptr; std::map<std::string, std::vector<uint8_t>> resources; bool regexOptionsEnum = false; - bool jsonValueKindEnum = false; }; class FuParser : public FuLexer @@ -2398,6 +2393,7 @@ private: void writeVisibility(FuVisibility visibility); void writeCallType(FuCallType callType, std::string_view sealedString); void writeElementType(const FuType * elementType); + void writeJsonElementIs(const FuExpr * obj, std::string_view name, FuPriority parent); void writeOrderedDictionaryIndexing(const FuBinaryExpr * expr); void writeResources(const std::map<std::string, std::vector<uint8_t>> * resources); }; @@ -2469,6 +2465,7 @@ private: void writeWrite(const std::vector<std::shared_ptr<FuExpr>> * args, bool newLine); void writeSlice(const FuExpr * obj, const FuExpr * offset, const FuExpr * length); void writeInsertedArg(const FuType * type, const std::vector<std::shared_ptr<FuExpr>> * args, int index = 0); + void writeJsonElementIs(const FuExpr * obj, std::string_view name, FuPriority parent); static bool isIsComparable(const FuExpr * expr); void writeIsVar(const FuExpr * left, const FuExpr * right, FuPriority parent); static bool isLong(const FuSymbolReference * expr); @@ -2612,6 +2609,7 @@ private: void writeSlice(const FuExpr * array, const FuExpr * offset, const FuExpr * length, FuPriority parent, std::string_view method); static bool isIdentifier(std::string_view s); void writeNewRegex(const std::vector<std::shared_ptr<FuExpr>> * args, int argIndex); + void writeTypeofEquals(const FuExpr * obj, std::string_view name, FuPriority parent); static bool hasLong(const std::vector<std::shared_ptr<FuExpr>> * args); void writeMathMaxMin(const FuMethod * method, std::string_view name, int op, const std::vector<std::shared_ptr<FuExpr>> * args); void writeBoolAndOrAssign(const FuBinaryExpr * expr, FuPriority parent); @@ -2885,6 +2883,7 @@ private: void writeAllAny(std::string_view function, const FuExpr * obj, const std::vector<std::shared_ptr<FuExpr>> * args); void writePyRegexOptions(const std::vector<std::shared_ptr<FuExpr>> * args); void writeRegexSearch(const std::vector<std::shared_ptr<FuExpr>> * args); + void writeJsonElementIs(const FuExpr * obj, std::string_view name); void writeInclusiveLimit(const FuExpr * limit, int increment, std::string_view incrementString); void writePyCaseValue(const FuExpr * value); void writePyCaseBody(const FuSwitch * statement, const std::vector<std::shared_ptr<FuStatement>> * body); @@ -1299,141 +1299,137 @@ export const FuId = { REGEX_OPTIONS_ENUM : 34, REGEX_CLASS : 35, MATCH_CLASS : 36, - JSON_VALUE_KIND_ENUM : 37, - JSON_ELEMENT_CLASS : 38, - LOCK_CLASS : 39, - STRING_LENGTH : 40, - ARRAY_LENGTH : 41, - CONSOLE_ERROR : 42, - MAIN : 43, - CLASS_TO_STRING : 44, - MATCH_START : 45, - MATCH_END : 46, - MATCH_LENGTH : 47, - MATCH_VALUE : 48, - JSON_VALUE_KIND_OBJECT : 49, - JSON_VALUE_KIND_ARRAY : 50, - JSON_VALUE_KIND_STRING : 51, - JSON_VALUE_KIND_NUMBER : 52, - JSON_VALUE_KIND_TRUE : 53, - JSON_VALUE_KIND_FALSE : 54, - JSON_VALUE_KIND_NULL : 55, - JSON_ELEMENT_VALUE_KIND : 56, - MATH_NA_N : 57, - MATH_NEGATIVE_INFINITY : 58, - MATH_POSITIVE_INFINITY : 59, - ENUM_FROM_INT : 60, - ENUM_HAS_FLAG : 61, - INT_TRY_PARSE : 62, - LONG_TRY_PARSE : 63, - DOUBLE_TRY_PARSE : 64, - STRING_CONTAINS : 65, - STRING_ENDS_WITH : 66, - STRING_INDEX_OF : 67, - STRING_LAST_INDEX_OF : 68, - STRING_REPLACE : 69, - STRING_STARTS_WITH : 70, - STRING_SUBSTRING : 71, - STRING_TO_LOWER : 72, - STRING_TO_UPPER : 73, - ARRAY_BINARY_SEARCH_ALL : 74, - ARRAY_BINARY_SEARCH_PART : 75, - ARRAY_CONTAINS : 76, - ARRAY_COPY_TO : 77, - ARRAY_FILL_ALL : 78, - ARRAY_FILL_PART : 79, - ARRAY_SORT_ALL : 80, - ARRAY_SORT_PART : 81, - LIST_ADD : 82, - LIST_ADD_RANGE : 83, - LIST_ALL : 84, - LIST_ANY : 85, - LIST_CLEAR : 86, - LIST_CONTAINS : 87, - LIST_COPY_TO : 88, - LIST_COUNT : 89, - LIST_INDEX_OF : 90, - LIST_INSERT : 91, - LIST_LAST : 92, - LIST_REMOVE_AT : 93, - LIST_REMOVE_RANGE : 94, - LIST_SORT_ALL : 95, - LIST_SORT_PART : 96, - QUEUE_CLEAR : 97, - QUEUE_COUNT : 98, - QUEUE_DEQUEUE : 99, - QUEUE_ENQUEUE : 100, - QUEUE_PEEK : 101, - STACK_CLEAR : 102, - STACK_COUNT : 103, - STACK_PEEK : 104, - STACK_PUSH : 105, - STACK_POP : 106, - HASH_SET_ADD : 107, - HASH_SET_CLEAR : 108, - HASH_SET_CONTAINS : 109, - HASH_SET_COUNT : 110, - HASH_SET_REMOVE : 111, - SORTED_SET_ADD : 112, - SORTED_SET_CLEAR : 113, - SORTED_SET_CONTAINS : 114, - SORTED_SET_COUNT : 115, - SORTED_SET_REMOVE : 116, - DICTIONARY_ADD : 117, - DICTIONARY_CLEAR : 118, - DICTIONARY_CONTAINS_KEY : 119, - DICTIONARY_COUNT : 120, - DICTIONARY_REMOVE : 121, - SORTED_DICTIONARY_CLEAR : 122, - SORTED_DICTIONARY_CONTAINS_KEY : 123, - SORTED_DICTIONARY_COUNT : 124, - SORTED_DICTIONARY_REMOVE : 125, - ORDERED_DICTIONARY_CLEAR : 126, - ORDERED_DICTIONARY_CONTAINS_KEY : 127, - ORDERED_DICTIONARY_COUNT : 128, - ORDERED_DICTIONARY_REMOVE : 129, - TEXT_WRITER_WRITE : 130, - TEXT_WRITER_WRITE_CHAR : 131, - TEXT_WRITER_WRITE_CODE_POINT : 132, - TEXT_WRITER_WRITE_LINE : 133, - CONSOLE_WRITE : 134, - CONSOLE_WRITE_LINE : 135, - STRING_WRITER_CLEAR : 136, - STRING_WRITER_TO_STRING : 137, - CONVERT_TO_BASE64_STRING : 138, - U_T_F8_GET_BYTE_COUNT : 139, - U_T_F8_GET_BYTES : 140, - U_T_F8_GET_STRING : 141, - ENVIRONMENT_GET_ENVIRONMENT_VARIABLE : 142, - REGEX_COMPILE : 143, - REGEX_ESCAPE : 144, - REGEX_IS_MATCH_STR : 145, - REGEX_IS_MATCH_REGEX : 146, - MATCH_FIND_STR : 147, - MATCH_FIND_REGEX : 148, - MATCH_GET_CAPTURE : 149, - JSON_ELEMENT_PARSE : 150, - JSON_ELEMENT_TRY_PARSE : 151, - JSON_ELEMENT_GET_OBJECT : 152, - JSON_ELEMENT_GET_ARRAY : 153, - JSON_ELEMENT_GET_STRING : 154, - JSON_ELEMENT_GET_DOUBLE : 155, - JSON_ELEMENT_GET_BOOLEAN : 156, - MATH_METHOD : 157, - MATH_ABS : 158, - MATH_CEILING : 159, - MATH_CLAMP : 160, - MATH_FUSED_MULTIPLY_ADD : 161, - MATH_IS_FINITE : 162, - MATH_IS_INFINITY : 163, - MATH_IS_NA_N : 164, - MATH_LOG2 : 165, - MATH_MAX_INT : 166, - MATH_MAX_DOUBLE : 167, - MATH_MIN_INT : 168, - MATH_MIN_DOUBLE : 169, - MATH_ROUND : 170, - MATH_TRUNCATE : 171 + JSON_ELEMENT_CLASS : 37, + LOCK_CLASS : 38, + STRING_LENGTH : 39, + ARRAY_LENGTH : 40, + CONSOLE_ERROR : 41, + MAIN : 42, + CLASS_TO_STRING : 43, + MATCH_START : 44, + MATCH_END : 45, + MATCH_LENGTH : 46, + MATCH_VALUE : 47, + MATH_NA_N : 48, + MATH_NEGATIVE_INFINITY : 49, + MATH_POSITIVE_INFINITY : 50, + ENUM_FROM_INT : 51, + ENUM_HAS_FLAG : 52, + INT_TRY_PARSE : 53, + LONG_TRY_PARSE : 54, + DOUBLE_TRY_PARSE : 55, + STRING_CONTAINS : 56, + STRING_ENDS_WITH : 57, + STRING_INDEX_OF : 58, + STRING_LAST_INDEX_OF : 59, + STRING_REPLACE : 60, + STRING_STARTS_WITH : 61, + STRING_SUBSTRING : 62, + STRING_TO_LOWER : 63, + STRING_TO_UPPER : 64, + ARRAY_BINARY_SEARCH_ALL : 65, + ARRAY_BINARY_SEARCH_PART : 66, + ARRAY_CONTAINS : 67, + ARRAY_COPY_TO : 68, + ARRAY_FILL_ALL : 69, + ARRAY_FILL_PART : 70, + ARRAY_SORT_ALL : 71, + ARRAY_SORT_PART : 72, + LIST_ADD : 73, + LIST_ADD_RANGE : 74, + LIST_ALL : 75, + LIST_ANY : 76, + LIST_CLEAR : 77, + LIST_CONTAINS : 78, + LIST_COPY_TO : 79, + LIST_COUNT : 80, + LIST_INDEX_OF : 81, + LIST_INSERT : 82, + LIST_LAST : 83, + LIST_REMOVE_AT : 84, + LIST_REMOVE_RANGE : 85, + LIST_SORT_ALL : 86, + LIST_SORT_PART : 87, + QUEUE_CLEAR : 88, + QUEUE_COUNT : 89, + QUEUE_DEQUEUE : 90, + QUEUE_ENQUEUE : 91, + QUEUE_PEEK : 92, + STACK_CLEAR : 93, + STACK_COUNT : 94, + STACK_PEEK : 95, + STACK_PUSH : 96, + STACK_POP : 97, + HASH_SET_ADD : 98, + HASH_SET_CLEAR : 99, + HASH_SET_CONTAINS : 100, + HASH_SET_COUNT : 101, + HASH_SET_REMOVE : 102, + SORTED_SET_ADD : 103, + SORTED_SET_CLEAR : 104, + SORTED_SET_CONTAINS : 105, + SORTED_SET_COUNT : 106, + SORTED_SET_REMOVE : 107, + DICTIONARY_ADD : 108, + DICTIONARY_CLEAR : 109, + DICTIONARY_CONTAINS_KEY : 110, + DICTIONARY_COUNT : 111, + DICTIONARY_REMOVE : 112, + SORTED_DICTIONARY_CLEAR : 113, + SORTED_DICTIONARY_CONTAINS_KEY : 114, + SORTED_DICTIONARY_COUNT : 115, + SORTED_DICTIONARY_REMOVE : 116, + ORDERED_DICTIONARY_CLEAR : 117, + ORDERED_DICTIONARY_CONTAINS_KEY : 118, + ORDERED_DICTIONARY_COUNT : 119, + ORDERED_DICTIONARY_REMOVE : 120, + TEXT_WRITER_WRITE : 121, + TEXT_WRITER_WRITE_CHAR : 122, + TEXT_WRITER_WRITE_CODE_POINT : 123, + TEXT_WRITER_WRITE_LINE : 124, + CONSOLE_WRITE : 125, + CONSOLE_WRITE_LINE : 126, + STRING_WRITER_CLEAR : 127, + STRING_WRITER_TO_STRING : 128, + CONVERT_TO_BASE64_STRING : 129, + U_T_F8_GET_BYTE_COUNT : 130, + U_T_F8_GET_BYTES : 131, + U_T_F8_GET_STRING : 132, + ENVIRONMENT_GET_ENVIRONMENT_VARIABLE : 133, + REGEX_COMPILE : 134, + REGEX_ESCAPE : 135, + REGEX_IS_MATCH_STR : 136, + REGEX_IS_MATCH_REGEX : 137, + MATCH_FIND_STR : 138, + MATCH_FIND_REGEX : 139, + MATCH_GET_CAPTURE : 140, + JSON_ELEMENT_PARSE : 141, + JSON_ELEMENT_IS_OBJECT : 142, + JSON_ELEMENT_IS_ARRAY : 143, + JSON_ELEMENT_IS_STRING : 144, + JSON_ELEMENT_IS_NUMBER : 145, + JSON_ELEMENT_IS_BOOLEAN : 146, + JSON_ELEMENT_IS_NULL : 147, + JSON_ELEMENT_GET_OBJECT : 148, + JSON_ELEMENT_GET_ARRAY : 149, + JSON_ELEMENT_GET_STRING : 150, + JSON_ELEMENT_GET_DOUBLE : 151, + JSON_ELEMENT_GET_BOOLEAN : 152, + MATH_METHOD : 153, + MATH_ABS : 154, + MATH_CEILING : 155, + MATH_CLAMP : 156, + MATH_FUSED_MULTIPLY_ADD : 157, + MATH_IS_FINITE : 158, + MATH_IS_INFINITY : 159, + MATH_IS_NA_N : 160, + MATH_LOG2 : 161, + MATH_MAX_INT : 162, + MATH_MAX_DOUBLE : 163, + MATH_MIN_INT : 164, + MATH_MIN_DOUBLE : 165, + MATH_ROUND : 166, + MATH_TRUNCATE : 167 } class FuDocInline @@ -2601,7 +2597,7 @@ export class FuNamedValue extends FuSymbol isAssignableStorage() { let storage; - return (storage = this.type) instanceof FuStorageType && !(this.type instanceof FuArrayStorageType) && (this.value instanceof FuLiteralNull || storage.class.id == FuId.JSON_ELEMENT_CLASS); + return (storage = this.type) instanceof FuStorageType && !(this.type instanceof FuArrayStorageType) && this.value instanceof FuLiteralNull; } } @@ -3286,28 +3282,20 @@ export class FuSystem extends FuScope matchClass.add(FuProperty.new(this.#uIntType, FuId.MATCH_LENGTH, "Length")); matchClass.add(FuProperty.new(this.stringStorageType, FuId.MATCH_VALUE, "Value")); this.add(matchClass); - let jsonValueKindEnum = this.newEnum(false); - jsonValueKindEnum.isPublic = true; - jsonValueKindEnum.id = FuId.JSON_VALUE_KIND_ENUM; - jsonValueKindEnum.name = "JsonValueKind"; - FuSystem.#addEnumValue(jsonValueKindEnum, Object.assign(new FuConst(), { visibility: FuVisibility.PUBLIC, id: FuId.JSON_VALUE_KIND_OBJECT, name: "Object", visitStatus: FuVisitStatus.DONE })); - FuSystem.#addEnumValue(jsonValueKindEnum, Object.assign(new FuConst(), { visibility: FuVisibility.PUBLIC, id: FuId.JSON_VALUE_KIND_ARRAY, name: "Array", visitStatus: FuVisitStatus.DONE })); - FuSystem.#addEnumValue(jsonValueKindEnum, Object.assign(new FuConst(), { visibility: FuVisibility.PUBLIC, id: FuId.JSON_VALUE_KIND_STRING, name: "String", visitStatus: FuVisitStatus.DONE })); - FuSystem.#addEnumValue(jsonValueKindEnum, Object.assign(new FuConst(), { visibility: FuVisibility.PUBLIC, id: FuId.JSON_VALUE_KIND_NUMBER, name: "Number", visitStatus: FuVisitStatus.DONE })); - FuSystem.#addEnumValue(jsonValueKindEnum, Object.assign(new FuConst(), { visibility: FuVisibility.PUBLIC, id: FuId.JSON_VALUE_KIND_TRUE, name: "True", visitStatus: FuVisitStatus.DONE })); - FuSystem.#addEnumValue(jsonValueKindEnum, Object.assign(new FuConst(), { visibility: FuVisibility.PUBLIC, id: FuId.JSON_VALUE_KIND_FALSE, name: "False", visitStatus: FuVisitStatus.DONE })); - FuSystem.#addEnumValue(jsonValueKindEnum, Object.assign(new FuConst(), { visibility: FuVisibility.PUBLIC, id: FuId.JSON_VALUE_KIND_NULL, name: "Null", visitStatus: FuVisitStatus.DONE })); - this.add(jsonValueKindEnum); let jsonElementClass = FuClass.new(FuCallType.SEALED, FuId.JSON_ELEMENT_CLASS, "JsonElement"); - jsonElementClass.add(FuMethod.new(null, FuVisibility.PUBLIC, FuCallType.NORMAL, this.voidType, FuId.JSON_ELEMENT_PARSE, "Parse", true, FuVar.new(this.stringPtrType, "value"))); - jsonElementClass.add(FuMethod.new(null, FuVisibility.PUBLIC, FuCallType.NORMAL, this.boolType, FuId.JSON_ELEMENT_TRY_PARSE, "TryParse", true, FuVar.new(this.stringPtrType, "value"))); let jsonElementPtr = Object.assign(new FuDynamicPtrType(), { class: jsonElementClass }); + jsonElementClass.add(FuMethod.new(null, FuVisibility.PUBLIC, FuCallType.STATIC, jsonElementPtr, FuId.JSON_ELEMENT_PARSE, "Parse", false, FuVar.new(this.stringPtrType, "value"))); + jsonElementClass.add(FuMethod.new(null, FuVisibility.PUBLIC, FuCallType.NORMAL, this.boolType, FuId.JSON_ELEMENT_IS_OBJECT, "IsObject", false)); + jsonElementClass.add(FuMethod.new(null, FuVisibility.PUBLIC, FuCallType.NORMAL, this.boolType, FuId.JSON_ELEMENT_IS_ARRAY, "IsArray", false)); + jsonElementClass.add(FuMethod.new(null, FuVisibility.PUBLIC, FuCallType.NORMAL, this.boolType, FuId.JSON_ELEMENT_IS_STRING, "IsString", false)); + jsonElementClass.add(FuMethod.new(null, FuVisibility.PUBLIC, FuCallType.NORMAL, this.boolType, FuId.JSON_ELEMENT_IS_NUMBER, "IsNumber", false)); + jsonElementClass.add(FuMethod.new(null, FuVisibility.PUBLIC, FuCallType.NORMAL, this.boolType, FuId.JSON_ELEMENT_IS_BOOLEAN, "IsBoolean", false)); + jsonElementClass.add(FuMethod.new(null, FuVisibility.PUBLIC, FuCallType.NORMAL, this.boolType, FuId.JSON_ELEMENT_IS_NULL, "IsNull", false)); jsonElementClass.add(FuMethod.new(null, FuVisibility.PUBLIC, FuCallType.NORMAL, Object.assign(new FuClassType(), { class: dictionaryClass, typeArg0: this.stringStorageType, typeArg1: jsonElementPtr }), FuId.JSON_ELEMENT_GET_OBJECT, "GetObject", false)); jsonElementClass.add(FuMethod.new(null, FuVisibility.PUBLIC, FuCallType.NORMAL, Object.assign(new FuClassType(), { class: listClass, typeArg0: jsonElementPtr }), FuId.JSON_ELEMENT_GET_ARRAY, "GetArray", false)); jsonElementClass.add(FuMethod.new(null, FuVisibility.PUBLIC, FuCallType.NORMAL, this.stringPtrType, FuId.JSON_ELEMENT_GET_STRING, "GetString", false)); jsonElementClass.add(FuMethod.new(null, FuVisibility.PUBLIC, FuCallType.NORMAL, this.doubleType, FuId.JSON_ELEMENT_GET_DOUBLE, "GetDouble", false)); jsonElementClass.add(FuMethod.new(null, FuVisibility.PUBLIC, FuCallType.NORMAL, this.boolType, FuId.JSON_ELEMENT_GET_BOOLEAN, "GetBoolean", false)); - jsonElementClass.add(FuProperty.new(jsonValueKindEnum, FuId.JSON_ELEMENT_VALUE_KIND, "ValueKind")); this.add(jsonElementClass); let floatIntType = Object.assign(new FuFloatingType(), { id: FuId.FLOAT_INT_TYPE, name: "float" }); let mathClass = FuClass.new(FuCallType.STATIC, FuId.NONE, "Math"); @@ -3475,7 +3463,6 @@ export class FuProgram extends FuScope main = null; resources = {}; regexOptionsEnum = false; - jsonValueKindEnum = false; } export class FuParser extends FuLexer @@ -4751,8 +4738,6 @@ export class FuSema } else if (symbol.symbol.id == FuId.REGEX_OPTIONS_ENUM) this.program.regexOptionsEnum = true; - else if (symbol.symbol.id == FuId.JSON_VALUE_KIND_ENUM) - this.program.jsonValueKindEnum = true; } return resolved; } @@ -16246,6 +16231,16 @@ export class GenCs extends GenTyped } } + #writeJsonElementIs(obj, name, parent) + { + if (parent > FuPriority.EQUALITY) + this.writeChar(40); + this.writePostfix(obj, ".ValueKind == JsonValueKind."); + this.write(name); + if (parent > FuPriority.EQUALITY) + this.writeChar(41); + } + writeCallExpr(obj, method, args, parent) { switch (method.id) { @@ -16474,11 +16469,33 @@ export class GenCs extends GenTyped this.write("].Value"); break; case FuId.JSON_ELEMENT_PARSE: - obj.accept(this, FuPriority.ASSIGN); - this.write(" = JsonDocument.Parse("); + this.write("JsonDocument.Parse("); args[0].accept(this, FuPriority.ARGUMENT); this.write(").RootElement"); break; + case FuId.JSON_ELEMENT_IS_OBJECT: + this.#writeJsonElementIs(obj, "Object", parent); + break; + case FuId.JSON_ELEMENT_IS_ARRAY: + this.#writeJsonElementIs(obj, "Array", parent); + break; + case FuId.JSON_ELEMENT_IS_STRING: + this.#writeJsonElementIs(obj, "String", parent); + break; + case FuId.JSON_ELEMENT_IS_NUMBER: + this.#writeJsonElementIs(obj, "Number", parent); + break; + case FuId.JSON_ELEMENT_IS_BOOLEAN: + if (parent > FuPriority.COND_OR) + this.writeChar(40); + this.writePostfix(obj, ".ValueKind == JsonValueKind.True || "); + this.writePostfix(obj, ".ValueKind == JsonValueKind.False"); + if (parent > FuPriority.COND_OR) + this.writeChar(41); + break; + case FuId.JSON_ELEMENT_IS_NULL: + this.#writeJsonElementIs(obj, "Null", parent); + break; case FuId.JSON_ELEMENT_GET_OBJECT: this.include("System.Linq"); this.writePostfix(obj, ".EnumerateObject().ToDictionary(p => p.Name, p => p.Value)"); @@ -17281,14 +17298,8 @@ export class GenD extends GenCCppD break; } } - else { - if (type.id == FuId.JSON_VALUE_KIND_ENUM) { - this.include("std.json"); - this.write("JSONType"); - } - else - this.write(type.name); - } + else + this.write(type.name); } writeTypeAndName(value) @@ -17495,30 +17506,6 @@ export class GenD extends GenCCppD case FuId.MATCH_VALUE: this.writePostfix(expr.left, ".hit"); break; - case FuId.JSON_ELEMENT_VALUE_KIND: - this.writePostfix(expr.left, ".type"); - break; - case FuId.JSON_VALUE_KIND_OBJECT: - this.write("JSONType.object"); - break; - case FuId.JSON_VALUE_KIND_ARRAY: - this.write("JSONType.array"); - break; - case FuId.JSON_VALUE_KIND_STRING: - this.write("JSONType.string"); - break; - case FuId.JSON_VALUE_KIND_NUMBER: - this.write("JSONType.float_"); - break; - case FuId.JSON_VALUE_KIND_TRUE: - this.write("JSONType.true_"); - break; - case FuId.JSON_VALUE_KIND_FALSE: - this.write("JSONType.false_"); - break; - case FuId.JSON_VALUE_KIND_NULL: - this.write("JSONType.null_"); - break; case FuId.MATH_NA_N: this.write("double.nan"); break; @@ -17580,6 +17567,16 @@ export class GenD extends GenCCppD this.writeChar(41); } + #writeJsonElementIs(obj, name, parent) + { + if (parent > FuPriority.EQUALITY) + this.writeChar(40); + this.writePostfix(obj, ".type == JSONType."); + this.write(name); + if (parent > FuPriority.EQUALITY) + this.writeChar(41); + } + writeCallExpr(obj, method, args, parent) { switch (method.id) { @@ -17919,8 +17916,30 @@ export class GenD extends GenCCppD this.writeIndexing(obj, args[0]); break; case FuId.JSON_ELEMENT_PARSE: - obj.accept(this, FuPriority.ASSIGN); - this.writeCall(" = parseJSON", args[0]); + this.writeCall("parseJSON", args[0]); + break; + case FuId.JSON_ELEMENT_IS_OBJECT: + this.#writeJsonElementIs(obj, "object", parent); + break; + case FuId.JSON_ELEMENT_IS_ARRAY: + this.#writeJsonElementIs(obj, "array", parent); + break; + case FuId.JSON_ELEMENT_IS_STRING: + this.#writeJsonElementIs(obj, "string", parent); + break; + case FuId.JSON_ELEMENT_IS_NUMBER: + this.#writeJsonElementIs(obj, "float_", parent); + break; + case FuId.JSON_ELEMENT_IS_BOOLEAN: + if (parent > FuPriority.COND_OR) + this.writeChar(40); + this.writePostfix(obj, ".type == JSONType.true_ || "); + this.writePostfix(obj, ".type == JSONType.false_"); + if (parent > FuPriority.COND_OR) + this.writeChar(41); + break; + case FuId.JSON_ELEMENT_IS_NULL: + this.#writeJsonElementIs(obj, "null_", parent); break; case FuId.JSON_ELEMENT_GET_OBJECT: this.writePostfix(obj, ".object"); @@ -20247,9 +20266,6 @@ export class GenJsNoModule extends GenBase case FuId.MATCH_VALUE: this.writePostfix(expr.left, "[0]"); break; - case FuId.JSON_ELEMENT_VALUE_KIND: - this.writeCall("JsonValueKind.get", expr.left); - break; case FuId.MATH_NA_N: this.write("NaN"); break; @@ -20348,6 +20364,19 @@ export class GenJsNoModule extends GenBase } } + #writeTypeofEquals(obj, name, parent) + { + if (parent > FuPriority.EQUALITY) + this.writeChar(40); + this.write("typeof("); + obj.accept(this, FuPriority.ARGUMENT); + this.write(") == \""); + this.write(name); + this.writeChar(34); + if (parent > FuPriority.EQUALITY) + this.writeChar(41); + } + static #hasLong(args) { return args.some(arg => arg.type.id == FuId.LONG_TYPE); @@ -20696,8 +20725,34 @@ export class GenJsNoModule extends GenBase this.writeIndexing(obj, args[0]); break; case FuId.JSON_ELEMENT_PARSE: - obj.accept(this, FuPriority.ASSIGN); - this.writeCall(" = JSON.parse", args[0]); + this.writeCall("JSON.parse", args[0]); + break; + case FuId.JSON_ELEMENT_IS_OBJECT: + if (parent > FuPriority.EQUALITY) + this.writeChar(40); + this.writePostfix(obj, "?.constructor == Object"); + if (parent > FuPriority.EQUALITY) + this.writeChar(41); + break; + case FuId.JSON_ELEMENT_IS_ARRAY: + this.writeCall("Array.isArray", obj); + break; + case FuId.JSON_ELEMENT_IS_STRING: + this.#writeTypeofEquals(obj, "string", parent); + break; + case FuId.JSON_ELEMENT_IS_NUMBER: + this.#writeTypeofEquals(obj, "number", parent); + break; + case FuId.JSON_ELEMENT_IS_BOOLEAN: + this.#writeTypeofEquals(obj, "boolean", parent); + break; + case FuId.JSON_ELEMENT_IS_NULL: + if (parent > FuPriority.EQUALITY) + this.writeChar(40); + obj.accept(this, FuPriority.EQUALITY); + this.write(" === null"); + if (parent > FuPriority.EQUALITY) + this.writeChar(41); break; case FuId.JSON_ELEMENT_GET_OBJECT: case FuId.JSON_ELEMENT_GET_ARRAY: @@ -21166,33 +21221,6 @@ export class GenJsNoModule extends GenBase writeLib(program) { - if (program.jsonValueKindEnum) { - this.writeNewLine(); - this.write("const JsonValueKind = "); - this.openBlock(); - this.writeLine("OBJECT : 1,"); - this.writeLine("ARRAY : 2,"); - this.writeLine("STRING : 3,"); - this.writeLine("NUMBER : 4,"); - this.writeLine("TRUE : 5,"); - this.writeLine("FALSE : 6,"); - this.writeLine("NULL : 7,"); - this.write("get : e => "); - this.openBlock(); - this.write("switch (typeof(e)) "); - this.openBlock(); - this.writeLine("case \"string\":"); - this.writeLine("\treturn JsonValueKind.STRING;"); - this.writeLine("case \"number\":"); - this.writeLine("\treturn JsonValueKind.NUMBER;"); - this.writeLine("case \"boolean\":"); - this.writeLine("\treturn e ? JsonValueKind.TRUE : JsonValueKind.FALSE;"); - this.writeLine("default:"); - this.writeLine("\treturn Array.isArray(e) ? JsonValueKind.ARRAY: e === null ? JsonValueKind.NULL : JsonValueKind.OBJECT;"); - this.closeBlock(); - this.closeBlock(); - this.closeBlock(); - } if (this.#stringWriter) { this.writeNewLine(); this.writeLine("class StringWriter"); @@ -24266,9 +24294,6 @@ export class GenPy extends GenPySwift case FuId.ORDERED_DICTIONARY_COUNT: this.writeStringLength(expr.left); break; - case FuId.JSON_ELEMENT_VALUE_KIND: - this.writeCall("JsonValueKind.get", expr.left); - break; case FuId.MATH_NA_N: this.include("math"); this.write("math.nan"); @@ -24580,6 +24605,15 @@ export class GenPy extends GenPySwift this.writeChar(41); } + #writeJsonElementIs(obj, name) + { + this.write("isinstance("); + obj.accept(this, FuPriority.ARGUMENT); + this.write(", "); + this.write(name); + this.writeChar(41); + } + writeCallExpr(obj, method, args, parent) { switch (method.id) { @@ -24852,8 +24886,30 @@ export class GenPy extends GenPySwift break; case FuId.JSON_ELEMENT_PARSE: this.include("json"); - obj.accept(this, FuPriority.ASSIGN); - this.writeCall(" = json.loads", args[0]); + this.writeCall("json.loads", args[0]); + break; + case FuId.JSON_ELEMENT_IS_OBJECT: + this.#writeJsonElementIs(obj, "dict"); + break; + case FuId.JSON_ELEMENT_IS_ARRAY: + this.#writeJsonElementIs(obj, "list"); + break; + case FuId.JSON_ELEMENT_IS_STRING: + this.#writeJsonElementIs(obj, "str"); + break; + case FuId.JSON_ELEMENT_IS_NUMBER: + this.#writeJsonElementIs(obj, "float"); + break; + case FuId.JSON_ELEMENT_IS_BOOLEAN: + this.#writeJsonElementIs(obj, "bool"); + break; + case FuId.JSON_ELEMENT_IS_NULL: + if (parent > FuPriority.EQUALITY) + this.writeChar(40); + obj.accept(this, FuPriority.EQUALITY); + this.write(" is None"); + if (parent > FuPriority.EQUALITY) + this.writeChar(41); break; case FuId.JSON_ELEMENT_GET_OBJECT: case FuId.JSON_ELEMENT_GET_ARRAY: @@ -25382,41 +25438,6 @@ export class GenPy extends GenPySwift this.#writtenTypes.clear(); this.#switchBreak = false; this.openStringWriter(); - if (program.jsonValueKindEnum) { - this.writeNewLine(); - this.include("enum"); - this.write("class JsonValueKind(enum.Enum)"); - this.openChild(); - this.writeLine("OBJECT = 1"); - this.writeLine("ARRAY = 2"); - this.writeLine("STRING = 3"); - this.writeLine("NUMBER = 4"); - this.writeLine("TRUE = 5"); - this.writeLine("FALSE = 6"); - this.writeLine("NULL = 7"); - this.writeLine("@staticmethod"); - this.write("def get(e)"); - this.openChild(); - this.write("match e"); - this.openChild(); - this.writeLine("case dict():"); - this.writeLine("\treturn JsonValueKind.OBJECT"); - this.writeLine("case list():"); - this.writeLine("\treturn JsonValueKind.ARRAY"); - this.writeLine("case str():"); - this.writeLine("\treturn JsonValueKind.STRING"); - this.writeLine("case float():"); - this.writeLine("\treturn JsonValueKind.NUMBER"); - this.writeLine("case True:"); - this.writeLine("\treturn JsonValueKind.TRUE"); - this.writeLine("case False:"); - this.writeLine("\treturn JsonValueKind.FALSE"); - this.writeLine("case None:"); - this.writeLine("\treturn JsonValueKind.NULL"); - this.closeChild(); - this.closeChild(); - this.closeChild(); - } this.writeTypes(program); this.createOutputFile(); this.writeTopLevelNatives(program); diff --git a/test/JsonElement.fu b/test/JsonElement.fu index fd36220..a01198c 100644 --- a/test/JsonElement.fu +++ b/test/JsonElement.fu @@ -2,35 +2,35 @@ public static class Test { public static bool Run() { - JsonElement() json; //FAIL: c cpp java swift TODO; cl - json.Parse("\"foo\""); - if (json.ValueKind != JsonValueKind.String || json.GetString() != "foo") + JsonElement# json; //FAIL: c cpp java swift TODO; cl + json = JsonElement.Parse("\"foo\""); + if (!json.IsString() || json.GetString() != "foo") return false; - json.Parse("10.5"); - if (json.ValueKind != JsonValueKind.Number || json.GetDouble() != 10.5) + json = JsonElement.Parse("10.5"); + if (!json.IsNumber() || json.GetDouble() != 10.5) return false; - json.Parse("true"); - if (json.ValueKind != JsonValueKind.True || !json.GetBoolean()) + json = JsonElement.Parse("true"); + if (!json.IsBoolean() || !json.GetBoolean()) return false; - json.Parse("false"); - if (json.ValueKind != JsonValueKind.False || json.GetBoolean()) + json = JsonElement.Parse("false"); + if (!json.IsBoolean() || json.GetBoolean()) return false; - json.Parse("null"); - if (json.ValueKind != JsonValueKind.Null) + json = JsonElement.Parse("null"); + if (!json.IsNull()) return false; - json.Parse("[ 5, true ]"); - if (json.ValueKind != JsonValueKind.Array) + json = JsonElement.Parse("[ 5, true ]"); + if (!json.IsArray()) return false; List<JsonElement#> list = json.GetArray(); //FAIL: d TODO - if (list.Count != 2 || list[0].GetDouble() != 5 || list[1].ValueKind != JsonValueKind.True) + if (list.Count != 2 || list[0].GetDouble() != 5 || !list[1].IsBoolean()) return false; - json.Parse("{ \"foo\": null, \"bar\": 42 }"); - if (json.ValueKind != JsonValueKind.Object) + json = JsonElement.Parse("{ \"foo\": null, \"bar\": 42 }"); + if (!json.IsObject()) return false; Dictionary<string(), JsonElement#> dict = json.GetObject(); - if (dict.Count != 2 || dict["foo"].ValueKind != JsonValueKind.Null || dict["bar"].GetDouble() != 42) + if (dict.Count != 2 || !dict["foo"].IsNull() || dict["bar"].GetDouble() != 42) return false; return true; |