json-as 1.0.0-alpha.3 → 1.0.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/CHANGELOG +14 -0
  2. package/README.md +76 -59
  3. package/assembly/__benches__/misc.bench.ts +48 -0
  4. package/assembly/__benches__/schemas.ts +25 -0
  5. package/assembly/__tests__/arbitrary.spec.ts +19 -0
  6. package/assembly/__tests__/box.spec.ts +37 -0
  7. package/assembly/__tests__/date.spec.ts +38 -0
  8. package/assembly/__tests__/types.ts +3 -3
  9. package/assembly/deserialize/simd/string.ts +1 -1
  10. package/assembly/deserialize/simple/arbitrary.ts +1 -1
  11. package/assembly/deserialize/simple/array/arbitrary.ts +47 -24
  12. package/assembly/deserialize/simple/array/{object.ts → struct.ts} +1 -1
  13. package/assembly/deserialize/simple/array.ts +4 -9
  14. package/assembly/deserialize/simple/bool.ts +4 -7
  15. package/assembly/deserialize/simple/date.ts +2 -2
  16. package/assembly/deserialize/simple/integer.ts +2 -1
  17. package/assembly/deserialize/simple/map.ts +1 -1
  18. package/assembly/deserialize/simple/object.ts +13 -17
  19. package/assembly/deserialize/simple/struct.ts +158 -0
  20. package/assembly/index.ts +143 -24
  21. package/assembly/serialize/simd/string.ts +11 -11
  22. package/assembly/serialize/simple/arbitrary.ts +15 -2
  23. package/assembly/serialize/simple/array.ts +4 -3
  24. package/assembly/serialize/simple/float.ts +1 -1
  25. package/assembly/serialize/simple/integer.ts +7 -2
  26. package/assembly/serialize/simple/object.ts +43 -6
  27. package/assembly/serialize/simple/struct.ts +7 -0
  28. package/assembly/test.ts +84 -4
  29. package/assembly/util/atoi.ts +1 -1
  30. package/assembly/util/snp.ts +2 -2
  31. package/bench.js +11 -2
  32. package/modules/as-bs/assembly/index.ts +63 -32
  33. package/modules/as-bs/assembly/state.ts +8 -0
  34. package/package.json +7 -6
  35. package/transform/lib/builder.js +1340 -1262
  36. package/transform/lib/index.js +577 -512
  37. package/transform/lib/index.js.map +1 -1
  38. package/transform/lib/linker.js +12 -10
  39. package/transform/lib/types.js +19 -19
  40. package/transform/lib/util.js +34 -34
  41. package/transform/lib/visitor.js +529 -526
  42. package/transform/src/index.ts +25 -23
@@ -8,566 +8,631 @@ import { Property, PropertyFlags, Schema } from "./types.js";
8
8
  import { getClasses, getImportedClass } from "./linker.js";
9
9
  let indent = " ";
