From 009a4ad06b6cef5aac179614f2e6c29310b02a52 Mon Sep 17 00:00:00 2001 From: Jairus Date: Fri, 2 Aug 2024 20:31:30 -0700 Subject: [PATCH] codegen issues --- assembly/index.ts | 173 +++++++++++++++++++++++++++++++++++++++++ assembly/test.ts | 41 ++-------- transform/lib/index.js | 34 +++++--- transform/src/index.ts | 36 +++++---- 4 files changed, 224 insertions(+), 60 deletions(-) diff --git a/assembly/index.ts b/assembly/index.ts index c56ed98..2ecf0b0 100644 --- a/assembly/index.ts +++ b/assembly/index.ts @@ -156,6 +156,179 @@ export namespace JSON { @inline static from(value: T): Box { return new Box(value); } + @inline + @operator("==") + eq(other: this): bool { + if (isNullable() && changetype(this) == 0) { + if (changetype(other) == 0) return true; + } + return this.value == other.value; + } + + @inline + @operator("!=") + notEq(other: this): bool { + if (isNullable() && changetype(this) == 0) { + if (changetype(this) == changetype(other)) return true; + } + return this.value != other.value; + } + + @inline + @operator(">") + gt(other: this): bool { + return this._val > other._val; + } + + @inline + @operator(">=") + ge(other: this): bool { + return this._val >= other._val; + } + + @inline + @operator("<") + lt(other: this): bool { + return this._val < other._val; + } + + @inline + @operator("<=") + le(other: this): bool { + return this._val <= other._val; + } + + @inline + @operator(">>") + shr(other: this): this { + // @ts-ignore + return instantiate(this._val >> other._val); + } + + @inline + @operator(">>>") + shr_u(other: this): this { + // @ts-ignore + return instantiate(this._val >>> other._val); + } + + @inline + @operator("<<") + shl(other: this): this { + // @ts-ignore + return instantiate(this._val << other._val); + } + + @inline + @operator("&") + and(other: this): this { + // @ts-ignore + return instantiate(this._val & other._val); + } + + @inline + @operator("|") + or(other: this): this { + // @ts-ignore + return instantiate(this._val | other._val); + } + + @inline + @operator("^") + xor(other: this): this { + // @ts-ignore + return instantiate(this._val ^ other._val); + } + + @inline + @operator("+") + add(other: this): this { + // @ts-ignore + return instantiate(this._val + other._val); + } + + @inline + @operator("-") + sub(other: this): this { + // @ts-ignore + return instantiate(this._val - other._val); + } + + @inline + @operator("*") + mul(other: this): this { + // @ts-ignore + return instantiate(this._val * other._val); + } + + @inline + @operator("/") + div(other: this): this { + // @ts-ignore + return instantiate(this._val / other._val); + } + + @inline + @operator("**") + pow(other: this): this { + // @ts-ignore + return instantiate((this._val ** other._val) as T); + } + + @inline + @operator("%") + rem(other: this): this { + // @ts-ignore + return instantiate(this._val % other._val); + } + + @inline + @operator.prefix("!") + isEmpty(): bool { + return !this._val; + } + + @inline + @operator.prefix("~") + not(): this { + return instantiate(~this._val); + } + + @inline + @operator.prefix("+") + pos(): this { + return instantiate(+this._val); + } + + @inline + @operator.prefix("-") + neg(): this { + return instantiate(-this._val); + } + + @operator.prefix("++") + preInc(): this { + // @ts-ignore + ++this._val; + return this; + } + + @operator.prefix("--") + preDec(): this { + // @ts-ignore + --this._val; + return this; + } + + @operator.postfix("++") + postInc(): this { + return this.clone().preInc(); + } + + @operator.postfix("--") + postDec(): this { + return this.clone().preDec(); + } } /** diff --git a/assembly/test.ts b/assembly/test.ts index f5d8629..3087d80 100644 --- a/assembly/test.ts +++ b/assembly/test.ts @@ -2,42 +2,13 @@ import { JSON } from "."; @json -class Vec3 { - x: f32 = 0.0; - y: f32 = 0.0; - z: f32 = 0.0; -} - -@json -class Player { - @alias("first name") - firstName!: string; - lastName!: string; - lastActive!: i32[]; - // Drop in a code block, function, or expression that evaluates to a boolean - @omitif("this.age < 18") - age!: i32; +class ContentBlock { @omitnull() - pos!: Vec3 | null; - isVerified!: boolean; + input: JSON.Raw | null = null; } -const player: Player = { - firstName: "Emmet", - lastName: "West", - lastActive: [8, 27, 2022], - age: 23, - pos: { - x: 3.4, - y: 1.2, - z: 8.3 - }, - isVerified: true -}; - -const stringified = JSON.stringify(player); - -const parsed = JSON.parse(stringified); +const foo: ContentBlock = { + input: "123" +} -console.log(stringified); -console.log(JSON.stringify(parsed)) \ No newline at end of file +console.log(JSON.stringify(foo)) \ No newline at end of file diff --git a/transform/lib/index.js b/transform/lib/index.js index 12cc84d..e3422e7 100644 --- a/transform/lib/index.js +++ b/transform/lib/index.js @@ -87,9 +87,12 @@ class JSONTransform extends BaseVisitor { mem.type = type; mem.value = value; mem.node = member; - if (type == "JSON.Raw") { + if (type.includes("JSON.Raw")) { mem.flags.set(PropertyFlags.JSON_Raw, []); } + if (member.type.isNullable) { + mem.flags.set(PropertyFlags.Null, []); + } if (member.decorators) { for (const decorator of member.decorators) { const decoratorName = decorator.name.text; @@ -214,8 +217,8 @@ class JSONTransform extends BaseVisitor { "`;\n store(changetype(out) + ((out.length - 2) << 1), 8192010);\n return out;\n}"; } else { - SERIALIZE_RAW += "`;\n};"; - SERIALIZE_PRETTY += "`;\n};"; + SERIALIZE_RAW += "}`;\n return out;\n}"; + SERIALIZE_PRETTY += "}`;\n return out;\n}"; } INITIALIZE += " return this;\n}"; const sortedMembers = []; @@ -307,12 +310,12 @@ class JSONTransform extends BaseVisitor { else { if (f) { f = false; - DESERIALIZE += ` if (0 == memory.compare(changetype("${escapeQuote(escapeSlash(name))}"), changetype(data) + (key_start << 1), ${name.length << 1})) {\n ${member.deserialize}\n return true;\n }\n`; + DESERIALIZE += ` if (0 === memory.compare(changetype("${escapeQuote(escapeSlash(name))}"), changetype(data) + (key_start << 1), ${name.length << 1})) {\n ${member.deserialize}\n return true;\n }\n`; } else { DESERIALIZE = DESERIALIZE.slice(0, DESERIALIZE.length - 1) + - ` else if (0 == memory.compare(changetype("${escapeQuote(escapeSlash(name))}"), changetype(data) + (key_start << 1), ${name.length << 1})) {\n ${member.deserialize}\n return true;\n }\n`; + ` else if (0 === memory.compare(changetype("${escapeQuote(escapeSlash(name))}"), changetype(data) + (key_start << 1), ${name.length << 1})) {\n ${member.deserialize}\n return true;\n }\n`; } } } @@ -400,11 +403,12 @@ export default class Transformer extends Transform { } var PropertyFlags; (function (PropertyFlags) { - PropertyFlags[PropertyFlags["Omit"] = 0] = "Omit"; - PropertyFlags[PropertyFlags["OmitNull"] = 1] = "OmitNull"; - PropertyFlags[PropertyFlags["OmitIf"] = 2] = "OmitIf"; - PropertyFlags[PropertyFlags["Alias"] = 3] = "Alias"; - PropertyFlags[PropertyFlags["JSON_Raw"] = 4] = "JSON_Raw"; + PropertyFlags[PropertyFlags["Null"] = 0] = "Null"; + PropertyFlags[PropertyFlags["Omit"] = 1] = "Omit"; + PropertyFlags[PropertyFlags["OmitNull"] = 2] = "OmitNull"; + PropertyFlags[PropertyFlags["OmitIf"] = 3] = "OmitIf"; + PropertyFlags[PropertyFlags["Alias"] = 4] = "Alias"; + PropertyFlags[PropertyFlags["JSON_Raw"] = 5] = "JSON_Raw"; })(PropertyFlags || (PropertyFlags = {})); class Property { constructor() { @@ -426,8 +430,14 @@ class Property { if (this.flags.has(PropertyFlags.Omit)) return; if (this.flags.has(PropertyFlags.JSON_Raw)) { - this.right_s = "this." + name; - this.right_d = "data.substring(value_start, value_end);"; + if (this.flags.has(PropertyFlags.Null)) { + this.right_s = "(this." + name + " || \"null\")"; + this.right_d = "value_start === value_end - 4 && 30399761348886638 === load(changetype(data) + (value_start << 1)) ? null : data.substring(value_start, value_end)"; + } + else { + this.right_s = "this." + name; + this.right_d = "data.substring(value_start, value_end);"; + } } else { this.right_s = "__SERIALIZE<" + type + ">(this." + name + ")"; diff --git a/transform/src/index.ts b/transform/src/index.ts index b3d3e80..2313b79 100644 --- a/transform/src/index.ts +++ b/transform/src/index.ts @@ -24,7 +24,7 @@ class JSONTransform extends BaseVisitor { public currentClass!: SchemaData; public sources = new Set(); - visitMethodDeclaration(): void {} + visitMethodDeclaration(): void { } visitClassDeclaration(node: ClassDeclaration): void { if (!node.decorators?.length) return; @@ -109,9 +109,9 @@ class JSONTransform extends BaseVisitor { if (!member.type) { throw new Error( "Fields must be strongly typed! Found " + - toString(member) + - " at " + - node.range.source.normalizedPath, + toString(member) + + " at " + + node.range.source.normalizedPath, ); } const type = toString(member.type!); @@ -128,10 +128,14 @@ class JSONTransform extends BaseVisitor { mem.value = value; mem.node = member; - if (type == "JSON.Raw") { + if (type.includes("JSON.Raw")) { mem.flags.set(PropertyFlags.JSON_Raw, []); } + if (member.type.isNullable) { + mem.flags.set(PropertyFlags.Null, []); + } + if (member.decorators) { for (const decorator of member.decorators) { const decoratorName = (decorator.name as IdentifierExpression).text; @@ -143,7 +147,7 @@ class JSONTransform extends BaseVisitor { if (!args.length) throw new Error( "Expected 1 argument but got zero at @alias in " + - node.range.source.normalizedPath, + node.range.source.normalizedPath, ); mem.alias = args[0]!; mem.flags.set(PropertyFlags.Alias, args); @@ -157,7 +161,7 @@ class JSONTransform extends BaseVisitor { if (!decorator.args?.length) throw new Error( "Expected 1 argument but got zero at @omitif in " + - node.range.source.normalizedPath, + node.range.source.normalizedPath, ); mem.flags.set(PropertyFlags.OmitIf, args); break; @@ -268,8 +272,8 @@ class JSONTransform extends BaseVisitor { SERIALIZE_PRETTY += "`;\n store(changetype(out) + ((out.length - 2) << 1), 8192010);\n return out;\n}"; } else { - SERIALIZE_RAW += "`;\n};"; - SERIALIZE_PRETTY += "`;\n};"; + SERIALIZE_RAW += "}`;\n return out;\n}"; + SERIALIZE_PRETTY += "}`;\n return out;\n}"; } INITIALIZE += " return this;\n}"; @@ -353,11 +357,11 @@ class JSONTransform extends BaseVisitor { } else { if (f) { f = false; - DESERIALIZE += ` if (0 == memory.compare(changetype("${escapeQuote(escapeSlash(name))}"), changetype(data) + (key_start << 1), ${name.length << 1})) {\n ${member.deserialize}\n return true;\n }\n`; + DESERIALIZE += ` if (0 === memory.compare(changetype("${escapeQuote(escapeSlash(name))}"), changetype(data) + (key_start << 1), ${name.length << 1})) {\n ${member.deserialize}\n return true;\n }\n`; } else { DESERIALIZE = DESERIALIZE.slice(0, DESERIALIZE.length - 1) + - ` else if (0 == memory.compare(changetype("${escapeQuote(escapeSlash(name))}"), changetype(data) + (key_start << 1), ${name.length << 1})) {\n ${member.deserialize}\n return true;\n }\n`; + ` else if (0 === memory.compare(changetype("${escapeQuote(escapeSlash(name))}"), changetype(data) + (key_start << 1), ${name.length << 1})) {\n ${member.deserialize}\n return true;\n }\n`; } } } @@ -456,6 +460,7 @@ export default class Transformer extends Transform { } enum PropertyFlags { + Null, Omit, OmitNull, OmitIf, @@ -489,8 +494,13 @@ class Property { if (this.flags.has(PropertyFlags.Omit)) return; if (this.flags.has(PropertyFlags.JSON_Raw)) { - this.right_s = "this." + name; - this.right_d = "data.substring(value_start, value_end);"; + if (this.flags.has(PropertyFlags.Null)) { + this.right_s = "(this." + name + " || \"null\")"; + this.right_d = "value_start === value_end - 4 && 30399761348886638 === load(changetype(data) + (value_start << 1)) ? null : data.substring(value_start, value_end)"; + } else { + this.right_s = "this." + name; + this.right_d = "data.substring(value_start, value_end);"; + } } else { this.right_s = "__SERIALIZE<" + type + ">(this." + name + ")"; this.right_d =