summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPiotr Fusik <piotr@fusion-lang.org>2024-02-19 14:55:51 +0100
committerPiotr Fusik <piotr@fusion-lang.org>2024-02-19 14:55:51 +0100
commit1e4e00455e3299770049c6a68275974799148dbb (patch)
tree1d4adfe0e0c22f6dfd248b8d57269e229244236d
parent6617ede213e784a2b6f13d3915cb040a11ad3abb (diff)
[json] JavaScript.
#140
-rw-r--r--AST.fu3
-rw-r--r--GenJs.fu42
-rw-r--r--GenTs.fu5
-rw-r--r--Sema.fu2
-rw-r--r--libfut.cpp50
-rw-r--r--libfut.cs51
-rw-r--r--libfut.hpp1
-rw-r--r--libfut.js51
-rw-r--r--test/JsonElement.fu2
9 files changed, 201 insertions, 6 deletions
diff --git a/AST.fu b/AST.fu
index ebc02f3..fa1871b 100644
--- a/AST.fu
+++ b/AST.fu
@@ -1051,7 +1051,7 @@ public abstract class FuNamedValue : FuSymbol
{
internal FuExpr#? TypeExpr;
internal FuExpr#? Value;
- public bool IsAssignableStorage() => this.Type is FuStorageType && !(this.Type is FuArrayStorageType) && this.Value is FuLiteralNull;
+ public bool IsAssignableStorage() => this.Type is FuStorageType storage && !(this.Type is FuArrayStorageType) && (this.Value is FuLiteralNull || storage.Class.Id == FuId.JsonElementClass);
}
public abstract class FuMember : FuNamedValue
@@ -1749,4 +1749,5 @@ public class FuProgram : FuScope
internal FuMethod? Main = null;
internal SortedDictionary<string(), List<byte>()>() Resources;
internal bool RegexOptionsEnum = false;
+ internal bool JsonValueKindEnum = false;
}
diff --git a/GenJs.fu b/GenJs.fu
index c24c50c..bfb5542 100644
--- a/GenJs.fu
+++ b/GenJs.fu
@@ -406,6 +406,9 @@ 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;
@@ -847,6 +850,17 @@ public class GenJsNoModule : GenBase
case FuId.MatchGetCapture:
WriteIndexing(obj, args[0]);
break;
+ case FuId.JsonElementParse:
+ obj.Accept(this, FuPriority.Assign);
+ WriteCall(" = JSON.parse", args[0]);
+ break;
+ case FuId.JsonElementGetObject:
+ case FuId.JsonElementGetArray:
+ case FuId.JsonElementGetString:
+ case FuId.JsonElementGetDouble:
+ case FuId.JsonElementGetBoolean:
+ obj.Accept(this, parent);
+ break;
case FuId.MathAbs:
WriteCall(args[0].Type.Id == FuId.LongType ? "(x => x < 0n ? -x : x)" : "Math.abs", args[0]);
break;
@@ -1318,6 +1332,34 @@ 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();
+ WriteNewLine();
+ CloseBlock();
+ }
if (this.StringWriter) {
WriteNewLine();
WriteLine("class StringWriter");
diff --git a/GenTs.fu b/GenTs.fu
index cd61981..a38e6f9 100644
--- a/GenTs.fu
+++ b/GenTs.fu
@@ -1,7 +1,7 @@
// GenTs.fu - TypeScript code generator
//
// Copyright (C) 2020-2021 Andy Edwards
-// Copyright (C) 2020-2023 Piotr Fusik
+// Copyright (C) 2020-2024 Piotr Fusik
//
// This file is part of Fusion Transpiler,
// see https://github.com/fusionlanguage/fut
@@ -131,6 +131,9 @@ public class GenTs : GenJs
case FuId.MatchClass:
Write("RegExpMatchArray");
break;
+ case FuId.JsonElementClass:
+ Write("any");
+ break;
default:
Write(klass.Class.Name);
break;
diff --git a/Sema.fu b/Sema.fu
index 0d4bb7c..f8a65db 100644
--- a/Sema.fu
+++ b/Sema.fu
@@ -234,6 +234,8 @@ 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;
}
diff --git a/libfut.cpp b/libfut.cpp
index 9eb934a..6c4719a 100644
--- a/libfut.cpp
+++ b/libfut.cpp
@@ -1961,7 +1961,8 @@ bool FuFloatingType::isAssignableFrom(const FuType * right) const
bool FuNamedValue::isAssignableStorage() const
{
- return dynamic_cast<const FuStorageType *>(this->type.get()) && !dynamic_cast<const FuArrayStorageType *>(this->type.get()) && dynamic_cast<const FuLiteralNull *>(this->value.get());
+ 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);
}
FuMember::FuMember()
{
@@ -4296,6 +4297,8 @@ 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;
}
@@ -18937,6 +18940,9 @@ 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;
@@ -19383,6 +19389,17 @@ void GenJsNoModule::writeCallExpr(const FuExpr * obj, const FuMethod * method, c
case FuId::matchGetCapture:
writeIndexing(obj, (*args)[0].get());
break;
+ case FuId::jsonElementParse:
+ obj->accept(this, FuPriority::assign);
+ writeCall(" = JSON.parse", (*args)[0].get());
+ break;
+ case FuId::jsonElementGetObject:
+ case FuId::jsonElementGetArray:
+ case FuId::jsonElementGetString:
+ case FuId::jsonElementGetDouble:
+ case FuId::jsonElementGetBoolean:
+ obj->accept(this, parent);
+ break;
case FuId::mathAbs:
writeCall((*args)[0]->type->id == FuId::longType ? "(x => x < 0n ? -x : x)" : "Math.abs", (*args)[0].get());
break;
@@ -19840,6 +19857,34 @@ 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();
+ writeNewLine();
+ closeBlock();
+ }
if (this->stringWriter) {
writeNewLine();
writeLine("class StringWriter");
@@ -20003,6 +20048,9 @@ void GenTs::writeType(const FuType * type, bool readOnly)
case FuId::matchClass:
write("RegExpMatchArray");
break;
+ case FuId::jsonElementClass:
+ write("any");
+ break;
default:
write(klass->class_->name);
break;
diff --git a/libfut.cs b/libfut.cs
index b5c9427..d1380eb 100644
--- a/libfut.cs
+++ b/libfut.cs
@@ -2551,7 +2551,7 @@ namespace Fusion
internal FuExpr Value;
- public bool IsAssignableStorage() => this.Type is FuStorageType && !(this.Type is FuArrayStorageType) && this.Value is FuLiteralNull;
+ public bool IsAssignableStorage() => this.Type is FuStorageType storage && !(this.Type is FuArrayStorageType) && (this.Value is FuLiteralNull || storage.Class.Id == FuId.JsonElementClass);
}
public abstract class FuMember : FuNamedValue
@@ -3326,6 +3326,8 @@ 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
@@ -4591,6 +4593,8 @@ 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;
}
@@ -19575,6 +19579,9 @@ 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;
@@ -20015,6 +20022,17 @@ namespace Fusion
case FuId.MatchGetCapture:
WriteIndexing(obj, args[0]);
break;
+ case FuId.JsonElementParse:
+ obj.Accept(this, FuPriority.Assign);
+ WriteCall(" = JSON.parse", args[0]);
+ break;
+ case FuId.JsonElementGetObject:
+ case FuId.JsonElementGetArray:
+ case FuId.JsonElementGetString:
+ case FuId.JsonElementGetDouble:
+ case FuId.JsonElementGetBoolean:
+ obj.Accept(this, parent);
+ break;
case FuId.MathAbs:
WriteCall(args[0].Type.Id == FuId.LongType ? "(x => x < 0n ? -x : x)" : "Math.abs", args[0]);
break;
@@ -20482,6 +20500,34 @@ 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();
+ WriteNewLine();
+ CloseBlock();
+ }
if (this.StringWriter) {
WriteNewLine();
WriteLine("class StringWriter");
@@ -20663,6 +20709,9 @@ namespace Fusion
case FuId.MatchClass:
Write("RegExpMatchArray");
break;
+ case FuId.JsonElementClass:
+ Write("any");
+ break;
default:
Write(klass.Class.Name);
break;
diff --git a/libfut.hpp b/libfut.hpp
index 743b29b..26d7a44 100644
--- a/libfut.hpp
+++ b/libfut.hpp
@@ -1503,6 +1503,7 @@ public:
const FuMethod * main = nullptr;
std::map<std::string, std::vector<uint8_t>> resources;
bool regexOptionsEnum = false;
+ bool jsonValueKindEnum = false;
};
class FuParser : public FuLexer
diff --git a/libfut.js b/libfut.js
index 2c62375..a45a2fd 100644
--- a/libfut.js
+++ b/libfut.js
@@ -2593,7 +2593,8 @@ export class FuNamedValue extends FuSymbol
isAssignableStorage()
{
- return this.type instanceof FuStorageType && !(this.type instanceof FuArrayStorageType) && this.value instanceof FuLiteralNull;
+ let storage;
+ return (storage = this.type) instanceof FuStorageType && !(this.type instanceof FuArrayStorageType) && (this.value instanceof FuLiteralNull || storage.class.id == FuId.JSON_ELEMENT_CLASS);
}
}
@@ -3467,6 +3468,7 @@ export class FuProgram extends FuScope
main = null;
resources = {};
regexOptionsEnum = false;
+ jsonValueKindEnum = false;
}
export class FuParser extends FuLexer
@@ -4742,6 +4744,8 @@ 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;
}
@@ -20128,6 +20132,9 @@ 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;
@@ -20573,6 +20580,17 @@ export class GenJsNoModule extends GenBase
case FuId.MATCH_GET_CAPTURE:
this.writeIndexing(obj, args[0]);
break;
+ case FuId.JSON_ELEMENT_PARSE:
+ obj.accept(this, FuPriority.ASSIGN);
+ this.writeCall(" = JSON.parse", args[0]);
+ break;
+ case FuId.JSON_ELEMENT_GET_OBJECT:
+ case FuId.JSON_ELEMENT_GET_ARRAY:
+ case FuId.JSON_ELEMENT_GET_STRING:
+ case FuId.JSON_ELEMENT_GET_DOUBLE:
+ case FuId.JSON_ELEMENT_GET_BOOLEAN:
+ obj.accept(this, parent);
+ break;
case FuId.MATH_ABS:
this.writeCall(args[0].type.id == FuId.LONG_TYPE ? "(x => x < 0n ? -x : x)" : "Math.abs", args[0]);
break;
@@ -21033,6 +21051,34 @@ 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.writeNewLine();
+ this.closeBlock();
+ }
if (this.#stringWriter) {
this.writeNewLine();
this.writeLine("class StringWriter");
@@ -21210,6 +21256,9 @@ export class GenTs extends GenJs
case FuId.MATCH_CLASS:
this.write("RegExpMatchArray");
break;
+ case FuId.JSON_ELEMENT_CLASS:
+ this.write("any");
+ break;
default:
this.write(klass.class.name);
break;
diff --git a/test/JsonElement.fu b/test/JsonElement.fu
index f622b9c..d8366dc 100644
--- a/test/JsonElement.fu
+++ b/test/JsonElement.fu
@@ -2,7 +2,7 @@ public static class Test
{
public static bool Run()
{
- JsonElement() json; //FAIL: c cpp d java js py swift ts TODO; cl
+ JsonElement() json; //FAIL: c cpp d java py swift TODO; cl
json.Parse("\"foo\"");
if (json.ValueKind != JsonValueKind.String || json.GetString() != "foo")
return false;