10
10
  class JSONTransform extends Visitor {
11
- parser;
12
- schemas = [];
13
- schema;
14
- sources = new Set();
15
- imports = [];
16
- jsonImport = null;
17
- bsImport = null;
18
- newStmts = { simd: [] };
19
- visitClassDeclaration(node) {
20
- if (!node.decorators?.length) return;
21
- if (
22
- !node.decorators.some((decorator) => {
23
- const name = decorator.name.text;
24
- return name === "json" || name === "serializable";
25
- })
26
- )
27
- return;
28
- this.schema = new Schema();
29
- this.schema.node = node;
30
- this.schema.name = node.name.text;
31
- this.schemas.push(this.schema);
32
- if (process.env["JSON_DEBUG"]) console.log("Created schema: " + this.schema.name);
33
- const members = [...node.members.filter((v) => v.kind === 54 && v.flags !== 32 && v.flags !== 512 && v.flags !== 1024 && !v.decorators?.some((decorator) => decorator.name.text === "omit"))];
34
- if (node.extendsType) {
35
- const extendsName = node.extendsType?.name.identifier.text;
36
- this.schema.parent = this.schemas.find((v) => v.name == extendsName);
37
- if (!this.schema.parent) {
38
- const internalSearch = getClasses(node.range.source).find((v) => v.name.text == extendsName);
39
- if (internalSearch) {
40
- if (process.env["JSON_DEBUG"]) console.log("Found " + extendsName + " internally");
41
- this.visitClassDeclaration(internalSearch);
42
- this.visitClassDeclaration(node);
43
- return;
11
+ parser;
12
+ schemas = [];
13
+ schema;
14
+ sources = new Set();
15
+ imports = [];
16
+ jsonImport = null;
17
+ bsImport = null;
18
+ newStmts = { simd: [] };
19
+ visitClassDeclaration(node) {
20
+ if (!node.decorators?.length)
21
+ return;
22
+ if (!node.decorators.some((decorator) => {
23
+ const name = decorator.name.text;
24
+ return name === "json" || name === "serializable";
25
+ }))
26
+ return;
27
+ this.schema = new Schema();
28
+ this.schema.node = node;
29
+ this.schema.name = node.name.text;
30
+ this.schemas.push(this.schema);
31
+ if (process.env["JSON_DEBUG"])
32
+ console.log("Created schema: " + this.schema.name);
33
+ const members = [...node.members.filter((v) => v.kind === 54 && v.flags !== 32 && v.flags !== 512 && v.flags !== 1024 && !v.decorators?.some((decorator) => decorator.name.text === "omit"))];
34
+ if (node.extendsType) {
35
+ const extendsName = node.extendsType?.name.identifier.text;
36
+ this.schema.parent = this.schemas.find((v) => v.name == extendsName);
37
+ if (!this.schema.parent) {
38
+ const internalSearch = getClasses(node.range.source).find((v) => v.name.text == extendsName);
39
+ if (internalSearch) {
40
+ if (process.env["JSON_DEBUG"])
41
+ console.log("Found " + extendsName + " internally");
42
+ this.visitClassDeclaration(internalSearch);
43
+ this.visitClassDeclaration(node);
44
+ return;
45
+ }
46
+ const externalSearch = getImportedClass(extendsName, node.range.source, this.parser);
47
+ if (externalSearch) {
48
+ if (process.env["JSON_DEBUG"])
49
+ console.log("Found " + extendsName + " externally");
50
+ this.visitClassDeclaration(externalSearch);
51
+ this.visitClassDeclaration(node);
52
+ return;
53
+ }
54
+ }
55
+ if (this.schema.parent?.members) {
56
+ for (let i = this.schema.parent.members.length - 1; i >= 0; i--) {
57
+ const replace = this.schema.members.find((v) => v.name == this.schema.parent?.members[i]?.name);
58
+ if (!replace) {
59
+ members.unshift(this.schema.parent?.members[i].node);
60
+ }
61
+ }
62
+ }
44
63
  }
45
- const externalSearch = getImportedClass(extendsName, node.range.source, this.parser);
46
- if (externalSearch) {
47
- if (process.env["JSON_DEBUG"]) console.log("Found " + extendsName + " externally");
48
- this.visitClassDeclaration(externalSearch);
49
- this.visitClassDeclaration(node);
50
- return;
64
+ if (!members.length) {
65
+ this.generateEmptyMethods(node);
66
+ return;
51
67
  }
52
- }
53
- if (this.schema.parent?.members) {
54
- for (let i = this.schema.parent.members.length - 1; i >= 0; i--) {
55
- const replace = this.schema.members.find((v) => v.name == this.schema.parent?.members[i]?.name);
56
- if (!replace) {
57
- members.unshift(this.schema.parent?.members[i].node);
58
- }
68
+ this.addRequiredImports(node);
69
+ for (const member of members) {
70
+ if (!member.type)
71
+ throwError("Fields must be strongly typed", node.range);
72
+ const type = toString(member.type);
73
+ const name = member.name;
74
+ const value = member.initializer ? toString(member.initializer) : null;
75
+ if (type.startsWith("(") && type.includes("=>"))
76
+ continue;
77
+ const mem = new Property();
78
+ mem.name = name.text;
79
+ mem.type = type;
80
+ mem.value = value;
81
+ mem.node = member;
82
+ mem.byteSize = sizeof(mem.type);
83
+ this.schema.byteSize += mem.byteSize;
84
+ if (type.includes("JSON.Raw"))
85
+ mem.flags.set(PropertyFlags.Raw, null);
86
+ if (member.decorators) {
87
+ for (const decorator of member.decorators) {
88
+ const decoratorName = decorator.name.text.toLowerCase().trim();
89
+ switch (decoratorName) {
90
+ case "alias": {
91
+ const args = getArgs(decorator.args);
92
+ if (!args.length)
93
+ throwError("@alias must have an argument of type string or number", member.range);
94
+ mem.alias = args[0];
95
+ break;
96
+ }
97
+ case "omitif": {
98
+ let arg = decorator.args[0];
99
+ if (!decorator.args?.length)
100
+ throwError("@omitif must have an argument or callback that resolves to type bool", member.range);
101
+ mem.flags.set(PropertyFlags.OmitIf, arg);
102
+ this.schema.static = false;
103
+ break;
104
+ }
105
+ case "omitnull": {
106
+ if (isPrimitive(type)) {
107
+ throwError("@omitnull cannot be used on primitive types!", member.range);
108
+ }
109
+ else if (!member.type.isNullable) {
110
+ throwError("@omitnull cannot be used on non-nullable types!", member.range);
111
+ }
112
+ mem.flags.set(PropertyFlags.OmitNull, null);
113
+ this.schema.static = false;
114
+ break;
115
+ }
116
+ }
117
+ }
118
+ }
119
+ this.schema.members.push(mem);
59
120
  }
60
- }
61
- }
62
- if (!members.length) {
63
- this.generateEmptyMethods(node);
64
- return;
65
- }
66
- this.addRequiredImports(node);
67
- for (const member of members) {
68
- if (!member.type) throwError("Fields must be strongly typed", node.range);
69
- const type = toString(member.type);
70
- const name = member.name;
71
- const value = member.initializer ? toString(member.initializer) : null;
72
- if (type.startsWith("(") && type.includes("=>")) continue;
73
- const mem = new Property();
74
- mem.name = name.text;
75
- mem.type = type;
76
- mem.value = value;
77
- mem.node = member;
78
- mem.byteSize = sizeof(mem.type);
79
- this.schema.byteSize += mem.byteSize;
80
- if (type.includes("JSON.Raw")) mem.flags.set(PropertyFlags.Raw, null);
81
- if (member.decorators) {
82
- for (const decorator of member.decorators) {
83
- const decoratorName = decorator.name.text.toLowerCase().trim();
84
- switch (decoratorName) {
85
- case "alias": {
86
- const args = getArgs(decorator.args);
87
- if (!args.length) throwError("@alias must have an argument of type string or number", member.range);
88
- mem.alias = args[0];
89
- break;
121
+ if (!this.schema.static)
122
+ this.schema.members = sortMembers(this.schema.members);
123
+ let SERIALIZE = "__SERIALIZE(ptr: usize): void {\n";
124
+ let INITIALIZE = "@inline __INITIALIZE(): this {\n";
125
+ let DESERIALIZE = "__DESERIALIZE(keyStart: usize, keyEnd: usize, valStart: usize, valEnd: usize, ptr: usize): void {\n switch (<u32>keyEnd - <u32>keyStart) {\n";
126
+ indent = " ";
127
+ if (this.schema.static == false) {
128
+ if (this.schema.members.some((v) => v.flags.has(PropertyFlags.OmitNull))) {
129
+ SERIALIZE += indent + "let block: usize = 0;\n";
130
+ }
131
+ this.schema.byteSize += 2;
132
+ SERIALIZE += indent + "store<u16>(bs.offset, 123, 0); // {\n";
133
+ SERIALIZE += indent + "bs.offset += 2;\n";
134
+ }
135
+ for (const member of this.schema.members) {
136
+ const nonNullType = member.type.replace(" | null", "");
137
+ if (!isPrimitive(nonNullType)) {
138
+ const schema = this.schemas.find((v) => v.name == nonNullType);
139
+ if (schema && !this.schema.deps.includes(schema)) {
140
+ this.schema.deps.push(schema);
141
+ this.schema.byteSize += schema.byteSize;
142
+ }
143
+ }
144
+ }
145
+ let isPure = this.schema.static;
146
+ let isRegular = isPure;
147
+ let isFirst = true;
148
+ for (let i = 0; i < this.schema.members.length; i++) {
149
+ const member = this.schema.members[i];
150
+ const aliasName = JSON.stringify(member.alias || member.name);
151
+ const realName = member.name;
152
+ const isLast = i == this.schema.members.length - 1;
153
+ const nonNullType = member.type.replace(" | null", "");
154
+ if (member.value) {
155
+ INITIALIZE += ` this.${member.name} = ${member.value};\n`;
156
+ }
157
+ else if (this.schemas.find((v) => nonNullType == v.name)) {
158
+ INITIALIZE += ` this.${member.name} = changetype<nonnull<${member.type}>>(__new(offsetof<nonnull<${member.type}>>(), idof<nonnull<${member.type}>>())).__INITIALIZE();\n`;
159
+ }
160
+ else if (member.type.startsWith("Array<") || member.type.startsWith("Map<")) {
161
+ INITIALIZE += ` this.${member.name} = [];\n`;
90
162
  }
91
- case "omitif": {
92
- let arg = decorator.args[0];
93
- if (!decorator.args?.length) throwError("@omitif must have an argument or callback that resolves to type bool", member.range);
94
- mem.flags.set(PropertyFlags.OmitIf, arg);
95
- this.schema.static = false;
96
- break;
163
+ else if (member.type == "string" || member.type == "String" || member.type == "JSON.Raw") {
164
+ INITIALIZE += ` this.${member.name} = "";\n`;
97
165
  }
98
- case "omitnull": {
99
- if (isPrimitive(type)) {
100
- throwError("@omitnull cannot be used on primitive types!", member.range);
101
- } else if (!member.type.isNullable) {
102
- throwError("@omitnull cannot be used on non-nullable types!", member.range);
103
- }
104
- mem.flags.set(PropertyFlags.OmitNull, null);
105
- this.schema.static = false;
106
- break;
166
+ if (!isRegular && !member.flags.has(PropertyFlags.OmitIf) && !member.flags.has(PropertyFlags.OmitNull))
167
+ isRegular = true;
168
+ if (isRegular && isPure) {
169
+ const keyPart = (isFirst ? "{" : ",") + aliasName + ":";
170
+ this.schema.byteSize += keyPart.length << 1;
171
+ SERIALIZE += this.getStores(keyPart)
172
+ .map((v) => indent + v + "\n")
173
+ .join("");
174
+ SERIALIZE += indent + `JSON.__serialize<${member.type}>(load<${member.type}>(ptr, offsetof<this>(${JSON.stringify(realName)})));\n`;
175
+ if (isFirst)
176
+ isFirst = false;
177
+ }
178
+ else if (isRegular && !isPure) {
179
+ const keyPart = (isFirst ? "" : ",") + aliasName + ":";
180
+ this.schema.byteSize += keyPart.length << 1;
181
+ SERIALIZE += this.getStores(keyPart)
182
+ .map((v) => indent + v + "\n")
183
+ .join("");
184
+ SERIALIZE += indent + `JSON.__serialize<${member.type}>(load<${member.type}>(ptr, offsetof<this>(${JSON.stringify(realName)})));\n`;
185
+ if (isFirst)
186
+ isFirst = false;
187
+ }
188
+ else {
189
+ if (member.flags.has(PropertyFlags.OmitNull)) {
190
+ SERIALIZE += indent + `if ((block = load<usize>(ptr, offsetof<this>(${JSON.stringify(realName)}))) !== 0) {\n`;
191
+ indentInc();
192
+ const keyPart = aliasName + ":";
193
+ this.schema.byteSize += keyPart.length << 1;
194
+ SERIALIZE += this.getStores(keyPart)
195
+ .map((v) => indent + v + "\n")
196
+ .join("");
197
+ SERIALIZE += indent + `JSON.__serialize<${member.type}>(load<${member.type}>(ptr, offsetof<this>(${JSON.stringify(realName)})));\n`;
198
+ if (!isLast) {
199
+ this.schema.byteSize += 2;
200
+ SERIALIZE += indent + `store<u16>(bs.offset, 44, 0); // ,\n`;
201
+ SERIALIZE += indent + `bs.offset += 2;\n`;
202
+ }
203
+ indentDec();
204
+ this.schema.byteSize += 2;
205
+ SERIALIZE += indent + `}\n`;
206
+ }
207
+ else if (member.flags.has(PropertyFlags.OmitIf)) {
208
+ if (member.flags.get(PropertyFlags.OmitIf).kind == 14) {
209
+ const arg = member.flags.get(PropertyFlags.OmitIf);
210
+ arg.declaration.signature.parameters[0].type = Node.createNamedType(Node.createSimpleTypeName("this", node.range), null, false, node.range);
211
+ arg.declaration.signature.returnType.name = Node.createSimpleTypeName("boolean", arg.declaration.signature.returnType.name.range);
212
+ SERIALIZE += indent + `if (!(${toString(member.flags.get(PropertyFlags.OmitIf))})(this)) {\n`;
213
+ }
214
+ else {
215
+ SERIALIZE += indent + `if (${toString(member.flags.get(PropertyFlags.OmitIf))}) {\n`;
216
+ }
217
+ indentInc();
218
+ SERIALIZE += this.getStores(aliasName + ":")
219
+ .map((v) => indent + v + "\n")
220
+ .join("");
221
+ SERIALIZE += indent + `JSON.__serialize<${member.type}>(load<${member.type}>(ptr, offsetof<this>(${JSON.stringify(realName)})));\n`;
222
+ if (!isLast) {
223
+ this.schema.byteSize += 2;
224
+ SERIALIZE += indent + `store<u16>(bs.offset, 44, 0); // ,\n`;
225
+ SERIALIZE += indent + `bs.offset += 2;\n`;
226
+ }
227
+ indentDec();
228
+ SERIALIZE += indent + `}\n`;
229
+ }
107
230
  }
108
- }
109
231
  }
110
- }
111
- this.schema.members.push(mem);
112
- }
113
- if (!this.schema.static) this.schema.members = sortMembers(this.schema.members);
114
- let SERIALIZE = "__SERIALIZE(ptr: usize): void {\n";
115
- let INITIALIZE = "@inline __INITIALIZE(): this {\n";
116
- let DESERIALIZE = "__DESERIALIZE(keyStart: usize, keyEnd: usize, valStart: usize, valEnd: usize, ptr: usize): void {\n switch (<u32>keyEnd - <u32>keyStart) {\n";
117
- let ALLOCATE = "@inline __ALLOCATE(): void {\n";
118
- indent = " ";
119
- if (this.schema.static == false) {
120
- if (this.schema.members.some((v) => v.flags.has(PropertyFlags.OmitNull))) {
121
- SERIALIZE += indent + "let block: usize = 0;\n";
122
- }
123
- this.schema.byteSize += 2;
124
- SERIALIZE += indent + "store<u16>(bs.offset, 123, 0); // {\n";
125
- SERIALIZE += indent + "bs.offset += 2;\n";
126
- }
127
- for (const member of this.schema.members) {
128
- const nonNullType = member.type.replace(" | null", "");
129
- if (!isPrimitive(nonNullType)) {
130
- const schema = this.schemas.find((v) => v.name == nonNullType);
131
- if (schema && !this.schema.deps.includes(schema)) {
132
- this.schema.deps.push(schema);
133
- this.schema.byteSize += schema.byteSize;
232
+ let sortedMembers = [];
233
+ let len = -1;
234
+ this.schema.members
235
+ .slice()
236
+ .sort((a, b) => (a.alias?.length || a.name.length) - (b.alias?.length || b.name.length))
237
+ .forEach((member) => {
238
+ const _nameLength = member.alias?.length || member.name.length;
239
+ if (_nameLength === len) {
240
+ sortedMembers[sortedMembers.length - 1].push(member);
241
+ }
242
+ else {
243
+ sortedMembers.push([member]);
244
+ len = _nameLength;
245
+ }
246
+ });
247
+ sortedMembers = sortedMembers.sort((a, b) => b.length - a.length);
248
+ indentInc();
249
+ for (const memberGroup of sortedMembers) {
250
+ const memberLen = (memberGroup[0].alias || memberGroup[0].name).length << 1;
251
+ DESERIALIZE += `${indent}case ${memberLen}: {\n`;
252
+ indentInc();
253
+ if (memberLen == 2)
254
+ DESERIALIZE += `${indent}switch (load<u16>(keyStart)) {\n`;
255
+ else if (memberLen == 4)
256
+ DESERIALIZE += `${indent}switch (load<u32>(keyStart)) {\n`;
257
+ else if (memberLen == 6)
258
+ DESERIALIZE += `${indent}let code = load<u64>(keyStart) & 0x0000FFFFFFFFFFFF;\n`;
259
+ else if (memberLen == 6)
260
+ DESERIALIZE += `${indent}let code = load<u64>(keyStart);\n`;
261
+ else
262
+ DESERIALIZE += toMemCDecl(memberLen, indent);
263
+ for (let i = 0; i < memberGroup.length; i++) {
264
+ const member = memberGroup[i];
265
+ const memberName = member.alias || member.name;
266
+ const dst = this.schemas.find(v => v.name == member.type) ? "ptr + offsetof<this>(\"" + member.name + "\") + 12" : "0";
267
+ if (memberLen == 2) {
268
+ DESERIALIZE += `${indent} case ${memberName.charCodeAt(0)}: { // ${memberName}\n`;
269
+ DESERIALIZE += `${indent} store<${member.type}>(ptr, JSON.__deserialize<${member.type}>(valStart, valEnd, ${dst}), offsetof<this>(${JSON.stringify(member.name)}));\n`;
270
+ DESERIALIZE += `${indent} return;\n`;
271
+ DESERIALIZE += `${indent} }\n`;
272
+ }
273
+ else if (memberLen == 4) {
274
+ DESERIALIZE += `${indent} case ${toU32(memberName)}: { // ${memberName}\n`;
275
+ DESERIALIZE += `${indent} store<${member.type}>(ptr, JSON.__deserialize<${member.type}>(valStart, valEnd, ${dst}), offsetof<this>(${JSON.stringify(member.name)}));\n`;
276
+ DESERIALIZE += `${indent} return;\n`;
277
+ DESERIALIZE += `${indent} }\n`;
278
+ }
279
+ else if (memberLen == 6) {
280
+ DESERIALIZE += i == 0 ? indent : "";
281
+ DESERIALIZE += `if (code == ${toU48(memberName)}) { // ${memberName}\n`;
282
+ DESERIALIZE += `${indent} store<${member.type}>(ptr, JSON.__deserialize<${member.type}>(valStart, valEnd, ${dst}), offsetof<this>(${JSON.stringify(member.name)}));\n`;
283
+ DESERIALIZE += `${indent} return;\n`;
284
+ DESERIALIZE += `${indent}}${i < memberGroup.length - 1 ? " else " : "\n"}`;
285
+ }
286
+ else if (memberLen == 8) {
287
+ DESERIALIZE += i == 0 ? indent : "";
288
+ DESERIALIZE += `if (code == ${toU64(memberName)}) { // ${memberName}\n`;
289
+ DESERIALIZE += `${indent} store<${member.type}>(ptr, JSON.__deserialize<${member.type}>(valStart, valEnd, ${dst}), offsetof<this>(${JSON.stringify(member.name)}));\n`;
290
+ DESERIALIZE += `${indent} return;\n`;
291
+ DESERIALIZE += `${indent}}${i < memberGroup.length - 1 ? " else " : "\n"}`;
292
+ }
293
+ else {
294
+ DESERIALIZE += i == 0 ? indent : "";
295
+ DESERIALIZE += `if (${toMemCCheck(memberName)}) { // ${memberName}\n`;
296
+ DESERIALIZE += `${indent} store<${member.type}>(ptr, JSON.__deserialize<${member.type}>(valStart, valEnd, ${dst}), offsetof<this>(${JSON.stringify(member.name)}));\n`;
297
+ DESERIALIZE += `${indent} return;\n`;
298
+ DESERIALIZE += `${indent}}${i < memberGroup.length - 1 ? " else " : "\n"}`;
299
+ }
300
+ }
301
+ if (memberLen < 6) {
302
+ DESERIALIZE += `${indent}}\n`;
303
+ }
304
+ indentDec();
305
+ DESERIALIZE += `${indent} return;\n`;
306
+ DESERIALIZE += `${indent}}\n`;
134
307
  }
135
- }
136
- }
137
- let isPure = this.schema.static;
138
- let isRegular = isPure;
139
- let isFirst = true;
140
- for (let i = 0; i < this.schema.members.length; i++) {
141
- const member = this.schema.members[i];
142
- const aliasName = JSON.stringify(member.alias || member.name);
143
- const realName = member.name;
144
- const isLast = i == this.schema.members.length - 1;
145
- const nonNullType = member.type.replace(" | null", "");
146
- if (member.value) {
147
- INITIALIZE += ` this.${member.name} = ${member.value};\n`;
148
- } else if (this.schemas.find((v) => nonNullType == v.name)) {
149
- INITIALIZE += ` this.${member.name} = changetype<nonnull<${member.type}>>(__new(offsetof<nonnull<${member.type}>>(), idof<nonnull<${member.type}>>())).__INITIALIZE();\n`;
150
- } else if (member.type.startsWith("Array<") || member.type.startsWith("Map<")) {
151
- INITIALIZE += ` this.${member.name} = [];\n`;
152
- } else if (member.type == "string" || member.type == "String" || member.type == "JSON.Raw") {
153
- INITIALIZE += ` this.${member.name} = "";\n`;
154
- }
155
- if (!isRegular && !member.flags.has(PropertyFlags.OmitIf) && !member.flags.has(PropertyFlags.OmitNull)) isRegular = true;
156
- if (isRegular && isPure) {
157
- const keyPart = (isFirst ? "{" : ",") + aliasName + ":";
158
- this.schema.byteSize += keyPart.length << 1;
159
- SERIALIZE += this.getStores(keyPart)
160
- .map((v) => indent + v + "\n")
161
- .join("");
162
- SERIALIZE += indent + `JSON.__serialize<${member.type}>(load<${member.type}>(ptr, offsetof<this>(${JSON.stringify(realName)})));\n`;
163
- if (isFirst) isFirst = false;
164
- } else if (isRegular && !isPure) {
165
- const keyPart = (isFirst ? "" : ",") + aliasName + ":";
166
- this.schema.byteSize += keyPart.length << 1;
167
- SERIALIZE += this.getStores(keyPart)
168
- .map((v) => indent + v + "\n")
169
- .join("");
170
- SERIALIZE += indent + `JSON.__serialize<${member.type}>(load<${member.type}>(ptr, offsetof<this>(${JSON.stringify(realName)})));\n`;
171
- if (isFirst) isFirst = false;
172
- } else {
173
- if (member.flags.has(PropertyFlags.OmitNull)) {
174
- SERIALIZE += indent + `if ((block = load<usize>(ptr, offsetof<this>(${JSON.stringify(realName)}))) !== 0) {\n`;
175
- indentInc();
176
- const keyPart = aliasName + ":";
177
- this.schema.byteSize += keyPart.length << 1;
178
- SERIALIZE += this.getStores(keyPart)
179
- .map((v) => indent + v + "\n")
180
- .join("");
181
- SERIALIZE += indent + `JSON.__serialize<${member.type}>(load<${member.type}>(ptr, offsetof<this>(${JSON.stringify(realName)})));\n`;
182
- if (!isLast) {
183
- this.schema.byteSize += 2;
184
- SERIALIZE += indent + `store<u16>(bs.offset, 44, 0); // ,\n`;
185
- SERIALIZE += indent + `bs.offset += 2;\n`;
186
- }
187
- indentDec();
188
- this.schema.byteSize += 2;
189
- SERIALIZE += indent + `}\n`;
190
- } else if (member.flags.has(PropertyFlags.OmitIf)) {
191
- if (member.flags.get(PropertyFlags.OmitIf).kind == 14) {
192
- const arg = member.flags.get(PropertyFlags.OmitIf);
193
- arg.declaration.signature.returnType.name = Node.createSimpleTypeName("boolean", arg.declaration.signature.returnType.name.range);
194
- SERIALIZE += indent + `if (!(${toString(member.flags.get(PropertyFlags.OmitIf))})(this)) {\n`;
195
- } else {
196
- SERIALIZE += indent + `if (${toString(member.flags.get(PropertyFlags.OmitIf))}) {\n`;
197
- }
198
- indentInc();
199
- SERIALIZE += this.getStores(aliasName + ":")
200
- .map((v) => indent + v + "\n")
201
- .join("");
202
- SERIALIZE += indent + `JSON.__serialize<${member.type}>(load<${member.type}>(ptr, offsetof<this>(${JSON.stringify(realName)})));\n`;
203
- if (!isLast) {
204
- this.schema.byteSize += 2;
205
- SERIALIZE += indent + `store<u16>(bs.offset, 44, 0); // ,\n`;
206
- SERIALIZE += indent + `bs.offset += 2;\n`;
207
- }
208
- indentDec();
209
- SERIALIZE += indent + `}\n`;
308
+ indentDec();
309
+ DESERIALIZE += `${indent}}\n`;
310
+ indentDec();
311
+ DESERIALIZE += `${indent}}\n`;
312
+ indent = " ";
313
+ this.schema.byteSize += 2;
314
+ SERIALIZE += indent + "store<u16>(bs.offset, 125, 0); // }\n";
315
+ SERIALIZE += indent + "bs.offset += 2;\n";
316
+ SERIALIZE += "}";
317
+ SERIALIZE = SERIALIZE.slice(0, 32) + indent + "bs.proposeSize(" + this.schema.byteSize + ");\n" + SERIALIZE.slice(32);
318
+ INITIALIZE += " return this;\n";
319
+ INITIALIZE += "}";
320
+ if (process.env["JSON_DEBUG"]) {
321
+ console.log(SERIALIZE);
322
+ console.log(INITIALIZE);
323
+ console.log(DESERIALIZE);
210
324
  }
211
- }
325
+ const SERIALIZE_METHOD = SimpleParser.parseClassMember(SERIALIZE, node);
326
+ const INITIALIZE_METHOD = SimpleParser.parseClassMember(INITIALIZE, node);
327
+ const DESERIALIZE_METHOD = SimpleParser.parseClassMember(DESERIALIZE, node);
328
+ if (!node.members.find((v) => v.name.text == "__SERIALIZE"))
329
+ node.members.push(SERIALIZE_METHOD);
330
+ if (!node.members.find((v) => v.name.text == "__INITIALIZE"))
331
+ node.members.push(INITIALIZE_METHOD);
332
+ if (!node.members.find((v) => v.name.text == "__DESERIALIZE"))
333
+ node.members.push(DESERIALIZE_METHOD);
334
+ super.visitClassDeclaration(node);
212
335
  }
213
- let sortedMembers = [];
214
- let len = -1;
215
- this.schema.members
216
- .slice()
217
- .sort((a, b) => (a.alias?.length || a.name.length) - (b.alias?.length || b.name.length))
218
- .forEach((member) => {
219
- const _nameLength = member.alias?.length || member.name.length;
220
- if (_nameLength === len) {
221
- sortedMembers[sortedMembers.length - 1].push(member);
222
- } else {
223
- sortedMembers.push([member]);
224
- len = _nameLength;
225
- }
226
- });
227
- sortedMembers = sortedMembers.sort((a, b) => b.length - a.length);
228
- indentInc();
229
- for (const memberGroup of sortedMembers) {
230
- const memberLen = (memberGroup[0].alias || memberGroup[0].name).length << 1;
231
- DESERIALIZE += `${indent}case ${memberLen}: {\n`;
232
- indentInc();
233
- if (memberLen == 2) DESERIALIZE += `${indent}switch (load<u16>(keyStart)) {\n`;
234
- else if (memberLen == 4) DESERIALIZE += `${indent}switch (load<u32>(keyStart)) {\n`;
235
- else if (memberLen == 6) DESERIALIZE += `${indent}let code = (<u64>load<u32>(keyStart) << 16) | <u64>load<u16>(keyStart, 4);\n`;
236
- else DESERIALIZE += toMemCDecl(memberLen, indent);
237
- for (let i = 0; i < memberGroup.length; i++) {
238
- const member = memberGroup[i];
239
- const memberName = member.alias || member.name;
240
- if (memberLen == 2) {
241
- DESERIALIZE += `${indent} case ${memberName.charCodeAt(0)}: { // ${memberName}\n`;
242
- DESERIALIZE += `${indent} store<${member.type}>(ptr, JSON.__deserialize<${member.type}>(valStart, valEnd), offsetof<this>(${JSON.stringify(member.name)}));\n`;
243
- DESERIALIZE += `${indent} return;\n`;
244
- DESERIALIZE += `${indent} }\n`;
245
- } else if (memberLen == 4) {
246
- DESERIALIZE += `${indent} case ${toU32(memberName)}: { // ${memberName}\n`;
247
- DESERIALIZE += `${indent} store<${member.type}>(ptr, JSON.__deserialize<${member.type}>(valStart, valEnd), offsetof<this>(${JSON.stringify(member.name)}));\n`;
248
- DESERIALIZE += `${indent} return;\n`;
249
- DESERIALIZE += `${indent} }\n`;
250
- } else if (memberLen == 6) {
251
- DESERIALIZE += i == 0 ? indent : "";
252
- DESERIALIZE += `if (code == ${toU48(memberName)}) { // ${memberName}\n`;
253
- DESERIALIZE += `${indent} store<${member.type}>(ptr, JSON.__deserialize<${member.type}>(valStart, valEnd), offsetof<this>(${JSON.stringify(member.name)}));\n`;
254
- DESERIALIZE += `${indent} return;\n`;
255
- DESERIALIZE += `${indent}}${i < memberGroup.length - 1 ? " else " : "\n"}`;
256
- } else {
257
- DESERIALIZE += i == 0 ? indent : "";
258
- DESERIALIZE += `if (${toMemCCheck(memberName)}) { // ${memberName}\n`;
259
- DESERIALIZE += `${indent} store<${member.type}>(ptr, JSON.__deserialize<${member.type}>(valStart, valEnd), offsetof<this>(${JSON.stringify(member.name)}));\n`;
260
- DESERIALIZE += `${indent} return;\n`;
261
- DESERIALIZE += `${indent}}${i < memberGroup.length - 1 ? " else " : "\n"}`;
336
+ generateEmptyMethods(node) {
337
+ let SERIALIZE_EMPTY = "@inline __SERIALIZE(ptr: usize): void {\n bs.proposeSize(4);\n store<u32>(bs.offset, 8192123);\n bs.offset += 4;\n}";
338
+ let INITIALIZE_EMPTY = "@inline __INITIALIZE(): this {\n return this;\n}";
339
+ let DESERIALIZE_EMPTY = "@inline __DESERIALIZE(keyStart: usize, keyEnd: usize, valStart: usize, valEnd: usize, ptr: usize): void {\n return false;\n}";
340
+ if (process.env["JSON_DEBUG"]) {
341
+ console.log(SERIALIZE_EMPTY);
342
+ console.log(INITIALIZE_EMPTY);
343
+ console.log(DESERIALIZE_EMPTY);
262
344
  }
263
- }
264
- if (memberLen < 6) {
265
- DESERIALIZE += `${indent}}\n`;
266
- }
267
- indentDec();
268
- DESERIALIZE += `${indent} return;\n`;
269
- DESERIALIZE += `${indent}}\n`;
270
- }
271
- indentDec();
272
- DESERIALIZE += `${indent}}\n`;
273
- indentDec();
274
- DESERIALIZE += `${indent}}\n`;
275
- indent = " ";
276
- this.schema.byteSize += 2;
277
- SERIALIZE += indent + "store<u16>(bs.offset, 125, 0); // }\n";
278
- SERIALIZE += indent + "bs.offset += 2;\n";
279
- SERIALIZE += "}";
280
- ALLOCATE += indent + "bs.proposeSize(" + this.schema.byteSize + ");\n";
281
- ALLOCATE += "}";
282
- INITIALIZE += " return this;\n";
283
- INITIALIZE += "}";
284
- if (process.env["JSON_DEBUG"]) {
285
- console.log(SERIALIZE);
286
- console.log(INITIALIZE);
287
- console.log(DESERIALIZE);
288
- console.log(ALLOCATE);
345
+ const SERIALIZE_METHOD_EMPTY = SimpleParser.parseClassMember(SERIALIZE_EMPTY, node);
346
+ const INITIALIZE_METHOD_EMPTY = SimpleParser.parseClassMember(INITIALIZE_EMPTY, node);
347
+ const DESERIALIZE_METHOD_EMPTY = SimpleParser.parseClassMember(DESERIALIZE_EMPTY, node);
348
+ if (!node.members.find((v) => v.name.text == "__SERIALIZE"))
349
+ node.members.push(SERIALIZE_METHOD_EMPTY);
350
+ if (!node.members.find((v) => v.name.text == "__INITIALIZE"))
351
+ node.members.push(INITIALIZE_METHOD_EMPTY);
352
+ if (!node.members.find((v) => v.name.text == "__DESERIALIZE"))
353
+ node.members.push(DESERIALIZE_METHOD_EMPTY);
289
354
  }
290
- const SERIALIZE_METHOD = SimpleParser.parseClassMember(SERIALIZE, node);
291
- const INITIALIZE_METHOD = SimpleParser.parseClassMember(INITIALIZE, node);
292
- const DESERIALIZE_METHOD = SimpleParser.parseClassMember(DESERIALIZE, node);
293
- const ALLOCATE_METHOD = SimpleParser.parseClassMember(ALLOCATE, node);
294
- if (!node.members.find((v) => v.name.text == "__SERIALIZE")) node.members.push(SERIALIZE_METHOD);
295
- if (!node.members.find((v) => v.name.text == "__INITIALIZE")) node.members.push(INITIALIZE_METHOD);
296
- if (!node.members.find((v) => v.name.text == "__DESERIALIZE")) node.members.push(DESERIALIZE_METHOD);
297
- if (!node.members.find((v) => v.name.text == "__ALLOCATE")) node.members.push(ALLOCATE_METHOD);
298
- super.visitClassDeclaration(node);
299
- }
300
- generateEmptyMethods(node) {
301
- let SERIALIZE_RAW_EMPTY = '@inline __SERIALIZE(ptr: usize = changetype<usize>(this)): string {\n return "{}";\n}';
302
- let SERIALIZE_BS_EMPTY = "@inline __SERIALIZE(ptr: usize: bool): void {\n store<u32>(bs.offset, 8192123);\n bs.offset += 4;\n}";
303
- let INITIALIZE_EMPTY = "@inline __INITIALIZE(): this {\n return this;\n}";
304
- let DESERIALIZE_EMPTY = "@inline __DESERIALIZE(keyStart: usize, keyEnd: usize, valStart: usize, valEnd: usize, ptr: usize): void {\n return false;\n}";
305
- let ALLOCATE_EMPTY = "@inline __ALLOCATE(): void {\n bs.ensureSize(4);\n}";
306
- if (process.env["JSON_DEBUG"]) {
307
- console.log(SERIALIZE_RAW_EMPTY);
308
- console.log(SERIALIZE_BS_EMPTY);
309
- console.log(INITIALIZE_EMPTY);
310
- console.log(DESERIALIZE_EMPTY);
311
- console.log(ALLOCATE_EMPTY);
355
+ visitImportStatement(node) {
356
+ super.visitImportStatement(node);
357
+ const source = this.parser.sources.find((src) => src.internalPath == node.internalPath);
358
+ if (!source)
359
+ return;
360
+ if (source.statements.some((stmt) => stmt.kind === 59 && stmt.name.text === "JSON"))
361
+ this.imports.push(node);
312
362
  }
313
- const SERIALIZE_RAW_METHOD_EMPTY = SimpleParser.parseClassMember(SERIALIZE_RAW_EMPTY, node);
314
- const SERIALIZE_BS_METHOD_EMPTY = SimpleParser.parseClassMember(SERIALIZE_BS_EMPTY, node);
315
- const INITIALIZE_METHOD_EMPTY = SimpleParser.parseClassMember(INITIALIZE_EMPTY, node);
316
- const DESERIALIZE_METHOD_EMPTY = SimpleParser.parseClassMember(DESERIALIZE_EMPTY, node);
317
- const ALLOCATE_METHOD_EMPTY = SimpleParser.parseClassMember(ALLOCATE_EMPTY, node);
318
- if (!node.members.find((v) => v.name.text == "__SERIALIZE")) node.members.push(SERIALIZE_RAW_METHOD_EMPTY);
319
- if (!node.members.find((v) => v.name.text == "__SERIALIZE")) node.members.push(SERIALIZE_BS_METHOD_EMPTY);
320
- if (!node.members.find((v) => v.name.text == "__INITIALIZE")) node.members.push(INITIALIZE_METHOD_EMPTY);
321
- if (!node.members.find((v) => v.name.text == "__DESERIALIZE")) node.members.push(DESERIALIZE_METHOD_EMPTY);
322
- if (!node.members.find((v) => v.name.text == "__ALLOCATE")) node.members.push(ALLOCATE_METHOD_EMPTY);
323
- }
324
- visitImportStatement(node) {
325
- super.visitImportStatement(node);
326
- const source = this.parser.sources.find((src) => src.internalPath == node.internalPath);
327
- if (!source) return;
328
- if (source.statements.some((stmt) => stmt.kind === 59 && stmt.name.text === "JSON")) this.imports.push(node);
329
- }
330
- visitSource(node) {
331
- this.imports = [];
332
- super.visitSource(node);
333
- }
334
- addRequiredImports(node) {
335
- if (!this.imports.find((i) => i.declarations.find((d) => d.foreignName.text == "bs"))) {
336
- const __filename = fileURLToPath(import.meta.url);
337
- const __dirname = path.dirname(__filename);
338
- let relativePath = path.relative(path.dirname(node.range.source.normalizedPath), path.resolve(__dirname, "../../modules/as-bs/"));
339
- if (!relativePath.startsWith(".") && !relativePath.startsWith("/")) relativePath = "./" + relativePath;
340
- const txt = `import { bs } from "${relativePath}";`;
341
- if (!this.bsImport) {
342
- this.bsImport = txt;
343
- if (process.env["JSON_DEBUG"]) console.log("Added as-bs import: " + txt + "\n");
344
- }
363
+ visitSource(node) {
364
+ this.imports = [];
365
+ super.visitSource(node);
345
366
  }
346
- if (!this.imports.find((i) => i.declarations.find((d) => d.foreignName.text == "JSON"))) {
347
- const __filename = fileURLToPath(import.meta.url);
348
- const __dirname = path.dirname(__filename);
349
- let relativePath = path.relative(path.dirname(node.range.source.normalizedPath), path.resolve(__dirname, "../../assembly/index.ts"));
350
- if (!relativePath.startsWith(".") && !relativePath.startsWith("/")) relativePath = "./" + relativePath;
351
- const txt = `import { JSON } from "${relativePath}";`;
352
- if (!this.jsonImport) {
353
- this.jsonImport = txt;
354
- if (process.env["JSON_DEBUG"]) console.log("Added json-as import: " + txt + "\n");
355
- }
367
+ addRequiredImports(node) {
368
+ if (!this.imports.find((i) => i.declarations.find((d) => d.foreignName.text == "bs"))) {
369
+ const __filename = fileURLToPath(import.meta.url);
370
+ const __dirname = path.dirname(__filename);
371
+ let relativePath = path.relative(path.dirname(node.range.source.normalizedPath), path.resolve(__dirname, "../../modules/as-bs/"));
372
+ if (!relativePath.startsWith(".") && !relativePath.startsWith("/"))
373
+ relativePath = "./" + relativePath;
374
+ const txt = `import { bs } from "${relativePath}";`;
375
+ if (!this.bsImport) {
376
+ this.bsImport = txt;
377
+ if (process.env["JSON_DEBUG"])
378
+ console.log("Added as-bs import: " + txt + "\n");
379
+ }
380
+ }
381
+ if (!this.imports.find((i) => i.declarations.find((d) => d.foreignName.text == "JSON"))) {
382
+ const __filename = fileURLToPath(import.meta.url);
383
+ const __dirname = path.dirname(__filename);
384
+ let relativePath = path.relative(path.dirname(node.range.source.normalizedPath), path.resolve(__dirname, "../../assembly/index.ts"));
385
+ if (!relativePath.startsWith(".") && !relativePath.startsWith("/"))
386
+ relativePath = "./" + relativePath;
387
+ const txt = `import { JSON } from "${relativePath}";`;
388
+ if (!this.jsonImport) {
389
+ this.jsonImport = txt;
390
+ if (process.env["JSON_DEBUG"])
391
+ console.log("Added json-as import: " + txt + "\n");
392
+ }
393
+ }
356
394
  }
357
- }
358
- getStores(data, simd = false) {
359
- const out = [];
360
- const sizes = strToNum(data, simd);
361
- let offset = 0;
362
- for (const [size, num] of sizes) {
363
- if (size == "v128") {
364
- let index = this.newStmts.simd.findIndex((v) => v.includes(num));
365
- let name = "SIMD_" + (index == -1 ? this.newStmts.simd.length : index);
366
- if (index && !this.newStmts.simd.includes(`const ${name} = ${num};`)) this.newStmts.simd.push(`const ${name} = ${num};`);
367
- out.push("store<v128>(bs.offset, " + name + ", " + offset + "); // " + data.slice(offset >> 1, (offset >> 1) + 8));
368
- offset += 16;
369
- }
370
- if (size == "u64") {
371
- out.push("store<u64>(bs.offset, " + num + ", " + offset + "); // " + data.slice(offset >> 1, (offset >> 1) + 4));
372
- offset += 8;
373
- } else if (size == "u32") {
374
- out.push("store<u32>(bs.offset, " + num + ", " + offset + "); // " + data.slice(offset >> 1, (offset >> 1) + 2));
375
- offset += 4;
376
- } else if (size == "u16") {
377
- out.push("store<u16>(bs.offset, " + num + ", " + offset + "); // " + data.slice(offset >> 1, (offset >> 1) + 1));
378
- offset += 2;
379
- }
395
+ getStores(data, simd = false) {
396
+ const out = [];
397
+ const sizes = strToNum(data, simd);
398
+ let offset = 0;
399
+ for (const [size, num] of sizes) {
400
+ if (size == "v128") {
401
+ let index = this.newStmts.simd.findIndex((v) => v.includes(num));
402
+ let name = "SIMD_" + (index == -1 ? this.newStmts.simd.length : index);
403
+ if (index && !this.newStmts.simd.includes(`const ${name} = ${num};`))
404
+ this.newStmts.simd.push(`const ${name} = ${num};`);
405
+ out.push("store<v128>(bs.offset, " + name + ", " + offset + "); // " + data.slice(offset >> 1, (offset >> 1) + 8));
406
+ offset += 16;
407
+ }
408
+ if (size == "u64") {
409
+ out.push("store<u64>(bs.offset, " + num + ", " + offset + "); // " + data.slice(offset >> 1, (offset >> 1) + 4));
410
+ offset += 8;
411
+ }
412
+ else if (size == "u32") {
413
+ out.push("store<u32>(bs.offset, " + num + ", " + offset + "); // " + data.slice(offset >> 1, (offset >> 1) + 2));
414
+ offset += 4;
415
+ }
416
+ else if (size == "u16") {
417
+ out.push("store<u16>(bs.offset, " + num + ", " + offset + "); // " + data.slice(offset >> 1, (offset >> 1) + 1));
418
+ offset += 2;
419
+ }
420
+ }
421
+ out.push("bs.offset += " + offset + ";");
422
+ return out;
380
423
  }
381
- out.push("bs.offset += " + offset + ";");
382
- return out;
383
- }
384
424
  }
385
425
  export default class Transformer extends Transform {
386
- afterParse(parser) {
387
- const transformer = new JSONTransform();
388
- const sources = parser.sources.sort((_a, _b) => {
389
- const a = _a.internalPath;
390
- const b = _b.internalPath;
391
- if (a[0] == "~" && b[0] !== "~") {
392
- return -1;
393
- } else if (a[0] !== "~" && b[0] == "~") {
394
- return 1;
395
- } else {
396
- return 0;
397
- }
398
- });
399
- transformer.parser = parser;
400
- for (const source of sources) {
401
- transformer.imports = [];
402
- transformer.currentSource = source;
403
- transformer.visit(source);
404
- if (transformer.newStmts.simd) {
405
- const tokenizer = new Tokenizer(new Source(0, source.normalizedPath, transformer.newStmts.simd.join("\n")));
406
- parser.currentSource = tokenizer.source;
407
- for (let i = 0; i < transformer.newStmts.simd.length; i++) source.statements.unshift(parser.parseTopLevelStatement(tokenizer));
408
- parser.currentSource = source;
409
- transformer.newStmts.simd = [];
410
- }
411
- if (transformer.jsonImport) {
412
- const tokenizer = new Tokenizer(new Source(0, source.normalizedPath, transformer.jsonImport));
413
- parser.currentSource = tokenizer.source;
414
- source.statements.unshift(parser.parseTopLevelStatement(tokenizer));
415
- parser.currentSource = source;
416
- transformer.jsonImport = null;
417
- }
418
- if (transformer.bsImport) {
419
- const tokenizer = new Tokenizer(new Source(0, source.normalizedPath, transformer.bsImport));
420
- parser.currentSource = tokenizer.source;
421
- source.statements.unshift(parser.parseTopLevelStatement(tokenizer));
422
- parser.currentSource = source;
423
- transformer.bsImport = null;
424
- }
425
- }
426
- const schemas = transformer.schemas;
427
- for (const schema of schemas) {
428
- if (schema.parent) {
429
- const parent = schemas.find((v) => v.name == schema.parent?.name);
430
- if (!parent) throwError(`Class ${schema.name} extends its parent class ${schema.parent}, but ${schema.parent} does not include a @json or @serializable decorator!`, schema.parent.node.range);
431
- }
426
+ afterParse(parser) {
427
+ const transformer = new JSONTransform();
428
+ const sources = parser.sources.sort((_a, _b) => {
429
+ const a = _a.internalPath;
430
+ const b = _b.internalPath;
431
+ if (a[0] == "~" && b[0] !== "~") {
432
+ return -1;
433
+ }
434
+ else if (a[0] !== "~" && b[0] == "~") {
435
+ return 1;
436
+ }
437
+ else {
438
+ return 0;
439
+ }
440
+ });
441
+ transformer.parser = parser;
442
+ for (const source of sources) {
443
+ transformer.imports = [];
444
+ transformer.currentSource = source;
445
+ transformer.visit(source);
446
+ if (transformer.newStmts.simd) {
447
+ const tokenizer = new Tokenizer(new Source(0, source.normalizedPath, transformer.newStmts.simd.join("\n")));
448
+ parser.currentSource = tokenizer.source;
449
+ for (let i = 0; i < transformer.newStmts.simd.length; i++)
450
+ source.statements.unshift(parser.parseTopLevelStatement(tokenizer));
451
+ parser.currentSource = source;
452
+ transformer.newStmts.simd = [];
453
+ }
454
+ if (transformer.jsonImport) {
455
+ const tokenizer = new Tokenizer(new Source(0, source.normalizedPath, transformer.jsonImport));
456
+ parser.currentSource = tokenizer.source;
457
+ source.statements.unshift(parser.parseTopLevelStatement(tokenizer));
458
+ parser.currentSource = source;
459
+ transformer.jsonImport = null;
460
+ }
461
+ if (transformer.bsImport) {
462
+ const tokenizer = new Tokenizer(new Source(0, source.normalizedPath, transformer.bsImport));
463
+ parser.currentSource = tokenizer.source;
464
+ source.statements.unshift(parser.parseTopLevelStatement(tokenizer));
465
+ parser.currentSource = source;
466
+ transformer.bsImport = null;
467
+ }
468
+ }
469
+ const schemas = transformer.schemas;
470
+ for (const schema of schemas) {
471
+ if (schema.parent) {
472
+ const parent = schemas.find((v) => v.name == schema.parent?.name);
473
+ if (!parent)
474
+ throwError(`Class ${schema.name} extends its parent class ${schema.parent}, but ${schema.parent} does not include a @json or @serializable decorator!`, schema.parent.node.range);
475
+ }
476
+ }
432
477
  }
433
- }
434
478
  }
435
479
  function sortMembers(members) {
436
- return members.sort((a, b) => {
437
- const aMove = a.flags.has(PropertyFlags.OmitIf) || a.flags.has(PropertyFlags.OmitNull);
438
- const bMove = b.flags.has(PropertyFlags.OmitIf) || b.flags.has(PropertyFlags.OmitNull);
439
- if (aMove && !bMove) {
440
- return -1;
441
- } else if (!aMove && bMove) {
442
- return 1;
443
- } else {
444
- return 0;
445
- }
446
- });
480
+ return members.sort((a, b) => {
481
+ const aMove = a.flags.has(PropertyFlags.OmitIf) || a.flags.has(PropertyFlags.OmitNull);
482
+ const bMove = b.flags.has(PropertyFlags.OmitIf) || b.flags.has(PropertyFlags.OmitNull);
483
+ if (aMove && !bMove) {
484
+ return -1;
485
+ }
486
+ else if (!aMove && bMove) {
487
+ return 1;
488
+ }
489
+ else {
490
+ return 0;
491
+ }
492
+ });
447
493
  }
448
494
  function getArgs(args) {
449
- if (!args) return [];
450
- let out = [];
451
- for (const arg of args) {
452
- if (arg instanceof StringLiteralExpression) {
453
- out.push(arg.value);
454
- } else if (arg instanceof IntegerLiteralExpression) {
455
- out.push(i64_to_string(arg.value));
456
- } else if (arg instanceof FloatLiteralExpression) {
457
- out.push(arg.value.toString());
458
- } else if (arg instanceof NullExpression) {
459
- out.push(arg.text);
460
- } else if (arg instanceof TrueExpression) {
461
- out.push(arg.text);
462
- } else if (arg instanceof FalseExpression) {
463
- out.push(arg.text);
464
- } else if (arg instanceof IdentifierExpression) {
465
- out.push(arg.text);
495
+ if (!args)
496
+ return [];
497
+ let out = [];
498
+ for (const arg of args) {
499
+ if (arg instanceof StringLiteralExpression) {
500
+ out.push(arg.value);
501
+ }
502
+ else if (arg instanceof IntegerLiteralExpression) {
503
+ out.push(i64_to_string(arg.value));
504
+ }
505
+ else if (arg instanceof FloatLiteralExpression) {
506
+ out.push(arg.value.toString());
507
+ }
508
+ else if (arg instanceof NullExpression) {
509
+ out.push(arg.text);
510
+ }
511
+ else if (arg instanceof TrueExpression) {
512
+ out.push(arg.text);
513
+ }
514
+ else if (arg instanceof FalseExpression) {
515
+ out.push(arg.text);
516
+ }
517
+ else if (arg instanceof IdentifierExpression) {
518
+ out.push(arg.text);
519
+ }
466
520
  }
467
- }
468
- return out;
521
+ return out;
469
522
  }
470
523
  function toU16(data, offset = 0) {
471
- return data.charCodeAt(offset + 0).toString();
524
+ return data.charCodeAt(offset + 0).toString();
472
525
  }
473
526
  function toU32(data, offset = 0) {
474
- return ((data.charCodeAt(offset + 1) << 16) | data.charCodeAt(offset + 0)).toString();
527
+ return ((data.charCodeAt(offset + 1) << 16) | data.charCodeAt(offset + 0)).toString();
475
528
  }
476
529
  function toU48(data, offset = 0) {
477
- return ((BigInt(data.charCodeAt(offset + 2)) << 32n) | (BigInt(data.charCodeAt(offset + 1)) << 16n) | BigInt(data.charCodeAt(offset + 0))).toString();
530
+ return ((BigInt(data.charCodeAt(offset + 2)) << 32n) | (BigInt(data.charCodeAt(offset + 1)) << 16n) | BigInt(data.charCodeAt(offset + 0))).toString();
478
531
  }
479
532
  function toU64(data, offset = 0) {
480
- return ((BigInt(data.charCodeAt(offset + 3)) << 48n) | (BigInt(data.charCodeAt(offset + 2)) << 32n) | (BigInt(data.charCodeAt(offset + 1)) << 16n) | BigInt(data.charCodeAt(offset + 0))).toString();
533
+ return ((BigInt(data.charCodeAt(offset + 3)) << 48n) | (BigInt(data.charCodeAt(offset + 2)) << 32n) | (BigInt(data.charCodeAt(offset + 1)) << 16n) | BigInt(data.charCodeAt(offset + 0))).toString();
481
534
  }
482
535
  function toMemCDecl(n, indent) {
483
- let out = "";
484
- let offset = 0;
485
- let index = 0;
486
- while (n >= 8) {
487
- out += `${indent}const code${index++} = load<u64>(keyStart, ${offset});\n`;
488
- offset += 8;
489
- n -= 8;
490
- }
491
- while (n >= 4) {
492
- out += `${indent}const code${index++} = load<u32>(keyStart, ${offset});\n`;
493
- offset += 4;
494
- n -= 4;
495
- }
496
- if (n == 1) out += `${indent}const code${index++} = load<u16>(keyStart, ${offset});\n`;
497
- return out;
536
+ let out = "";
537
+ let offset = 0;
538
+ let index = 0;
539
+ while (n >= 8) {
540
+ out += `${indent}const code${index++} = load<u64>(keyStart, ${offset});\n`;
541
+ offset += 8;
542
+ n -= 8;
543
+ }
544
+ while (n >= 4) {
545
+ out += `${indent}const code${index++} = load<u32>(keyStart, ${offset});\n`;
546
+ offset += 4;
547
+ n -= 4;
548
+ }
549
+ if (n == 1)
550
+ out += `${indent}const code${index++} = load<u16>(keyStart, ${offset});\n`;
551
+ return out;
498
552
  }
499
553
  function toMemCCheck(data) {
500
- let n = data.length << 1;
501
- let out = "";
502
- let offset = 0;
503
- let index = 0;
504
- while (n >= 8) {
505
- out += ` && code${index++} == ${toU64(data, offset >> 1)}`;
506
- offset += 8;
507
- n -= 8;
508
- }
509
- while (n >= 4) {
510
- out += ` && code${index++} == ${toU32(data, offset >> 1)}`;
511
- offset += 4;
512
- n -= 4;
513
- }
514
- if (n == 1) out += ` && code${index++} == ${toU16(data, offset >> 1)}`;
515
- return out.slice(4);
554
+ let n = data.length << 1;
555
+ let out = "";
556
+ let offset = 0;
557
+ let index = 0;
558
+ while (n >= 8) {
559
+ out += ` && code${index++} == ${toU64(data, offset >> 1)}`;
560
+ offset += 8;
561
+ n -= 8;
562
+ }
563
+ while (n >= 4) {
564
+ out += ` && code${index++} == ${toU32(data, offset >> 1)}`;
565
+ offset += 4;
566
+ n -= 4;
567
+ }
568
+ if (n == 1)
569
+ out += ` && code${index++} == ${toU16(data, offset >> 1)}`;
570
+ return out.slice(4);
516
571
  }
517
572
  function strToNum(data, simd = false, offset = 0) {
518
- const out = [];
519
- let n = data.length;
520
- while (n >= 8 && simd) {
521
- out.push(["v128", "i16x8(" + data.charCodeAt(offset + 0) + ", " + data.charCodeAt(offset + 1) + ", " + data.charCodeAt(offset + 2) + ", " + data.charCodeAt(offset + 3) + ", " + data.charCodeAt(offset + 4) + ", " + data.charCodeAt(offset + 5) + ", " + data.charCodeAt(offset + 6) + ", " + data.charCodeAt(offset + 7) + ")"]);
522
- offset += 8;
523
- n -= 8;
524
- }
525
- while (n >= 4) {
526
- const value = (BigInt(data.charCodeAt(offset + 3)) << 48n) | (BigInt(data.charCodeAt(offset + 2)) << 32n) | (BigInt(data.charCodeAt(offset + 1)) << 16n) | BigInt(data.charCodeAt(offset + 0));
527
- out.push(["u64", value.toString()]);
528
- offset += 4;
529
- n -= 4;
530
- }
531
- while (n >= 2) {
532
- const value = (data.charCodeAt(offset + 1) << 16) | data.charCodeAt(offset + 0);
533
- out.push(["u32", value.toString()]);
534
- offset += 2;
535
- n -= 2;
536
- }
537
- if (n === 1) {
538
- const value = data.charCodeAt(offset + 0);
539
- out.push(["u16", value.toString()]);
540
- }
541
- return out;
573
+ const out = [];
574
+ let n = data.length;
575
+ while (n >= 8 && simd) {
576
+ out.push(["v128", "i16x8(" + data.charCodeAt(offset + 0) + ", " + data.charCodeAt(offset + 1) + ", " + data.charCodeAt(offset + 2) + ", " + data.charCodeAt(offset + 3) + ", " + data.charCodeAt(offset + 4) + ", " + data.charCodeAt(offset + 5) + ", " + data.charCodeAt(offset + 6) + ", " + data.charCodeAt(offset + 7) + ")"]);
577
+ offset += 8;
578
+ n -= 8;
579
+ }
580
+ while (n >= 4) {
581
+ const value = (BigInt(data.charCodeAt(offset + 3)) << 48n) | (BigInt(data.charCodeAt(offset + 2)) << 32n) | (BigInt(data.charCodeAt(offset + 1)) << 16n) | BigInt(data.charCodeAt(offset + 0));
582
+ out.push(["u64", value.toString()]);
583
+ offset += 4;
584
+ n -= 4;
585
+ }
586
+ while (n >= 2) {
587
+ const value = (data.charCodeAt(offset + 1) << 16) | data.charCodeAt(offset + 0);
588
+ out.push(["u32", value.toString()]);
589
+ offset += 2;
590
+ n -= 2;
591
+ }
592
+ if (n === 1) {
593
+ const value = data.charCodeAt(offset + 0);
594
+ out.push(["u16", value.toString()]);
595
+ }
596
+ return out;
542
597
  }
543
598
  function isPrimitive(type) {
544
- const primitiveTypes = ["u8", "u16", "u32", "u64", "i8", "i16", "i32", "i64", "f32", "f64", "bool", "boolean"];
545
- return primitiveTypes.some((v) => type.includes(v));
599
+ const primitiveTypes = ["u8", "u16", "u32", "u64", "i8", "i16", "i32", "i64", "f32", "f64", "bool", "boolean"];
600
+ return primitiveTypes.some((v) => type.includes(v));
546
601
  }
547
602
  function throwError(message, range) {
548
- const err = new Error();
549
- err.stack = `${message}\n at ${range.source.normalizedPath}:${range.source.lineAt(range.start)}:${range.source.columnAt()}\n`;
550
- throw err;
603
+ const err = new Error();
604
+ err.stack = `${message}\n at ${range.source.normalizedPath}:${range.source.lineAt(range.start)}:${range.source.columnAt()}\n`;
605
+ throw err;
551
606
  }
552
607
  function indentInc() {
553
- indent += " ";
608
+ indent += " ";
554
609
  }
555
610
  function indentDec() {
556
- indent = indent.slice(0, Math.max(0, indent.length - 2));
611
+ indent = indent.slice(0, Math.max(0, indent.length - 2));
557
612
  }
558
613
  function sizeof(type) {
559
- if (type == "u8") return 6;
560
- else if (type == "i8") return 8;
561
- else if (type == "u16") return 10;
562
- else if (type == "i16") return 12;
563
- else if (type == "u32") return 20;
564
- else if (type == "i32") return 22;
565
- else if (type == "u64") return 40;
566
- else if (type == "i64") return 40;
567
- else if (type == "bool" || type == "boolean") return 10;
568
- else return 0;
614
+ if (type == "u8")
615
+ return 6;
616
+ else if (type == "i8")
617
+ return 8;
618
+ else if (type == "u16")
619
+ return 10;
620
+ else if (type == "i16")
621
+ return 12;
622
+ else if (type == "u32")
623
+ return 20;
624
+ else if (type == "i32")
625
+ return 22;
626
+ else if (type == "u64")
627
+ return 40;
628
+ else if (type == "i64")
629
+ return 40;
630
+ else if (type == "bool" || type == "boolean")
631
+ return 10;
632
+ else
633
+ return 0;
569
634
  }
570
635
  function allPrimitive(schema) {
571
- return !schema.members.some((p) => p.byteSize == 0);
636
+ return !schema.members.some((p) => p.byteSize == 0);
572
637
  }
573
- //# sourceMappingURL=index.js.map
638
+ //# sourceMappingURL=index.js.map