Comparing version
@@ -1,9 +0,6 @@ | ||
import { CHAR_F, CHAR_T } from "../../custom/chars"; | ||
export function deserializeBoolean(srcStart: usize, srcEnd: usize): boolean { | ||
const srcSize = srcEnd - srcStart; | ||
const firstChar = load<u16>(srcStart); | ||
if (firstChar == CHAR_T && load<u64>(srcStart) == 28429475166421108) return true; | ||
else if (firstChar == CHAR_F && load<u64>(srcSize, 2) == 28429466576093281) return false; | ||
const block = load<u64>(srcStart); | ||
if (block == 28429475166421108) return true; | ||
else if (block == 32370086184550502 && load<u16>(srcStart, 8) == 101) return false; | ||
return false; //throw new Error(`Expected to find boolean, but found "${data.slice(0, 100)}" instead!`); | ||
} | ||
} |
@@ -5,8 +5,8 @@ import { ptrToStr } from "../../util/ptrToStr"; | ||
// Use AssemblyScript's date parser | ||
const d = Date.fromString(ptrToStr(srcStart, srcEnd)); | ||
const d = Date.fromString(ptrToStr(srcStart + 2, srcEnd - 2)); | ||
// Return a new object instead of the one that the parser returned. | ||
// This may seem redundant, but addreses the issue when Date | ||
// This may seem redundant, but it addresses the issue when Date | ||
// is globally aliased to wasi_Date (or some other superclass). | ||
return new Date(d.getTime()); | ||
} |
@@ -0,3 +1,5 @@ | ||
import { JSON } from "../.."; | ||
import { BACK_SLASH, COMMA, CHAR_F, BRACE_LEFT, BRACKET_LEFT, CHAR_N, QUOTE, BRACE_RIGHT, BRACKET_RIGHT, CHAR_T } from "../../custom/chars"; | ||
import { isSpace } from "../../util"; | ||
import { ptrToStr } from "../../util/ptrToStr"; | ||
@@ -63,5 +65,5 @@ export function deserializeObject<T>(srcStart: usize, srcEnd: usize, dst: usize): T { | ||
if (code == COMMA || code == BRACE_RIGHT || isSpace(code)) { | ||
// console.log("Value (number): " + ptrToStr(lastIndex, srcStart)); | ||
// @ts-ignore: exists | ||
out.__DESERIALIZE(keyStart, keyEnd, lastIndex, srcStart, dst); | ||
// console.log("Value (number): " + ptrToStr(lastIndex, srcStart)); | ||
// while (isSpace(load<u16>((srcStart += 2)))) { | ||
@@ -68,0 +70,0 @@ // /* empty */ |
@@ -39,2 +39,7 @@ /// <reference path="./index.d.ts" /> | ||
export namespace JSON { | ||
export namespace Memory { | ||
export function shrink(): void { | ||
bs.resize(64); | ||
} | ||
} | ||
/** | ||
@@ -111,6 +116,4 @@ * Serializes valid JSON data | ||
// @ts-ignore: Supplied by transform | ||
} else if (isDefined(data.__SERIALIZE) && isDefined(data.__ALLOCATE)) { | ||
} else if (isDefined(data.__SERIALIZE)) { | ||
// @ts-ignore | ||
// data.__ALLOCATE(); | ||
// @ts-ignore | ||
data.__SERIALIZE(changetype<usize>(data)); | ||
@@ -124,4 +127,4 @@ return bs.out<string>(); | ||
memory.copy(changetype<usize>(out) + 2, changetype<usize>(data.toISOString()), 48); | ||
store<u16>(changetype<usize>(out), 50); | ||
return out; | ||
store<u16>(changetype<usize>(out), QUOTE, 50); | ||
return changetype<string>(out); | ||
} else if (data instanceof Array) { | ||
@@ -162,3 +165,3 @@ // @ts-ignore | ||
return deserializeFloat<T>(dataPtr, dataPtr + dataSize); | ||
} else if (isNullable<T>() && data.length == 4 && data == "null") { | ||
} else if (isNullable<T>() && dataSize == 8 && load<u64>(dataPtr) == 30399761348886638) { | ||
// @ts-ignore | ||
@@ -189,3 +192,3 @@ return null; | ||
// @ts-ignore | ||
return new JSON.Box(JSON.parse<indexof<T>>(data)); | ||
return new JSON.Box(parseBox(data, changetype<nonnull<T>>(0).value)); | ||
} else { | ||
@@ -347,3 +350,5 @@ throw new Error(`Could not deserialize data ${data} to type ${nameof<T>()}. Make sure to add the correct decorators to classes.`); | ||
export class Box<T> { | ||
constructor(public value: T) {} | ||
constructor(public value: T) { | ||
if (!isInteger<T>() && !isFloat<T>()) ERROR("JSON.Box should only hold primitive types!"); | ||
} | ||
/** | ||
@@ -362,2 +367,8 @@ * Creates a reference to a primitive type | ||
} | ||
toString(): string { | ||
if (isNullable<this>() && changetype<usize>(this) == null) return "null"; | ||
// @ts-ignore: type | ||
if (isDefined(this.value.toString)) return this.value.toString(); | ||
return "null"; | ||
} | ||
} | ||
@@ -431,2 +442,5 @@ | ||
return deserializeDate(srcStart, srcEnd); | ||
} else if (type instanceof JSON.Box) { | ||
// @ts-ignore: type | ||
return new JSON.Box(deserializeBox(srcStart, srcEnd, dst, changetype<nonnull<T>>(0).value)); | ||
} | ||
@@ -437,1 +451,10 @@ } | ||
} | ||
// @ts-ignore: decorator | ||
@inline function parseBox<T>(data: string, ty: T): T { | ||
return JSON.parse<T>(data); | ||
} | ||
function deserializeBox<T>(srcStart: usize, srcEnd: usize, dst: usize, ty: T): T { | ||
return JSON.__deserialize<T>(srcStart, srcEnd, dst); | ||
} |
@@ -21,3 +21,3 @@ import { bs } from "../../../modules/as-bs"; | ||
const srcEnd = srcStart + srcSize; | ||
bs.ensureSize(srcSize + 4); | ||
bs.proposeSize(srcSize + 4); | ||
const srcEnd16 = srcEnd - 15; | ||
@@ -49,3 +49,3 @@ | ||
if ((escaped & 0xffff) != BACK_SLASH) { | ||
bs.addSize(10); | ||
bs.growSize(10); | ||
store<u64>(dst_offset, 13511005048209500); | ||
@@ -56,3 +56,3 @@ store<u32>(dst_offset, escaped, 8); | ||
} else { | ||
bs.addSize(2); | ||
bs.growSize(2); | ||
store<u32>(dst_offset, escaped); | ||
@@ -90,3 +90,3 @@ v128.store(dst_offset, v128.load(src_offset, 2), 4); | ||
if ((escaped & 0xffff) != BACK_SLASH) { | ||
bs.addSize(10); | ||
bs.growSize(10); | ||
store<u64>(dst_offset, 13511005048209500); | ||
@@ -100,3 +100,3 @@ store<u32>(dst_offset, escaped, 8); | ||
} else { | ||
bs.addSize(2); | ||
bs.growSize(2); | ||
store<u32>(dst_offset, escaped); | ||
@@ -124,3 +124,3 @@ | ||
if ((escaped & 0xffff) != BACK_SLASH) { | ||
bs.addSize(10); | ||
bs.growSize(10); | ||
store<u64>(bs.offset, 13511005048209500); | ||
@@ -130,3 +130,3 @@ store<u32>(bs.offset, escaped, 8); | ||
} else { | ||
bs.addSize(2); | ||
bs.growSize(2); | ||
store<u32>(bs.offset, escaped); | ||
@@ -144,3 +144,3 @@ bs.offset += 4; | ||
if ((escaped & 0xffff) != BACK_SLASH) { | ||
bs.addSize(10); | ||
bs.growSize(10); | ||
store<u64>(bs.offset, 13511005048209500); | ||
@@ -150,3 +150,3 @@ store<u32>(bs.offset, escaped, 8); | ||
} else { | ||
bs.addSize(2); | ||
bs.growSize(2); | ||
store<u32>(bs.offset, escaped); | ||
@@ -168,3 +168,3 @@ bs.offset += 4; | ||
if ((escaped & 0xffff) != BACK_SLASH) { | ||
bs.addSize(10); | ||
bs.growSize(10); | ||
store<u64>(bs.offset, 13511005048209500); | ||
@@ -174,3 +174,3 @@ store<u32>(bs.offset, escaped, 8); | ||
} else { | ||
bs.addSize(2); | ||
bs.growSize(2); | ||
store<u32>(bs.offset, escaped); | ||
@@ -177,0 +177,0 @@ bs.offset += 4; |
@@ -6,6 +6,6 @@ import { bs } from "../../../modules/as-bs"; | ||
export function serializeArray<T extends any[]>(src: T): void { | ||
bs.proposeSize(4); | ||
const end = src.length - 1; | ||
let i = 0; | ||
if (end == -1) { | ||
bs.proposeSize(4); | ||
store<u32>(bs.offset, 6094939); | ||
@@ -15,3 +15,4 @@ bs.offset += 4; | ||
} | ||
bs.proposeSize(end << 3); | ||
// {} = 4 | ||
// xi, = n << 1 | ||
@@ -31,5 +32,5 @@ store<u16>(bs.offset, BRACKET_LEFT); | ||
JSON.__serialize<valueof<T>>(lastBlock); | ||
bs.proposeSize(2); | ||
bs.growSize(2); | ||
store<u16>(bs.offset, BRACKET_RIGHT); | ||
bs.offset += 2; | ||
} |
@@ -5,4 +5,4 @@ import { dtoa_buffered } from "util/number"; | ||
export function serializeFloat<T extends number>(data: T): void { | ||
bs.proposeSize(64); | ||
bs.ensureSize(64); | ||
bs.offset += dtoa_buffered(bs.offset, data) << 1; | ||
} |
@@ -5,4 +5,9 @@ import { itoa_buffered } from "util/number"; | ||
export function serializeInteger<T extends number>(data: T): void { | ||
bs.proposeSize(sizeof<T>() << 3); | ||
bs.offset += itoa_buffered(bs.offset, data) << 1; | ||
bs.ensureSize(sizeof<T>() << 3); | ||
const bytesWritten = itoa_buffered(bs.offset, data) << 1; | ||
bs.offset += bytesWritten; | ||
bs.growSize(bytesWritten); | ||
} | ||
// 32 {"x":,"y":,"z"} | ||
// 18 3.41.28.3 |
@@ -1,5 +0,59 @@ | ||
import { JSON } from "./"; | ||
import { describe, expect } from "../modules/test/assembly"; | ||
import { JSON } from "."; | ||
import { bytes } from "./util"; | ||
console.log(JSON.stringify(JSON.parse<string>('"\\u0000\\u0001\\u0002\\u0003\\u0004\\u0005\\u0006\\u0007\\b\\t\\n\\u000b\\f\\r\\u000e\\u000f\\u000f\\u0011\\u0012\\u0013\\u0014\\u0015\\u0016\\u0017\\u0018\\u0019\\u001a\\u001b\\u001c\\u001d\\u001e\\u001f"'))); | ||
console.log('"\\u0000\\u0001\\u0002\\u0003\\u0004\\u0005\\u0006\\u0007\\b\\t\\n\\u000b\\f\\r\\u000e\\u000f\\u000f\\u0011\\u0012\\u0013\\u0014\\u0015\\u0016\\u0017\\u0018\\u0019\\u001a\\u001b\\u001c\\u001d\\u001e\\u001f"'); | ||
@json | ||
class Obj { | ||
public a: string = "hello"; | ||
public b: string = "world"; | ||
public c: string = "\"\t\f\u0000\u0001"; | ||
} | ||
@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((age) => age < 18) | ||
@omitif('this.age <= 0') | ||
age!: i32; | ||
@omitnull() | ||
pos!: Vec3 | null; | ||
isVerified!: boolean; | ||
} | ||
const player: Player = { | ||
firstName: "Jairus", | ||
lastName: "Tanaka", | ||
lastActive: [2, 7, 2025], | ||
age: 18, | ||
pos: { | ||
x: 3.4, | ||
y: 1.2, | ||
z: 8.3 | ||
}, | ||
isVerified: true | ||
}; | ||
const a1 = JSON.stringify("\u0000\u0001\u0002\u0003\u0004\u0005\u0006\u0007\u0008\u0009\u000a\u000b\u000c\u000d\u000e\u000f\u000f\u0011\u0012\u0013\u0014\u0015\u0016\u0017\u0018\u0019\u001a\u001b\u001c\u001d\u001e\u001f"); | ||
// console.log("Bytes " + bytes(a1).toString()); | ||
console.log("a1: " + a1); | ||
const obj = new Obj(); | ||
const a2 = JSON.stringify(obj); | ||
// console.log("Bytes " + bytes(a2).toString()); | ||
console.log("a2: " + a2); | ||
const a3 = JSON.stringify(player); | ||
// console.log("Bytes " + bytes(a3).toString()); | ||
console.log("a3: " + a3); | ||
JSON.Memory.shrink(); |
@@ -10,3 +10,3 @@ // e -> 101 | ||
// @ts-ignore: Decorator valid here | ||
@inline function snp<T extends number>(srcStart: usize, srcEnd: usize): T { | ||
@inline export function snp<T extends number>(srcStart: usize, srcEnd: usize): T { | ||
// @ts-ignore: type | ||
@@ -50,3 +50,3 @@ let val: T = 0; | ||
// @ts-ignore: type | ||
return val / pow10(atoi(srcStart + 2, srcEnd)); | ||
return val / pow10(atoi<u8>(srcStart + 2, srcEnd)); | ||
} else { | ||
@@ -53,0 +53,0 @@ // @ts-ignore: type |
@@ -8,12 +8,12 @@ import { OBJECT, TOTAL_OVERHEAD } from "rt/common"; | ||
/** Current buffer pointer. */ // @ts-ignore | ||
export let buffer: usize = __new(32, idof<ArrayBuffer>()); | ||
export let buffer: ArrayBuffer = new ArrayBuffer(32);//__new(32, idof<ArrayBuffer>()); | ||
/** Current offset within the buffer. */ | ||
export let offset: usize = buffer; | ||
export let offset: usize = changetype<usize>(buffer); | ||
/** Byte length of the buffer. */ | ||
export let byteLength: usize = 32; | ||
let bufferSize: usize = 32; | ||
/** Proposed size of output */ | ||
export let realSize: usize = offset; | ||
export let stackSize: usize = 0; | ||
@@ -25,9 +25,35 @@ /** | ||
*/ | ||
// @ts-ignore: Decorator valid here | ||
// @ts-ignore: decorator | ||
@inline export function ensureSize(size: u32): void { | ||
// console.log("Ensure " + (stackSize).toString() + " -> " + (stackSize + size).toString() + " (" + size.toString() + ") " + (((stackSize + size) > bufferSize) ? "+" : "")); | ||
if (offset + size > bufferSize + changetype<usize>(buffer)) { | ||
const deltaBytes = nextPowerOf2(size + 64); | ||
bufferSize += deltaBytes; | ||
// @ts-ignore: exists | ||
const newPtr = changetype<ArrayBuffer>(__renew( | ||
changetype<usize>(buffer), | ||
bufferSize | ||
)); | ||
offset = offset + changetype<usize>(newPtr) - changetype<usize>(buffer); | ||
buffer = newPtr; | ||
} | ||
} | ||
/** | ||
* Proposes that the buffer size is should be greater than or equal to the proposed size. | ||
* If necessary, reallocates the buffer to the exact new size. | ||
* @param size - The size to propose. | ||
*/ | ||
// @ts-ignore: decorator | ||
@inline export function proposeSize(size: u32): void { | ||
if ((realSize = size) > byteLength) { | ||
byteLength = nextPowerOf2(size); | ||
// @ts-ignore | ||
const newPtr = __renew(buffer, byteLength); | ||
offset = offset - buffer + newPtr; | ||
// console.log("Propose " + (stackSize).toString() + " -> " + (stackSize + size).toString() + " (" + size.toString() + ") " + (((stackSize + size) > bufferSize) ? "+" : "")); | ||
if ((stackSize += size) > bufferSize) { | ||
const deltaBytes = nextPowerOf2(size); | ||
bufferSize += deltaBytes; | ||
// @ts-ignore: exists | ||
const newPtr = changetype<ArrayBuffer>(__renew( | ||
changetype<usize>(buffer), | ||
bufferSize | ||
)); | ||
offset = offset + changetype<usize>(newPtr) - changetype<usize>(buffer); | ||
buffer = newPtr; | ||
@@ -38,14 +64,19 @@ } | ||
/** | ||
* Increases the proposed size by nextPowerOf2(n + 8) if necessary. | ||
* Increases the proposed size by nextPowerOf2(n + 64) if necessary. | ||
* If necessary, reallocates the buffer to the exact new size. | ||
* @param size - The size to grow by. | ||
*/ | ||
// @ts-ignore: Decorator valid here | ||
// @ts-ignore: decorator | ||
@inline export function growSize(size: u32): void { | ||
realSize += size; | ||
if (realSize > byteLength) { | ||
byteLength += nextPowerOf2(size + 8); | ||
// console.log("Grow " + (stackSize).toString() + " -> " + (stackSize + size).toString() + " (" + size.toString() + ") " + (((stackSize + size) > bufferSize) ? "+" : "")); | ||
if ((stackSize += size) > bufferSize) { | ||
const deltaBytes = nextPowerOf2(size + 64); | ||
bufferSize += deltaBytes; | ||
// @ts-ignore | ||
const newPtr = __renew(buffer, byteLength); | ||
offset = offset - buffer + newPtr; | ||
const newPtr = changetype<ArrayBuffer>(__renew( | ||
changetype<usize>(buffer), | ||
bufferSize | ||
)); | ||
// if (buffer != newPtr) console.log(" Old: " + changetype<usize>(buffer).toString() + "\n New: " + changetype<usize>(newPtr).toString()); | ||
offset = offset + changetype<usize>(newPtr) - changetype<usize>(buffer); | ||
buffer = newPtr; | ||
@@ -61,8 +92,8 @@ } | ||
@inline export function resize(newSize: u32): void { | ||
// @ts-ignore | ||
// @ts-ignore: exists | ||
const newPtr = __renew(buffer, newSize); | ||
byteLength = newSize; | ||
bufferSize = newSize; | ||
buffer = newPtr; | ||
offset = newPtr + newSize; | ||
realSize = newPtr; | ||
stackSize = newPtr; | ||
} | ||
@@ -76,9 +107,9 @@ | ||
@inline export function out<T>(): T { | ||
const len = offset - buffer; | ||
// @ts-ignore | ||
const len = offset - changetype<usize>(buffer); | ||
// @ts-ignore: exists | ||
const _out = __new(len, idof<T>()); | ||
memory.copy(_out, buffer, len); | ||
memory.copy(_out, changetype<usize>(buffer), len); | ||
offset = buffer; | ||
realSize = buffer; | ||
offset = changetype<usize>(buffer); | ||
stackSize = 0; | ||
return changetype<T>(_out); | ||
@@ -96,9 +127,9 @@ } | ||
@inline export function outTo<T>(dst: usize): T { | ||
const len = offset - buffer; | ||
// @ts-ignore | ||
const len = offset - changetype<usize>(buffer); | ||
// @ts-ignore: exists | ||
if (len != changetype<OBJECT>(dst - TOTAL_OVERHEAD).rtSize) __renew(len, idof<T>()); | ||
memory.copy(dst, buffer, len); | ||
memory.copy(dst, changetype<usize>(buffer), len); | ||
offset = buffer; | ||
realSize = buffer; | ||
offset = changetype<usize>(buffer); | ||
stackSize = 0; | ||
return changetype<T>(dst); | ||
@@ -105,0 +136,0 @@ } |
{ | ||
"name": "json-as", | ||
"version": "1.0.0-alpha.3", | ||
"version": "1.0.0-alpha.4", | ||
"author": "Jairus Tanaka", | ||
@@ -12,8 +12,8 @@ "repository": { | ||
"@assemblyscript/wasi-shim": "^0.1.0", | ||
"@types/node": "latest", | ||
"@types/node": "^22.13.1", | ||
"as-console": "^7.0.0", | ||
"assemblyscript": "^0.27.31", | ||
"assemblyscript": "^0.27.34", | ||
"assemblyscript-prettier": "^3.0.1", | ||
"prettier": "^3.4.2", | ||
"typescript": "latest" | ||
"prettier": "^3.5.0", | ||
"typescript": "^5.7.3" | ||
}, | ||
@@ -20,0 +20,0 @@ "bugs": { |
@@ -9,6 +9,17 @@ <h5 align="center"> | ||
</span> | ||
AssemblyScript - v1.0.0-alpha.3 | ||
AssemblyScript - v1.0.0-alpha.4 | ||
</pre> | ||
</h5> | ||
## Contents | ||
- [About](#about) | ||
- [Installation](#installation) | ||
- [Usage](#usage) | ||
- [Examples](#examples) | ||
- [Performance](#performance) | ||
- [License](#license) | ||
- [Contact](#contact) | ||
## About | ||
## Installation | ||
@@ -44,3 +55,2 @@ | ||
// @json or @serializable work here | ||
@json | ||
@@ -60,4 +70,3 @@ class Vec3 { | ||
// Drop in a code block, function, or expression that evaluates to a boolean | ||
@omitif((age) => age < 18) | ||
@omitif('this.age <= 0') | ||
@omitif((self: Player) => self.age < 18) | ||
age!: i32; | ||
@@ -70,6 +79,6 @@ @omitnull() | ||
const player: Player = { | ||
firstName: "Emmet", | ||
lastName: "West", | ||
lastActive: [8, 27, 2022], | ||
age: 23, | ||
firstName: "Jairus", | ||
lastName: "Tanaka", | ||
lastActive: [2, 7, 2025], | ||
age: 18, | ||
pos: { | ||
@@ -83,7 +92,11 @@ x: 3.4, | ||
const stringified = JSON.stringify<Player>(player); | ||
const serialized = JSON.stringify<Player>(player); | ||
const parsed = JSON.parse<Player>(serialized); | ||
const parsed = JSON.parse<Player>(stringified); | ||
console.log("Serialized: " + serialized); | ||
console.log("Parsed: " + JSON.stringify(parsed)); | ||
``` | ||
## Examples | ||
Classes can even have inheritance. Here's a nasty example | ||
@@ -132,14 +145,13 @@ | ||
## Notes | ||
## 📃 License | ||
If you want a feature, drop an issue (and again, maybe a star). I'll likely add it in less than 7 days. | ||
This project is distributed under an open source license. You can view the full license using the following link: [License](./LICENSE) | ||
## Contact | ||
## 📫 Contact | ||
- [Email](mailto:me@jairus.dev) | ||
- [GitHub](https://github.com/JairusSW) | ||
- [Discord](discord.com/users/600700584038760448) | ||
Please send all issues to [GitHub Issues](https://github.com/JairusSW/as-json/issues) and to converse, please send me an email at [me@jairus.dev](mailto:me@jairus.dev) | ||
## Issues | ||
Please submit an issue to https://github.com/JairusSW/as-json/issues if you find anything wrong with this library | ||
- **Email:** Send me inquiries, questions, or requests at [me@jairus.dev](mailto:me@jairus.dev) | ||
- **GitHub:** Visit the official GitHub repository [Here](https://github.com/JairusSW/as-json) | ||
- **Website:** Visit my official website at [jairus.dev](https://jairus.dev/) | ||
- **Discord:** Converse with me on [My Discord](discord.com/users/600700584038760448) or on the [AssemblyScript Discord Server](https://discord.gg/assemblyscript/) |
import { isTypeOmitted, operatorTokenToString, util } from "assemblyscript/dist/assemblyscript.js"; | ||
import { Visitor } from "./visitor.js"; | ||
function assert(isTruish, message = "assertion error") { | ||
if (!isTruish) throw new Error(message); | ||
return isTruish; | ||
if (!isTruish) | ||
throw new Error(message); | ||
return isTruish; | ||
} | ||
export class ASTBuilder extends Visitor { | ||
static build(node) { | ||
var builder = new ASTBuilder(); | ||
builder.visitNode(node); | ||
return builder.finish(); | ||
} | ||
sb = []; | ||
indentLevel = 0; | ||
visitNode(node) { | ||
return this.visit(node); | ||
} | ||
visitSource(source) { | ||
var statements = source.statements; | ||
for (let i = 0, k = statements.length; i < k; ++i) { | ||
this.visitNodeAndTerminate(statements[i]); | ||
static build(node) { | ||
var builder = new ASTBuilder(); | ||
builder.visitNode(node); | ||
return builder.finish(); | ||
} | ||
} | ||
visitTypeNode(node) { | ||
switch (node.kind) { | ||
case 1: { | ||
this.visitNamedTypeNode(node); | ||
break; | ||
} | ||
case 2: { | ||
this.visitFunctionTypeNode(node); | ||
break; | ||
} | ||
default: | ||
assert(false); | ||
sb = []; | ||
indentLevel = 0; | ||
visitNode(node) { | ||
return this.visit(node); | ||
} | ||
} | ||
visitTypeName(node) { | ||
this.visitIdentifierExpression(node.identifier); | ||
var sb = this.sb; | ||
var current = node.next; | ||
while (current) { | ||
sb.push("."); | ||
this.visitIdentifierExpression(current.identifier); | ||
current = current.next; | ||
visitSource(source) { | ||
var statements = source.statements; | ||
for (let i = 0, k = statements.length; i < k; ++i) { | ||
this.visitNodeAndTerminate(statements[i]); | ||
} | ||
} | ||
} | ||
visitNamedTypeNode(node) { | ||
this.visitTypeName(node.name); | ||
var typeArguments = node.typeArguments; | ||
if (typeArguments) { | ||
let numTypeArguments = typeArguments.length; | ||
let sb = this.sb; | ||
if (numTypeArguments) { | ||
sb.push("<"); | ||
this.visitTypeNode(typeArguments[0]); | ||
for (let i = 1; i < numTypeArguments; ++i) { | ||
sb.push(", "); | ||
this.visitTypeNode(typeArguments[i]); | ||
visitTypeNode(node) { | ||
switch (node.kind) { | ||
case 1: { | ||
this.visitNamedTypeNode(node); | ||
break; | ||
} | ||
case 2: { | ||
this.visitFunctionTypeNode(node); | ||
break; | ||
} | ||
default: | ||
assert(false); | ||
} | ||
sb.push(">"); | ||
} | ||
if (node.isNullable) sb.push(" | null"); | ||
} | ||
} | ||
visitFunctionTypeNode(node) { | ||
var isNullable = node.isNullable; | ||
var sb = this.sb; | ||
sb.push(isNullable ? "((" : "("); | ||
var explicitThisType = node.explicitThisType; | ||
if (explicitThisType) { | ||
sb.push("this: "); | ||
this.visitTypeNode(explicitThisType); | ||
} | ||
var parameters = node.parameters; | ||
var numParameters = parameters.length; | ||
if (numParameters) { | ||
if (explicitThisType) sb.push(", "); | ||
this.serializeParameter(parameters[0]); | ||
for (let i = 1; i < numParameters; ++i) { | ||
sb.push(", "); | ||
this.serializeParameter(parameters[i]); | ||
} | ||
} | ||
var returnType = node.returnType; | ||
if (returnType) { | ||
sb.push(") => "); | ||
this.visitTypeNode(returnType); | ||
} else { | ||
sb.push(") => void"); | ||
} | ||
if (isNullable) sb.push(") | null"); | ||
} | ||
visitTypeParameter(node) { | ||
this.visitIdentifierExpression(node.name); | ||
var extendsType = node.extendsType; | ||
if (extendsType) { | ||
this.sb.push(" extends "); | ||
this.visitTypeNode(extendsType); | ||
} | ||
var defaultType = node.defaultType; | ||
if (defaultType) { | ||
this.sb.push("="); | ||
this.visitTypeNode(defaultType); | ||
} | ||
} | ||
visitIdentifierExpression(node) { | ||
if (node.isQuoted) this.visitStringLiteral(node.text); | ||
else this.sb.push(node.text); | ||
} | ||
visitArrayLiteralExpression(node) { | ||
var sb = this.sb; | ||
sb.push("["); | ||
var elements = node.elementExpressions; | ||
var numElements = elements.length; | ||
if (numElements) { | ||
let element = elements[0]; | ||
if (element) this.visitNode(element); | ||
for (let i = 1; i < numElements; ++i) { | ||
element = elements[i]; | ||
sb.push(", "); | ||
if (element) this.visitNode(element); | ||
} | ||
} | ||
sb.push("]"); | ||
} | ||
visitObjectLiteralExpression(node) { | ||
var sb = this.sb; | ||
var names = node.names; | ||
var values = node.values; | ||
var numElements = names.length; | ||
assert(numElements == values.length); | ||
if (numElements) { | ||
sb.push("{\n"); | ||
util.indent(sb, ++this.indentLevel); | ||
this.visitNode(names[0]); | ||
sb.push(": "); | ||
this.visitNode(values[0]); | ||
for (let i = 1; i < numElements; ++i) { | ||
sb.push(",\n"); | ||
util.indent(sb, this.indentLevel); | ||
let name = names[i]; | ||
let value = values[i]; | ||
if (name == value) { | ||
this.visitNode(name); | ||
} else { | ||
this.visitNode(name); | ||
sb.push(": "); | ||
this.visitNode(value); | ||
visitTypeName(node) { | ||
this.visitIdentifierExpression(node.identifier); | ||
var sb = this.sb; | ||
var current = node.next; | ||
while (current) { | ||
sb.push("."); | ||
this.visitIdentifierExpression(current.identifier); | ||
current = current.next; | ||
} | ||
} | ||
sb.push("\n"); | ||
util.indent(sb, --this.indentLevel); | ||
sb.push("}"); | ||
} else { | ||
sb.push("{}"); | ||
} | ||
} | ||
visitAssertionExpression(node) { | ||
var sb = this.sb; | ||
switch (node.assertionKind) { | ||
case 0: { | ||
sb.push("<"); | ||
if (node.toType) this.visitTypeNode(node.toType); | ||
sb.push(">"); | ||
this.visitNode(node.expression); | ||
break; | ||
} | ||
case 1: { | ||
this.visitNode(node.expression); | ||
sb.push(" as "); | ||
if (node.toType) this.visitTypeNode(node.toType); | ||
break; | ||
} | ||
case 2: { | ||
this.visitNode(node.expression); | ||
sb.push("!"); | ||
break; | ||
} | ||
case 3: { | ||
this.visitNode(node.expression); | ||
sb.push(" as const"); | ||
break; | ||
} | ||
default: | ||
assert(false); | ||
} | ||
} | ||
visitBinaryExpression(node) { | ||
var sb = this.sb; | ||
this.visitNode(node.left); | ||
sb.push(" "); | ||
sb.push(operatorTokenToString(node.operator)); | ||
sb.push(" "); | ||
this.visitNode(node.right); | ||
} | ||
visitCallExpression(node) { | ||
this.visitNode(node.expression); | ||
this.visitArguments(node.typeArguments, node.args); | ||
} | ||
visitArguments(typeArguments, args) { | ||
var sb = this.sb; | ||
if (typeArguments) { | ||
let numTypeArguments = typeArguments.length; | ||
if (numTypeArguments) { | ||
sb.push("<"); | ||
this.visitTypeNode(typeArguments[0]); | ||
for (let i = 1; i < numTypeArguments; ++i) { | ||
sb.push(", "); | ||
this.visitTypeNode(typeArguments[i]); | ||
visitNamedTypeNode(node) { | ||
this.visitTypeName(node.name); | ||
var typeArguments = node.typeArguments; | ||
if (typeArguments) { | ||
let numTypeArguments = typeArguments.length; | ||
let sb = this.sb; | ||
if (numTypeArguments) { | ||
sb.push("<"); | ||
this.visitTypeNode(typeArguments[0]); | ||
for (let i = 1; i < numTypeArguments; ++i) { | ||
sb.push(", "); | ||
this.visitTypeNode(typeArguments[i]); | ||
} | ||
sb.push(">"); | ||
} | ||
if (node.isNullable) | ||
sb.push(" | null"); | ||
} | ||
sb.push(">("); | ||
} | ||
} else { | ||
sb.push("("); | ||
} | ||
var numArgs = args.length; | ||
if (numArgs) { | ||
this.visitNode(args[0]); | ||
for (let i = 1; i < numArgs; ++i) { | ||
sb.push(", "); | ||
this.visitNode(args[i]); | ||
} | ||
} | ||
sb.push(")"); | ||
} | ||
visitClassExpression(node) { | ||
var declaration = node.declaration; | ||
this.visitClassDeclaration(declaration); | ||
} | ||
visitCommaExpression(node) { | ||
var expressions = node.expressions; | ||
var numExpressions = expressions.length; | ||
this.visitNode(expressions[0]); | ||
var sb = this.sb; | ||
for (let i = 1; i < numExpressions; ++i) { | ||
sb.push(","); | ||
this.visitNode(expressions[i]); | ||
} | ||
} | ||
visitElementAccessExpression(node) { | ||
var sb = this.sb; | ||
this.visitNode(node.expression); | ||
sb.push("["); | ||
this.visitNode(node.elementExpression); | ||
sb.push("]"); | ||
} | ||
visitFunctionExpression(node) { | ||
var declaration = node.declaration; | ||
if (!declaration.arrowKind) { | ||
if (declaration.name.text.length) { | ||
this.sb.push("function "); | ||
} else { | ||
this.sb.push("function"); | ||
} | ||
} else { | ||
assert(declaration.name.text.length == 0); | ||
} | ||
this.visitFunctionCommon(declaration); | ||
} | ||
visitLiteralExpression(node) { | ||
switch (node.literalKind) { | ||
case 0: { | ||
this.visitFloatLiteralExpression(node); | ||
break; | ||
} | ||
case 1: { | ||
this.visitIntegerLiteralExpression(node); | ||
break; | ||
} | ||
case 2: { | ||
this.visitStringLiteralExpression(node); | ||
break; | ||
} | ||
case 3: { | ||
this.visitTemplateLiteralExpression(node); | ||
break; | ||
} | ||
case 4: { | ||
this.visitRegexpLiteralExpression(node); | ||
break; | ||
} | ||
case 5: { | ||
this.visitArrayLiteralExpression(node); | ||
break; | ||
} | ||
case 6: { | ||
this.visitObjectLiteralExpression(node); | ||
break; | ||
} | ||
default: { | ||
assert(false); | ||
break; | ||
} | ||
} | ||
} | ||
visitFloatLiteralExpression(node) { | ||
this.sb.push(node.value.toString()); | ||
} | ||
visitInstanceOfExpression(node) { | ||
this.visitNode(node.expression); | ||
this.sb.push(" instanceof "); | ||
this.visitTypeNode(node.isType); | ||
} | ||
visitIntegerLiteralExpression(node) { | ||
this.sb.push(i64_to_string(node.value)); | ||
} | ||
visitStringLiteral(str) { | ||
var sb = this.sb; | ||
sb.push('"'); | ||
this.visitRawString(str, 34); | ||
sb.push('"'); | ||
} | ||
visitRawString(str, quote) { | ||
var sb = this.sb; | ||
var off = 0; | ||
var i = 0; | ||
for (let k = str.length; i < k; ) { | ||
switch (str.charCodeAt(i)) { | ||
case 0: { | ||
if (i > off) sb.push(str.substring(off, (off = i + 1))); | ||
sb.push("\\0"); | ||
off = ++i; | ||
break; | ||
visitFunctionTypeNode(node) { | ||
var isNullable = node.isNullable; | ||
var sb = this.sb; | ||
sb.push(isNullable ? "((" : "("); | ||
var explicitThisType = node.explicitThisType; | ||
if (explicitThisType) { | ||
sb.push("this: "); | ||
this.visitTypeNode(explicitThisType); | ||
} | ||
case 92: { | ||
if (i > off) sb.push(str.substring(off, i)); | ||
off = ++i; | ||
sb.push("\\b"); | ||
break; | ||
var parameters = node.parameters; | ||
var numParameters = parameters.length; | ||
if (numParameters) { | ||
if (explicitThisType) | ||
sb.push(", "); | ||
this.serializeParameter(parameters[0]); | ||
for (let i = 1; i < numParameters; ++i) { | ||
sb.push(", "); | ||
this.serializeParameter(parameters[i]); | ||
} | ||
} | ||
case 9: { | ||
if (i > off) sb.push(str.substring(off, i)); | ||
off = ++i; | ||
sb.push("\\t"); | ||
break; | ||
var returnType = node.returnType; | ||
if (returnType) { | ||
sb.push(") => "); | ||
this.visitTypeNode(returnType); | ||
} | ||
case 10: { | ||
if (i > off) sb.push(str.substring(off, i)); | ||
off = ++i; | ||
sb.push("\\n"); | ||
break; | ||
else { | ||
sb.push(") => void"); | ||
} | ||
case 11: { | ||
if (i > off) sb.push(str.substring(off, i)); | ||
off = ++i; | ||
sb.push("\\v"); | ||
break; | ||
if (isNullable) | ||
sb.push(") | null"); | ||
} | ||
visitTypeParameter(node) { | ||
this.visitIdentifierExpression(node.name); | ||
var extendsType = node.extendsType; | ||
if (extendsType) { | ||
this.sb.push(" extends "); | ||
this.visitTypeNode(extendsType); | ||
} | ||
case 12: { | ||
if (i > off) sb.push(str.substring(off, i)); | ||
off = ++i; | ||
sb.push("\\f"); | ||
break; | ||
var defaultType = node.defaultType; | ||
if (defaultType) { | ||
this.sb.push("="); | ||
this.visitTypeNode(defaultType); | ||
} | ||
case 13: { | ||
if (i > off) sb.push(str.substring(off, i)); | ||
sb.push("\\r"); | ||
off = ++i; | ||
break; | ||
} | ||
visitIdentifierExpression(node) { | ||
if (node.isQuoted) | ||
this.visitStringLiteral(node.text); | ||
else | ||
this.sb.push(node.text); | ||
} | ||
visitArrayLiteralExpression(node) { | ||
var sb = this.sb; | ||
sb.push("["); | ||
var elements = node.elementExpressions; | ||
var numElements = elements.length; | ||
if (numElements) { | ||
let element = elements[0]; | ||
if (element) | ||
this.visitNode(element); | ||
for (let i = 1; i < numElements; ++i) { | ||
element = elements[i]; | ||
sb.push(", "); | ||
if (element) | ||
this.visitNode(element); | ||
} | ||
} | ||
case 34: { | ||
if (quote == 34) { | ||
if (i > off) sb.push(str.substring(off, i)); | ||
sb.push('\\"'); | ||
off = ++i; | ||
} else { | ||
++i; | ||
} | ||
break; | ||
sb.push("]"); | ||
} | ||
visitObjectLiteralExpression(node) { | ||
var sb = this.sb; | ||
var names = node.names; | ||
var values = node.values; | ||
var numElements = names.length; | ||
assert(numElements == values.length); | ||
if (numElements) { | ||
sb.push("{\n"); | ||
util.indent(sb, ++this.indentLevel); | ||
this.visitNode(names[0]); | ||
sb.push(": "); | ||
this.visitNode(values[0]); | ||
for (let i = 1; i < numElements; ++i) { | ||
sb.push(",\n"); | ||
util.indent(sb, this.indentLevel); | ||
let name = names[i]; | ||
let value = values[i]; | ||
if (name == value) { | ||
this.visitNode(name); | ||
} | ||
else { | ||
this.visitNode(name); | ||
sb.push(": "); | ||
this.visitNode(value); | ||
} | ||
} | ||
sb.push("\n"); | ||
util.indent(sb, --this.indentLevel); | ||
sb.push("}"); | ||
} | ||
case 39: { | ||
if (quote == 39) { | ||
if (i > off) sb.push(str.substring(off, i)); | ||
sb.push("\\'"); | ||
off = ++i; | ||
} else { | ||
++i; | ||
} | ||
break; | ||
else { | ||
sb.push("{}"); | ||
} | ||
case 92: { | ||
if (i > off) sb.push(str.substring(off, i)); | ||
sb.push("\\\\"); | ||
off = ++i; | ||
break; | ||
} | ||
visitAssertionExpression(node) { | ||
var sb = this.sb; | ||
switch (node.assertionKind) { | ||
case 0: { | ||
sb.push("<"); | ||
if (node.toType) | ||
this.visitTypeNode(node.toType); | ||
sb.push(">"); | ||
this.visitNode(node.expression); | ||
break; | ||
} | ||
case 1: { | ||
this.visitNode(node.expression); | ||
sb.push(" as "); | ||
if (node.toType) | ||
this.visitTypeNode(node.toType); | ||
break; | ||
} | ||
case 2: { | ||
this.visitNode(node.expression); | ||
sb.push("!"); | ||
break; | ||
} | ||
case 3: { | ||
this.visitNode(node.expression); | ||
sb.push(" as const"); | ||
break; | ||
} | ||
default: | ||
assert(false); | ||
} | ||
case 96: { | ||
if (quote == 96) { | ||
if (i > off) sb.push(str.substring(off, i)); | ||
sb.push("\\`"); | ||
off = ++i; | ||
} else { | ||
++i; | ||
} | ||
break; | ||
} | ||
default: { | ||
++i; | ||
break; | ||
} | ||
} | ||
} | ||
if (i > off) sb.push(str.substring(off, i)); | ||
} | ||
visitStringLiteralExpression(node) { | ||
this.visitStringLiteral(node.value); | ||
} | ||
visitTemplateLiteralExpression(node) { | ||
var sb = this.sb; | ||
var tag = node.tag; | ||
var parts = node.parts; | ||
var expressions = node.expressions; | ||
if (tag) this.visitNode(tag); | ||
sb.push("`"); | ||
this.visitRawString(parts[0], 96); | ||
assert(parts.length == expressions.length + 1); | ||
for (let i = 0, k = expressions.length; i < k; ++i) { | ||
sb.push("${"); | ||
this.visitNode(expressions[i]); | ||
sb.push("}"); | ||
this.visitRawString(parts[i + 1], 96); | ||
visitBinaryExpression(node) { | ||
var sb = this.sb; | ||
this.visitNode(node.left); | ||
sb.push(" "); | ||
sb.push(operatorTokenToString(node.operator)); | ||
sb.push(" "); | ||
this.visitNode(node.right); | ||
} | ||
sb.push("`"); | ||
} | ||
visitRegexpLiteralExpression(node) { | ||
var sb = this.sb; | ||
sb.push("/"); | ||
sb.push(node.pattern); | ||
sb.push("/"); | ||
sb.push(node.patternFlags); | ||
} | ||
visitNewExpression(node) { | ||
this.sb.push("new "); | ||
this.visitTypeName(node.typeName); | ||
this.visitArguments(node.typeArguments, node.args); | ||
} | ||
visitParenthesizedExpression(node) { | ||
var sb = this.sb; | ||
sb.push("("); | ||
this.visitNode(node.expression); | ||
sb.push(")"); | ||
} | ||
visitPropertyAccessExpression(node) { | ||
this.visitNode(node.expression); | ||
this.sb.push("."); | ||
this.visitIdentifierExpression(node.property); | ||
} | ||
visitTernaryExpression(node) { | ||
var sb = this.sb; | ||
this.visitNode(node.condition); | ||
sb.push(" ? "); | ||
this.visitNode(node.ifThen); | ||
sb.push(" : "); | ||
this.visitNode(node.ifElse); | ||
} | ||
visitUnaryExpression(node) { | ||
switch (node.kind) { | ||
case 27: { | ||
this.visitUnaryPostfixExpression(node); | ||
break; | ||
} | ||
case 28: { | ||
this.visitUnaryPrefixExpression(node); | ||
break; | ||
} | ||
default: | ||
assert(false); | ||
visitCallExpression(node) { | ||
this.visitNode(node.expression); | ||
this.visitArguments(node.typeArguments, node.args); | ||
} | ||
} | ||
visitUnaryPostfixExpression(node) { | ||
this.visitNode(node.operand); | ||
this.sb.push(operatorTokenToString(node.operator)); | ||
} | ||
visitUnaryPrefixExpression(node) { | ||
this.sb.push(operatorTokenToString(node.operator)); | ||
this.visitNode(node.operand); | ||
} | ||
visitNodeAndTerminate(node) { | ||
this.visitNode(node); | ||
var sb = this.sb; | ||
if (!sb.length || node.kind == 47 || node.kind == 38) { | ||
sb.push(";\n"); | ||
} else { | ||
let last = sb[sb.length - 1]; | ||
let lastCharPos = last.length - 1; | ||
if (lastCharPos >= 0 && (last.charCodeAt(lastCharPos) == 125 || last.charCodeAt(lastCharPos) == 59)) { | ||
sb.push("\n"); | ||
} else { | ||
sb.push(";\n"); | ||
} | ||
visitArguments(typeArguments, args) { | ||
var sb = this.sb; | ||
if (typeArguments) { | ||
let numTypeArguments = typeArguments.length; | ||
if (numTypeArguments) { | ||
sb.push("<"); | ||
this.visitTypeNode(typeArguments[0]); | ||
for (let i = 1; i < numTypeArguments; ++i) { | ||
sb.push(", "); | ||
this.visitTypeNode(typeArguments[i]); | ||
} | ||
sb.push(">("); | ||
} | ||
} | ||
else { | ||
sb.push("("); | ||
} | ||
var numArgs = args.length; | ||
if (numArgs) { | ||
this.visitNode(args[0]); | ||
for (let i = 1; i < numArgs; ++i) { | ||
sb.push(", "); | ||
this.visitNode(args[i]); | ||
} | ||
} | ||
sb.push(")"); | ||
} | ||
} | ||
visitBlockStatement(node) { | ||
var sb = this.sb; | ||
var statements = node.statements; | ||
var numStatements = statements.length; | ||
if (numStatements) { | ||
sb.push("{\n"); | ||
let indentLevel = ++this.indentLevel; | ||
for (let i = 0; i < numStatements; ++i) { | ||
util.indent(sb, indentLevel); | ||
this.visitNodeAndTerminate(statements[i]); | ||
} | ||
util.indent(sb, --this.indentLevel); | ||
sb.push("}"); | ||
} else { | ||
sb.push("{}"); | ||
visitClassExpression(node) { | ||
var declaration = node.declaration; | ||
this.visitClassDeclaration(declaration); | ||
} | ||
} | ||
visitBreakStatement(node) { | ||
var label = node.label; | ||
if (label) { | ||
this.sb.push("break "); | ||
this.visitIdentifierExpression(label); | ||
} else { | ||
this.sb.push("break"); | ||
visitCommaExpression(node) { | ||
var expressions = node.expressions; | ||
var numExpressions = expressions.length; | ||
this.visitNode(expressions[0]); | ||
var sb = this.sb; | ||
for (let i = 1; i < numExpressions; ++i) { | ||
sb.push(","); | ||
this.visitNode(expressions[i]); | ||
} | ||
} | ||
} | ||
visitContinueStatement(node) { | ||
var label = node.label; | ||
if (label) { | ||
this.sb.push("continue "); | ||
this.visitIdentifierExpression(label); | ||
} else { | ||
this.sb.push("continue"); | ||
visitElementAccessExpression(node) { | ||
var sb = this.sb; | ||
this.visitNode(node.expression); | ||
sb.push("["); | ||
this.visitNode(node.elementExpression); | ||
sb.push("]"); | ||
} | ||
} | ||
visitClassDeclaration(node, isDefault = false) { | ||
var decorators = node.decorators; | ||
if (decorators) { | ||
for (let i = 0, k = decorators.length; i < k; ++i) { | ||
this.serializeDecorator(decorators[i]); | ||
} | ||
} | ||
var sb = this.sb; | ||
if (isDefault) { | ||
sb.push("export default "); | ||
} else { | ||
this.serializeExternalModifiers(node); | ||
} | ||
if (node.is(128)) sb.push("abstract "); | ||
if (node.name.text.length) { | ||
sb.push("class "); | ||
this.visitIdentifierExpression(node.name); | ||
} else { | ||
sb.push("class"); | ||
} | ||
var typeParameters = node.typeParameters; | ||
if (typeParameters != null && typeParameters.length > 0) { | ||
sb.push("<"); | ||
this.visitTypeParameter(typeParameters[0]); | ||
for (let i = 1, k = typeParameters.length; i < k; ++i) { | ||
sb.push(", "); | ||
this.visitTypeParameter(typeParameters[i]); | ||
} | ||
sb.push(">"); | ||
} | ||
var extendsType = node.extendsType; | ||
if (extendsType) { | ||
sb.push(" extends "); | ||
this.visitTypeNode(extendsType); | ||
} | ||
var implementsTypes = node.implementsTypes; | ||
if (implementsTypes) { | ||
let numImplementsTypes = implementsTypes.length; | ||
if (numImplementsTypes) { | ||
sb.push(" implements "); | ||
this.visitTypeNode(implementsTypes[0]); | ||
for (let i = 1; i < numImplementsTypes; ++i) { | ||
sb.push(", "); | ||
this.visitTypeNode(implementsTypes[i]); | ||
visitFunctionExpression(node) { | ||
var declaration = node.declaration; | ||
if (!declaration.arrowKind) { | ||
if (declaration.name.text.length) { | ||
this.sb.push("function "); | ||
} | ||
else { | ||
this.sb.push("function"); | ||
} | ||
} | ||
} | ||
else { | ||
assert(declaration.name.text.length == 0); | ||
} | ||
this.visitFunctionCommon(declaration); | ||
} | ||
var indexSignature = node.indexSignature; | ||
var members = node.members; | ||
var numMembers = members.length; | ||
if (indexSignature !== null || numMembers) { | ||
sb.push(" {\n"); | ||
let indentLevel = ++this.indentLevel; | ||
if (indexSignature) { | ||
util.indent(sb, indentLevel); | ||
this.visitNodeAndTerminate(indexSignature); | ||
} | ||
for (let i = 0, k = members.length; i < k; ++i) { | ||
let member = members[i]; | ||
if (member.kind != 54 || member.parameterIndex < 0) { | ||
util.indent(sb, indentLevel); | ||
this.visitNodeAndTerminate(member); | ||
visitLiteralExpression(node) { | ||
switch (node.literalKind) { | ||
case 0: { | ||
this.visitFloatLiteralExpression(node); | ||
break; | ||
} | ||
case 1: { | ||
this.visitIntegerLiteralExpression(node); | ||
break; | ||
} | ||
case 2: { | ||
this.visitStringLiteralExpression(node); | ||
break; | ||
} | ||
case 3: { | ||
this.visitTemplateLiteralExpression(node); | ||
break; | ||
} | ||
case 4: { | ||
this.visitRegexpLiteralExpression(node); | ||
break; | ||
} | ||
case 5: { | ||
this.visitArrayLiteralExpression(node); | ||
break; | ||
} | ||
case 6: { | ||
this.visitObjectLiteralExpression(node); | ||
break; | ||
} | ||
default: { | ||
assert(false); | ||
break; | ||
} | ||
} | ||
} | ||
util.indent(sb, --this.indentLevel); | ||
sb.push("}"); | ||
} else { | ||
sb.push(" {}"); | ||
} | ||
} | ||
visitDoStatement(node) { | ||
var sb = this.sb; | ||
sb.push("do "); | ||
this.visitNode(node.body); | ||
if (node.body.kind == 30) { | ||
sb.push(" while ("); | ||
} else { | ||
util.indent(sb, this.indentLevel); | ||
sb.push("while ("); | ||
visitFloatLiteralExpression(node) { | ||
this.sb.push(node.value.toString()); | ||
} | ||
this.visitNode(node.condition); | ||
sb.push(")"); | ||
} | ||
visitEmptyStatement(node) {} | ||
visitEnumDeclaration(node, isDefault = false) { | ||
var sb = this.sb; | ||
if (isDefault) { | ||
sb.push("export default "); | ||
} else { | ||
this.serializeExternalModifiers(node); | ||
visitInstanceOfExpression(node) { | ||
this.visitNode(node.expression); | ||
this.sb.push(" instanceof "); | ||
this.visitTypeNode(node.isType); | ||
} | ||
if (node.is(8)) sb.push("const "); | ||
sb.push("enum "); | ||
this.visitIdentifierExpression(node.name); | ||
var values = node.values; | ||
var numValues = values.length; | ||
if (numValues) { | ||
sb.push(" {\n"); | ||
let indentLevel = ++this.indentLevel; | ||
util.indent(sb, indentLevel); | ||
this.visitEnumValueDeclaration(node.values[0]); | ||
for (let i = 1; i < numValues; ++i) { | ||
sb.push(",\n"); | ||
util.indent(sb, indentLevel); | ||
this.visitEnumValueDeclaration(node.values[i]); | ||
} | ||
sb.push("\n"); | ||
util.indent(sb, --this.indentLevel); | ||
sb.push("}"); | ||
} else { | ||
sb.push(" {}"); | ||
visitIntegerLiteralExpression(node) { | ||
this.sb.push(i64_to_string(node.value)); | ||
} | ||
} | ||
visitEnumValueDeclaration(node) { | ||
this.visitIdentifierExpression(node.name); | ||
var initializer = node.initializer; | ||
if (initializer) { | ||
this.sb.push(" = "); | ||
this.visitNode(initializer); | ||
visitStringLiteral(str) { | ||
var sb = this.sb; | ||
sb.push('"'); | ||
this.visitRawString(str, 34); | ||
sb.push('"'); | ||
} | ||
} | ||
visitExportImportStatement(node) { | ||
var sb = this.sb; | ||
sb.push("export import "); | ||
this.visitIdentifierExpression(node.externalName); | ||
sb.push(" = "); | ||
this.visitIdentifierExpression(node.name); | ||
} | ||
visitExportMember(node) { | ||
this.visitIdentifierExpression(node.localName); | ||
if (node.exportedName.text != node.localName.text) { | ||
this.sb.push(" as "); | ||
this.visitIdentifierExpression(node.exportedName); | ||
visitRawString(str, quote) { | ||
var sb = this.sb; | ||
var off = 0; | ||
var i = 0; | ||
for (let k = str.length; i < k;) { | ||
switch (str.charCodeAt(i)) { | ||
case 0: { | ||
if (i > off) | ||
sb.push(str.substring(off, (off = i + 1))); | ||
sb.push("\\0"); | ||
off = ++i; | ||
break; | ||
} | ||
case 92: { | ||
if (i > off) | ||
sb.push(str.substring(off, i)); | ||
off = ++i; | ||
sb.push("\\b"); | ||
break; | ||
} | ||
case 9: { | ||
if (i > off) | ||
sb.push(str.substring(off, i)); | ||
off = ++i; | ||
sb.push("\\t"); | ||
break; | ||
} | ||
case 10: { | ||
if (i > off) | ||
sb.push(str.substring(off, i)); | ||
off = ++i; | ||
sb.push("\\n"); | ||
break; | ||
} | ||
case 11: { | ||
if (i > off) | ||
sb.push(str.substring(off, i)); | ||
off = ++i; | ||
sb.push("\\v"); | ||
break; | ||
} | ||
case 12: { | ||
if (i > off) | ||
sb.push(str.substring(off, i)); | ||
off = ++i; | ||
sb.push("\\f"); | ||
break; | ||
} | ||
case 13: { | ||
if (i > off) | ||
sb.push(str.substring(off, i)); | ||
sb.push("\\r"); | ||
off = ++i; | ||
break; | ||
} | ||
case 34: { | ||
if (quote == 34) { | ||
if (i > off) | ||
sb.push(str.substring(off, i)); | ||
sb.push('\\"'); | ||
off = ++i; | ||
} | ||
else { | ||
++i; | ||
} | ||
break; | ||
} | ||
case 39: { | ||
if (quote == 39) { | ||
if (i > off) | ||
sb.push(str.substring(off, i)); | ||
sb.push("\\'"); | ||
off = ++i; | ||
} | ||
else { | ||
++i; | ||
} | ||
break; | ||
} | ||
case 92: { | ||
if (i > off) | ||
sb.push(str.substring(off, i)); | ||
sb.push("\\\\"); | ||
off = ++i; | ||
break; | ||
} | ||
case 96: { | ||
if (quote == 96) { | ||
if (i > off) | ||
sb.push(str.substring(off, i)); | ||
sb.push("\\`"); | ||
off = ++i; | ||
} | ||
else { | ||
++i; | ||
} | ||
break; | ||
} | ||
default: { | ||
++i; | ||
break; | ||
} | ||
} | ||
} | ||
if (i > off) | ||
sb.push(str.substring(off, i)); | ||
} | ||
} | ||
visitExportStatement(node) { | ||
var sb = this.sb; | ||
if (node.isDeclare) { | ||
sb.push("declare "); | ||
visitStringLiteralExpression(node) { | ||
this.visitStringLiteral(node.value); | ||
} | ||
var members = node.members; | ||
if (members == null) { | ||
sb.push("export *"); | ||
} else if (members.length > 0) { | ||
let numMembers = members.length; | ||
sb.push("export {\n"); | ||
let indentLevel = ++this.indentLevel; | ||
util.indent(sb, indentLevel); | ||
this.visitExportMember(members[0]); | ||
for (let i = 1; i < numMembers; ++i) { | ||
sb.push(",\n"); | ||
util.indent(sb, indentLevel); | ||
this.visitExportMember(members[i]); | ||
} | ||
--this.indentLevel; | ||
sb.push("\n}"); | ||
} else { | ||
sb.push("export {}"); | ||
visitTemplateLiteralExpression(node) { | ||
var sb = this.sb; | ||
var tag = node.tag; | ||
var parts = node.parts; | ||
var expressions = node.expressions; | ||
if (tag) | ||
this.visitNode(tag); | ||
sb.push("`"); | ||
this.visitRawString(parts[0], 96); | ||
assert(parts.length == expressions.length + 1); | ||
for (let i = 0, k = expressions.length; i < k; ++i) { | ||
sb.push("${"); | ||
this.visitNode(expressions[i]); | ||
sb.push("}"); | ||
this.visitRawString(parts[i + 1], 96); | ||
} | ||
sb.push("`"); | ||
} | ||
var path = node.path; | ||
if (path) { | ||
sb.push(" from "); | ||
this.visitStringLiteralExpression(path); | ||
visitRegexpLiteralExpression(node) { | ||
var sb = this.sb; | ||
sb.push("/"); | ||
sb.push(node.pattern); | ||
sb.push("/"); | ||
sb.push(node.patternFlags); | ||
} | ||
sb.push(";"); | ||
} | ||
visitExportDefaultStatement(node) { | ||
var declaration = node.declaration; | ||
switch (declaration.kind) { | ||
case 52: { | ||
this.visitEnumDeclaration(declaration, true); | ||
break; | ||
} | ||
case 55: { | ||
this.visitFunctionDeclaration(declaration, true); | ||
break; | ||
} | ||
case 51: { | ||
this.visitClassDeclaration(declaration, true); | ||
break; | ||
} | ||
case 57: { | ||
this.visitInterfaceDeclaration(declaration, true); | ||
break; | ||
} | ||
case 59: { | ||
this.visitNamespaceDeclaration(declaration, true); | ||
break; | ||
} | ||
default: | ||
assert(false); | ||
visitNewExpression(node) { | ||
this.sb.push("new "); | ||
this.visitTypeName(node.typeName); | ||
this.visitArguments(node.typeArguments, node.args); | ||
} | ||
} | ||
visitExpressionStatement(node) { | ||
this.visitNode(node.expression); | ||
} | ||
visitFieldDeclaration(node) { | ||
var decorators = node.decorators; | ||
if (decorators) { | ||
for (let i = 0, k = decorators.length; i < k; ++i) { | ||
this.serializeDecorator(decorators[i]); | ||
} | ||
visitParenthesizedExpression(node) { | ||
var sb = this.sb; | ||
sb.push("("); | ||
this.visitNode(node.expression); | ||
sb.push(")"); | ||
} | ||
this.serializeAccessModifiers(node); | ||
this.visitIdentifierExpression(node.name); | ||
var sb = this.sb; | ||
if (node.flags & 16384) { | ||
sb.push("!"); | ||
visitPropertyAccessExpression(node) { | ||
this.visitNode(node.expression); | ||
this.sb.push("."); | ||
this.visitIdentifierExpression(node.property); | ||
} | ||
var type = node.type; | ||
if (type) { | ||
sb.push(": "); | ||
this.visitTypeNode(type); | ||
visitTernaryExpression(node) { | ||
var sb = this.sb; | ||
this.visitNode(node.condition); | ||
sb.push(" ? "); | ||
this.visitNode(node.ifThen); | ||
sb.push(" : "); | ||
this.visitNode(node.ifElse); | ||
} | ||
var initializer = node.initializer; | ||
if (initializer) { | ||
sb.push(" = "); | ||
this.visitNode(initializer); | ||
visitUnaryExpression(node) { | ||
switch (node.kind) { | ||
case 27: { | ||
this.visitUnaryPostfixExpression(node); | ||
break; | ||
} | ||
case 28: { | ||
this.visitUnaryPrefixExpression(node); | ||
break; | ||
} | ||
default: | ||
assert(false); | ||
} | ||
} | ||
} | ||
visitForStatement(node) { | ||
var sb = this.sb; | ||
sb.push("for ("); | ||
var initializer = node.initializer; | ||
if (initializer) { | ||
this.visitNode(initializer); | ||
visitUnaryPostfixExpression(node) { | ||
this.visitNode(node.operand); | ||
this.sb.push(operatorTokenToString(node.operator)); | ||
} | ||
var condition = node.condition; | ||
if (condition) { | ||
sb.push("; "); | ||
this.visitNode(condition); | ||
} else { | ||
sb.push(";"); | ||
visitUnaryPrefixExpression(node) { | ||
this.sb.push(operatorTokenToString(node.operator)); | ||
this.visitNode(node.operand); | ||
} | ||
var incrementor = node.incrementor; | ||
if (incrementor) { | ||
sb.push("; "); | ||
this.visitNode(incrementor); | ||
} else { | ||
sb.push(";"); | ||
visitNodeAndTerminate(node) { | ||
this.visitNode(node); | ||
var sb = this.sb; | ||
if (!sb.length || | ||
node.kind == 47 || | ||
node.kind == 38) { | ||
sb.push(";\n"); | ||
} | ||
else { | ||
let last = sb[sb.length - 1]; | ||
let lastCharPos = last.length - 1; | ||
if (lastCharPos >= 0 && (last.charCodeAt(lastCharPos) == 125 || last.charCodeAt(lastCharPos) == 59)) { | ||
sb.push("\n"); | ||
} | ||
else { | ||
sb.push(";\n"); | ||
} | ||
} | ||
} | ||
sb.push(") "); | ||
this.visitNode(node.body); | ||
} | ||
visitForOfStatement(node) { | ||
var sb = this.sb; | ||
sb.push("for ("); | ||
this.visitNode(node.variable); | ||
sb.push(" of "); | ||
this.visitNode(node.iterable); | ||
sb.push(") "); | ||
this.visitNode(node.body); | ||
} | ||
visitFunctionDeclaration(node, isDefault = false) { | ||
var sb = this.sb; | ||
var decorators = node.decorators; | ||
if (decorators) { | ||
for (let i = 0, k = decorators.length; i < k; ++i) { | ||
this.serializeDecorator(decorators[i]); | ||
} | ||
visitBlockStatement(node) { | ||
var sb = this.sb; | ||
var statements = node.statements; | ||
var numStatements = statements.length; | ||
if (numStatements) { | ||
sb.push("{\n"); | ||
let indentLevel = ++this.indentLevel; | ||
for (let i = 0; i < numStatements; ++i) { | ||
util.indent(sb, indentLevel); | ||
this.visitNodeAndTerminate(statements[i]); | ||
} | ||
util.indent(sb, --this.indentLevel); | ||
sb.push("}"); | ||
} | ||
else { | ||
sb.push("{}"); | ||
} | ||
} | ||
if (isDefault) { | ||
sb.push("export default "); | ||
} else { | ||
this.serializeExternalModifiers(node); | ||
this.serializeAccessModifiers(node); | ||
visitBreakStatement(node) { | ||
var label = node.label; | ||
if (label) { | ||
this.sb.push("break "); | ||
this.visitIdentifierExpression(label); | ||
} | ||
else { | ||
this.sb.push("break"); | ||
} | ||
} | ||
if (node.name.text.length) { | ||
sb.push("function "); | ||
} else { | ||
sb.push("function"); | ||
} | ||
this.visitFunctionCommon(node); | ||
} | ||
visitFunctionCommon(node) { | ||
var sb = this.sb; | ||
this.visitIdentifierExpression(node.name); | ||
var signature = node.signature; | ||
var typeParameters = node.typeParameters; | ||
if (typeParameters) { | ||
let numTypeParameters = typeParameters.length; | ||
if (numTypeParameters) { | ||
sb.push("<"); | ||
this.visitTypeParameter(typeParameters[0]); | ||
for (let i = 1; i < numTypeParameters; ++i) { | ||
sb.push(", "); | ||
this.visitTypeParameter(typeParameters[i]); | ||
visitContinueStatement(node) { | ||
var label = node.label; | ||
if (label) { | ||
this.sb.push("continue "); | ||
this.visitIdentifierExpression(label); | ||
} | ||
sb.push(">"); | ||
} | ||
else { | ||
this.sb.push("continue"); | ||
} | ||
} | ||
if (node.arrowKind == 2) { | ||
let parameters = signature.parameters; | ||
assert(parameters.length == 1); | ||
assert(!signature.explicitThisType); | ||
this.serializeParameter(parameters[0]); | ||
} else { | ||
sb.push("("); | ||
let parameters = signature.parameters; | ||
let numParameters = parameters.length; | ||
let explicitThisType = signature.explicitThisType; | ||
if (explicitThisType) { | ||
sb.push("this: "); | ||
this.visitTypeNode(explicitThisType); | ||
} | ||
if (numParameters) { | ||
if (explicitThisType) sb.push(", "); | ||
this.serializeParameter(parameters[0]); | ||
for (let i = 1; i < numParameters; ++i) { | ||
sb.push(", "); | ||
this.serializeParameter(parameters[i]); | ||
visitClassDeclaration(node, isDefault = false) { | ||
var decorators = node.decorators; | ||
if (decorators) { | ||
for (let i = 0, k = decorators.length; i < k; ++i) { | ||
this.serializeDecorator(decorators[i]); | ||
} | ||
} | ||
} | ||
var sb = this.sb; | ||
if (isDefault) { | ||
sb.push("export default "); | ||
} | ||
else { | ||
this.serializeExternalModifiers(node); | ||
} | ||
if (node.is(128)) | ||
sb.push("abstract "); | ||
if (node.name.text.length) { | ||
sb.push("class "); | ||
this.visitIdentifierExpression(node.name); | ||
} | ||
else { | ||
sb.push("class"); | ||
} | ||
var typeParameters = node.typeParameters; | ||
if (typeParameters != null && typeParameters.length > 0) { | ||
sb.push("<"); | ||
this.visitTypeParameter(typeParameters[0]); | ||
for (let i = 1, k = typeParameters.length; i < k; ++i) { | ||
sb.push(", "); | ||
this.visitTypeParameter(typeParameters[i]); | ||
} | ||
sb.push(">"); | ||
} | ||
var extendsType = node.extendsType; | ||
if (extendsType) { | ||
sb.push(" extends "); | ||
this.visitTypeNode(extendsType); | ||
} | ||
var implementsTypes = node.implementsTypes; | ||
if (implementsTypes) { | ||
let numImplementsTypes = implementsTypes.length; | ||
if (numImplementsTypes) { | ||
sb.push(" implements "); | ||
this.visitTypeNode(implementsTypes[0]); | ||
for (let i = 1; i < numImplementsTypes; ++i) { | ||
sb.push(", "); | ||
this.visitTypeNode(implementsTypes[i]); | ||
} | ||
} | ||
} | ||
var indexSignature = node.indexSignature; | ||
var members = node.members; | ||
var numMembers = members.length; | ||
if (indexSignature !== null || numMembers) { | ||
sb.push(" {\n"); | ||
let indentLevel = ++this.indentLevel; | ||
if (indexSignature) { | ||
util.indent(sb, indentLevel); | ||
this.visitNodeAndTerminate(indexSignature); | ||
} | ||
for (let i = 0, k = members.length; i < k; ++i) { | ||
let member = members[i]; | ||
if (member.kind != 54 || member.parameterIndex < 0) { | ||
util.indent(sb, indentLevel); | ||
this.visitNodeAndTerminate(member); | ||
} | ||
} | ||
util.indent(sb, --this.indentLevel); | ||
sb.push("}"); | ||
} | ||
else { | ||
sb.push(" {}"); | ||
} | ||
} | ||
var body = node.body; | ||
var returnType = signature.returnType; | ||
if (node.arrowKind) { | ||
if (body) { | ||
if (node.arrowKind == 2) { | ||
assert(isTypeOmitted(returnType)); | ||
} else { | ||
if (isTypeOmitted(returnType)) { | ||
sb.push(")"); | ||
} else { | ||
sb.push("): "); | ||
this.visitTypeNode(returnType); | ||
} | ||
visitDoStatement(node) { | ||
var sb = this.sb; | ||
sb.push("do "); | ||
this.visitNode(node.body); | ||
if (node.body.kind == 30) { | ||
sb.push(" while ("); | ||
} | ||
sb.push(" => "); | ||
this.visitNode(body); | ||
} else { | ||
assert(!isTypeOmitted(returnType)); | ||
sb.push(" => "); | ||
this.visitTypeNode(returnType); | ||
} | ||
} else { | ||
if (!isTypeOmitted(returnType) && !node.isAny(524288 | 4096)) { | ||
sb.push("): "); | ||
this.visitTypeNode(returnType); | ||
} else { | ||
else { | ||
util.indent(sb, this.indentLevel); | ||
sb.push("while ("); | ||
} | ||
this.visitNode(node.condition); | ||
sb.push(")"); | ||
} | ||
if (body) { | ||
sb.push(" "); | ||
this.visitNode(body); | ||
} | ||
} | ||
} | ||
visitIfStatement(node) { | ||
var sb = this.sb; | ||
sb.push("if ("); | ||
this.visitNode(node.condition); | ||
sb.push(") "); | ||
var ifTrue = node.ifTrue; | ||
this.visitNode(ifTrue); | ||
if (ifTrue.kind != 30) { | ||
sb.push(";\n"); | ||
visitEmptyStatement(node) { | ||
} | ||
var ifFalse = node.ifFalse; | ||
if (ifFalse) { | ||
if (ifTrue.kind == 30) { | ||
sb.push(" else "); | ||
} else { | ||
sb.push("else "); | ||
} | ||
this.visitNode(ifFalse); | ||
visitEnumDeclaration(node, isDefault = false) { | ||
var sb = this.sb; | ||
if (isDefault) { | ||
sb.push("export default "); | ||
} | ||
else { | ||
this.serializeExternalModifiers(node); | ||
} | ||
if (node.is(8)) | ||
sb.push("const "); | ||
sb.push("enum "); | ||
this.visitIdentifierExpression(node.name); | ||
var values = node.values; | ||
var numValues = values.length; | ||
if (numValues) { | ||
sb.push(" {\n"); | ||
let indentLevel = ++this.indentLevel; | ||
util.indent(sb, indentLevel); | ||
this.visitEnumValueDeclaration(node.values[0]); | ||
for (let i = 1; i < numValues; ++i) { | ||
sb.push(",\n"); | ||
util.indent(sb, indentLevel); | ||
this.visitEnumValueDeclaration(node.values[i]); | ||
} | ||
sb.push("\n"); | ||
util.indent(sb, --this.indentLevel); | ||
sb.push("}"); | ||
} | ||
else { | ||
sb.push(" {}"); | ||
} | ||
} | ||
} | ||
visitImportDeclaration(node) { | ||
var externalName = node.foreignName; | ||
var name = node.name; | ||
this.visitIdentifierExpression(externalName); | ||
if (externalName.text != name.text) { | ||
this.sb.push(" as "); | ||
this.visitIdentifierExpression(name); | ||
} | ||
} | ||
visitImportStatement(node) { | ||
var sb = this.sb; | ||
sb.push("import "); | ||
var declarations = node.declarations; | ||
var namespaceName = node.namespaceName; | ||
if (declarations) { | ||
let numDeclarations = declarations.length; | ||
if (numDeclarations) { | ||
sb.push("{\n"); | ||
let indentLevel = ++this.indentLevel; | ||
util.indent(sb, indentLevel); | ||
this.visitImportDeclaration(declarations[0]); | ||
for (let i = 1; i < numDeclarations; ++i) { | ||
sb.push(",\n"); | ||
util.indent(sb, indentLevel); | ||
this.visitImportDeclaration(declarations[i]); | ||
visitEnumValueDeclaration(node) { | ||
this.visitIdentifierExpression(node.name); | ||
var initializer = node.initializer; | ||
if (initializer) { | ||
this.sb.push(" = "); | ||
this.visitNode(initializer); | ||
} | ||
--this.indentLevel; | ||
sb.push("\n} from "); | ||
} else { | ||
sb.push("{} from "); | ||
} | ||
} else if (namespaceName) { | ||
sb.push("* as "); | ||
this.visitIdentifierExpression(namespaceName); | ||
sb.push(" from "); | ||
} | ||
this.visitStringLiteralExpression(node.path); | ||
} | ||
visitIndexSignature(node) { | ||
var sb = this.sb; | ||
sb.push("[key: "); | ||
this.visitTypeNode(node.keyType); | ||
sb.push("]: "); | ||
this.visitTypeNode(node.valueType); | ||
} | ||
visitInterfaceDeclaration(node, isDefault = false) { | ||
var decorators = node.decorators; | ||
if (decorators) { | ||
for (let i = 0, k = decorators.length; i < k; ++i) { | ||
this.serializeDecorator(decorators[i]); | ||
} | ||
visitExportImportStatement(node) { | ||
var sb = this.sb; | ||
sb.push("export import "); | ||
this.visitIdentifierExpression(node.externalName); | ||
sb.push(" = "); | ||
this.visitIdentifierExpression(node.name); | ||
} | ||
var sb = this.sb; | ||
if (isDefault) { | ||
sb.push("export default "); | ||
} else { | ||
this.serializeExternalModifiers(node); | ||
visitExportMember(node) { | ||
this.visitIdentifierExpression(node.localName); | ||
if (node.exportedName.text != node.localName.text) { | ||
this.sb.push(" as "); | ||
this.visitIdentifierExpression(node.exportedName); | ||
} | ||
} | ||
sb.push("interface "); | ||
this.visitIdentifierExpression(node.name); | ||
var typeParameters = node.typeParameters; | ||
if (typeParameters != null && typeParameters.length > 0) { | ||
sb.push("<"); | ||
this.visitTypeParameter(typeParameters[0]); | ||
for (let i = 1, k = typeParameters.length; i < k; ++i) { | ||
sb.push(", "); | ||
this.visitTypeParameter(typeParameters[i]); | ||
} | ||
sb.push(">"); | ||
visitExportStatement(node) { | ||
var sb = this.sb; | ||
if (node.isDeclare) { | ||
sb.push("declare "); | ||
} | ||
var members = node.members; | ||
if (members == null) { | ||
sb.push("export *"); | ||
} | ||
else if (members.length > 0) { | ||
let numMembers = members.length; | ||
sb.push("export {\n"); | ||
let indentLevel = ++this.indentLevel; | ||
util.indent(sb, indentLevel); | ||
this.visitExportMember(members[0]); | ||
for (let i = 1; i < numMembers; ++i) { | ||
sb.push(",\n"); | ||
util.indent(sb, indentLevel); | ||
this.visitExportMember(members[i]); | ||
} | ||
--this.indentLevel; | ||
sb.push("\n}"); | ||
} | ||
else { | ||
sb.push("export {}"); | ||
} | ||
var path = node.path; | ||
if (path) { | ||
sb.push(" from "); | ||
this.visitStringLiteralExpression(path); | ||
} | ||
sb.push(";"); | ||
} | ||
var extendsType = node.extendsType; | ||
if (extendsType) { | ||
sb.push(" extends "); | ||
this.visitTypeNode(extendsType); | ||
visitExportDefaultStatement(node) { | ||
var declaration = node.declaration; | ||
switch (declaration.kind) { | ||
case 52: { | ||
this.visitEnumDeclaration(declaration, true); | ||
break; | ||
} | ||
case 55: { | ||
this.visitFunctionDeclaration(declaration, true); | ||
break; | ||
} | ||
case 51: { | ||
this.visitClassDeclaration(declaration, true); | ||
break; | ||
} | ||
case 57: { | ||
this.visitInterfaceDeclaration(declaration, true); | ||
break; | ||
} | ||
case 59: { | ||
this.visitNamespaceDeclaration(declaration, true); | ||
break; | ||
} | ||
default: | ||
assert(false); | ||
} | ||
} | ||
sb.push(" {\n"); | ||
var indentLevel = ++this.indentLevel; | ||
var members = node.members; | ||
for (let i = 0, k = members.length; i < k; ++i) { | ||
util.indent(sb, indentLevel); | ||
this.visitNodeAndTerminate(members[i]); | ||
visitExpressionStatement(node) { | ||
this.visitNode(node.expression); | ||
} | ||
--this.indentLevel; | ||
sb.push("}"); | ||
} | ||
visitMethodDeclaration(node) { | ||
var decorators = node.decorators; | ||
if (decorators) { | ||
for (let i = 0, k = decorators.length; i < k; ++i) { | ||
this.serializeDecorator(decorators[i]); | ||
} | ||
visitFieldDeclaration(node) { | ||
var decorators = node.decorators; | ||
if (decorators) { | ||
for (let i = 0, k = decorators.length; i < k; ++i) { | ||
this.serializeDecorator(decorators[i]); | ||
} | ||
} | ||
this.serializeAccessModifiers(node); | ||
this.visitIdentifierExpression(node.name); | ||
var sb = this.sb; | ||
if (node.flags & 16384) { | ||
sb.push("!"); | ||
} | ||
var type = node.type; | ||
if (type) { | ||
sb.push(": "); | ||
this.visitTypeNode(type); | ||
} | ||
var initializer = node.initializer; | ||
if (initializer) { | ||
sb.push(" = "); | ||
this.visitNode(initializer); | ||
} | ||
} | ||
this.serializeAccessModifiers(node); | ||
if (node.is(2048)) { | ||
this.sb.push("get "); | ||
} else if (node.is(4096)) { | ||
this.sb.push("set "); | ||
visitForStatement(node) { | ||
var sb = this.sb; | ||
sb.push("for ("); | ||
var initializer = node.initializer; | ||
if (initializer) { | ||
this.visitNode(initializer); | ||
} | ||
var condition = node.condition; | ||
if (condition) { | ||
sb.push("; "); | ||
this.visitNode(condition); | ||
} | ||
else { | ||
sb.push(";"); | ||
} | ||
var incrementor = node.incrementor; | ||
if (incrementor) { | ||
sb.push("; "); | ||
this.visitNode(incrementor); | ||
} | ||
else { | ||
sb.push(";"); | ||
} | ||
sb.push(") "); | ||
this.visitNode(node.body); | ||
} | ||
this.visitFunctionCommon(node); | ||
} | ||
visitNamespaceDeclaration(node, isDefault = false) { | ||
var decorators = node.decorators; | ||
if (decorators) { | ||
for (let i = 0, k = decorators.length; i < k; ++i) { | ||
this.serializeDecorator(decorators[i]); | ||
} | ||
visitForOfStatement(node) { | ||
var sb = this.sb; | ||
sb.push("for ("); | ||
this.visitNode(node.variable); | ||
sb.push(" of "); | ||
this.visitNode(node.iterable); | ||
sb.push(") "); | ||
this.visitNode(node.body); | ||
} | ||
var sb = this.sb; | ||
if (isDefault) { | ||
sb.push("export default "); | ||
} else { | ||
this.serializeExternalModifiers(node); | ||
visitFunctionDeclaration(node, isDefault = false) { | ||
var sb = this.sb; | ||
var decorators = node.decorators; | ||
if (decorators) { | ||
for (let i = 0, k = decorators.length; i < k; ++i) { | ||
this.serializeDecorator(decorators[i]); | ||
} | ||
} | ||
if (isDefault) { | ||
sb.push("export default "); | ||
} | ||
else { | ||
this.serializeExternalModifiers(node); | ||
this.serializeAccessModifiers(node); | ||
} | ||
if (node.name.text.length) { | ||
sb.push("function "); | ||
} | ||
else { | ||
sb.push("function"); | ||
} | ||
this.visitFunctionCommon(node); | ||
} | ||
sb.push("namespace "); | ||
this.visitIdentifierExpression(node.name); | ||
var members = node.members; | ||
var numMembers = members.length; | ||
if (numMembers) { | ||
sb.push(" {\n"); | ||
let indentLevel = ++this.indentLevel; | ||
for (let i = 0, k = members.length; i < k; ++i) { | ||
util.indent(sb, indentLevel); | ||
this.visitNodeAndTerminate(members[i]); | ||
} | ||
util.indent(sb, --this.indentLevel); | ||
sb.push("}"); | ||
} else { | ||
sb.push(" {}"); | ||
visitFunctionCommon(node) { | ||
var sb = this.sb; | ||
this.visitIdentifierExpression(node.name); | ||
var signature = node.signature; | ||
var typeParameters = node.typeParameters; | ||
if (typeParameters) { | ||
let numTypeParameters = typeParameters.length; | ||
if (numTypeParameters) { | ||
sb.push("<"); | ||
this.visitTypeParameter(typeParameters[0]); | ||
for (let i = 1; i < numTypeParameters; ++i) { | ||
sb.push(", "); | ||
this.visitTypeParameter(typeParameters[i]); | ||
} | ||
sb.push(">"); | ||
} | ||
} | ||
if (node.arrowKind == 2) { | ||
let parameters = signature.parameters; | ||
assert(parameters.length == 1); | ||
assert(!signature.explicitThisType); | ||
this.serializeParameter(parameters[0]); | ||
} | ||
else { | ||
sb.push("("); | ||
let parameters = signature.parameters; | ||
let numParameters = parameters.length; | ||
let explicitThisType = signature.explicitThisType; | ||
if (explicitThisType) { | ||
sb.push("this: "); | ||
this.visitTypeNode(explicitThisType); | ||
} | ||
if (numParameters) { | ||
if (explicitThisType) | ||
sb.push(", "); | ||
this.serializeParameter(parameters[0]); | ||
for (let i = 1; i < numParameters; ++i) { | ||
sb.push(", "); | ||
this.serializeParameter(parameters[i]); | ||
} | ||
} | ||
} | ||
var body = node.body; | ||
var returnType = signature.returnType; | ||
if (node.arrowKind) { | ||
if (body) { | ||
if (node.arrowKind == 2) { | ||
assert(isTypeOmitted(returnType)); | ||
} | ||
else { | ||
if (isTypeOmitted(returnType)) { | ||
sb.push(")"); | ||
} | ||
else { | ||
sb.push("): "); | ||
this.visitTypeNode(returnType); | ||
} | ||
} | ||
sb.push(" => "); | ||
this.visitNode(body); | ||
} | ||
else { | ||
assert(!isTypeOmitted(returnType)); | ||
sb.push(" => "); | ||
this.visitTypeNode(returnType); | ||
} | ||
} | ||
else { | ||
if (!isTypeOmitted(returnType) && !node.isAny(524288 | 4096)) { | ||
sb.push("): "); | ||
this.visitTypeNode(returnType); | ||
} | ||
else { | ||
sb.push(")"); | ||
} | ||
if (body) { | ||
sb.push(" "); | ||
this.visitNode(body); | ||
} | ||
} | ||
} | ||
} | ||
visitReturnStatement(node) { | ||
var value = node.value; | ||
if (value) { | ||
this.sb.push("return "); | ||
this.visitNode(value); | ||
} else { | ||
this.sb.push("return"); | ||
visitIfStatement(node) { | ||
var sb = this.sb; | ||
sb.push("if ("); | ||
this.visitNode(node.condition); | ||
sb.push(") "); | ||
var ifTrue = node.ifTrue; | ||
this.visitNode(ifTrue); | ||
if (ifTrue.kind != 30) { | ||
sb.push(";\n"); | ||
} | ||
var ifFalse = node.ifFalse; | ||
if (ifFalse) { | ||
if (ifTrue.kind == 30) { | ||
sb.push(" else "); | ||
} | ||
else { | ||
sb.push("else "); | ||
} | ||
this.visitNode(ifFalse); | ||
} | ||
} | ||
} | ||
visitTrueExpression(node) { | ||
this.sb.push("true"); | ||
} | ||
visitFalseExpression(node) { | ||
this.sb.push("false"); | ||
} | ||
visitNullExpression(node) { | ||
this.sb.push("null"); | ||
} | ||
visitSwitchCase(node) { | ||
var sb = this.sb; | ||
var label = node.label; | ||
if (label) { | ||
sb.push("case "); | ||
this.visitNode(label); | ||
sb.push(":\n"); | ||
} else { | ||
sb.push("default:\n"); | ||
visitImportDeclaration(node) { | ||
var externalName = node.foreignName; | ||
var name = node.name; | ||
this.visitIdentifierExpression(externalName); | ||
if (externalName.text != name.text) { | ||
this.sb.push(" as "); | ||
this.visitIdentifierExpression(name); | ||
} | ||
} | ||
var statements = node.statements; | ||
var numStatements = statements.length; | ||
if (numStatements) { | ||
let indentLevel = ++this.indentLevel; | ||
util.indent(sb, indentLevel); | ||
this.visitNodeAndTerminate(statements[0]); | ||
for (let i = 1; i < numStatements; ++i) { | ||
util.indent(sb, indentLevel); | ||
this.visitNodeAndTerminate(statements[i]); | ||
} | ||
--this.indentLevel; | ||
visitImportStatement(node) { | ||
var sb = this.sb; | ||
sb.push("import "); | ||
var declarations = node.declarations; | ||
var namespaceName = node.namespaceName; | ||
if (declarations) { | ||
let numDeclarations = declarations.length; | ||
if (numDeclarations) { | ||
sb.push("{\n"); | ||
let indentLevel = ++this.indentLevel; | ||
util.indent(sb, indentLevel); | ||
this.visitImportDeclaration(declarations[0]); | ||
for (let i = 1; i < numDeclarations; ++i) { | ||
sb.push(",\n"); | ||
util.indent(sb, indentLevel); | ||
this.visitImportDeclaration(declarations[i]); | ||
} | ||
--this.indentLevel; | ||
sb.push("\n} from "); | ||
} | ||
else { | ||
sb.push("{} from "); | ||
} | ||
} | ||
else if (namespaceName) { | ||
sb.push("* as "); | ||
this.visitIdentifierExpression(namespaceName); | ||
sb.push(" from "); | ||
} | ||
this.visitStringLiteralExpression(node.path); | ||
} | ||
} | ||
visitSwitchStatement(node) { | ||
var sb = this.sb; | ||
sb.push("switch ("); | ||
this.visitNode(node.condition); | ||
sb.push(") {\n"); | ||
var indentLevel = ++this.indentLevel; | ||
var cases = node.cases; | ||
for (let i = 0, k = cases.length; i < k; ++i) { | ||
util.indent(sb, indentLevel); | ||
this.visitSwitchCase(cases[i]); | ||
sb.push("\n"); | ||
visitIndexSignature(node) { | ||
var sb = this.sb; | ||
sb.push("[key: "); | ||
this.visitTypeNode(node.keyType); | ||
sb.push("]: "); | ||
this.visitTypeNode(node.valueType); | ||
} | ||
--this.indentLevel; | ||
sb.push("}"); | ||
} | ||
visitThrowStatement(node) { | ||
this.sb.push("throw "); | ||
this.visitNode(node.value); | ||
} | ||
visitTryStatement(node) { | ||
var sb = this.sb; | ||
sb.push("try {\n"); | ||
var indentLevel = ++this.indentLevel; | ||
var statements = node.bodyStatements; | ||
for (let i = 0, k = statements.length; i < k; ++i) { | ||
util.indent(sb, indentLevel); | ||
this.visitNodeAndTerminate(statements[i]); | ||
visitInterfaceDeclaration(node, isDefault = false) { | ||
var decorators = node.decorators; | ||
if (decorators) { | ||
for (let i = 0, k = decorators.length; i < k; ++i) { | ||
this.serializeDecorator(decorators[i]); | ||
} | ||
} | ||
var sb = this.sb; | ||
if (isDefault) { | ||
sb.push("export default "); | ||
} | ||
else { | ||
this.serializeExternalModifiers(node); | ||
} | ||
sb.push("interface "); | ||
this.visitIdentifierExpression(node.name); | ||
var typeParameters = node.typeParameters; | ||
if (typeParameters != null && typeParameters.length > 0) { | ||
sb.push("<"); | ||
this.visitTypeParameter(typeParameters[0]); | ||
for (let i = 1, k = typeParameters.length; i < k; ++i) { | ||
sb.push(", "); | ||
this.visitTypeParameter(typeParameters[i]); | ||
} | ||
sb.push(">"); | ||
} | ||
var extendsType = node.extendsType; | ||
if (extendsType) { | ||
sb.push(" extends "); | ||
this.visitTypeNode(extendsType); | ||
} | ||
sb.push(" {\n"); | ||
var indentLevel = ++this.indentLevel; | ||
var members = node.members; | ||
for (let i = 0, k = members.length; i < k; ++i) { | ||
util.indent(sb, indentLevel); | ||
this.visitNodeAndTerminate(members[i]); | ||
} | ||
--this.indentLevel; | ||
sb.push("}"); | ||
} | ||
var catchVariable = node.catchVariable; | ||
if (catchVariable) { | ||
util.indent(sb, indentLevel - 1); | ||
sb.push("} catch ("); | ||
this.visitIdentifierExpression(catchVariable); | ||
sb.push(") {\n"); | ||
let catchStatements = node.catchStatements; | ||
if (catchStatements) { | ||
for (let i = 0, k = catchStatements.length; i < k; ++i) { | ||
util.indent(sb, indentLevel); | ||
this.visitNodeAndTerminate(catchStatements[i]); | ||
visitMethodDeclaration(node) { | ||
var decorators = node.decorators; | ||
if (decorators) { | ||
for (let i = 0, k = decorators.length; i < k; ++i) { | ||
this.serializeDecorator(decorators[i]); | ||
} | ||
} | ||
} | ||
this.serializeAccessModifiers(node); | ||
if (node.is(2048)) { | ||
this.sb.push("get "); | ||
} | ||
else if (node.is(4096)) { | ||
this.sb.push("set "); | ||
} | ||
this.visitFunctionCommon(node); | ||
} | ||
var finallyStatements = node.finallyStatements; | ||
if (finallyStatements) { | ||
util.indent(sb, indentLevel - 1); | ||
sb.push("} finally {\n"); | ||
for (let i = 0, k = finallyStatements.length; i < k; ++i) { | ||
util.indent(sb, indentLevel); | ||
this.visitNodeAndTerminate(finallyStatements[i]); | ||
} | ||
visitNamespaceDeclaration(node, isDefault = false) { | ||
var decorators = node.decorators; | ||
if (decorators) { | ||
for (let i = 0, k = decorators.length; i < k; ++i) { | ||
this.serializeDecorator(decorators[i]); | ||
} | ||
} | ||
var sb = this.sb; | ||
if (isDefault) { | ||
sb.push("export default "); | ||
} | ||
else { | ||
this.serializeExternalModifiers(node); | ||
} | ||
sb.push("namespace "); | ||
this.visitIdentifierExpression(node.name); | ||
var members = node.members; | ||
var numMembers = members.length; | ||
if (numMembers) { | ||
sb.push(" {\n"); | ||
let indentLevel = ++this.indentLevel; | ||
for (let i = 0, k = members.length; i < k; ++i) { | ||
util.indent(sb, indentLevel); | ||
this.visitNodeAndTerminate(members[i]); | ||
} | ||
util.indent(sb, --this.indentLevel); | ||
sb.push("}"); | ||
} | ||
else { | ||
sb.push(" {}"); | ||
} | ||
} | ||
util.indent(sb, indentLevel - 1); | ||
sb.push("}"); | ||
} | ||
visitTypeDeclaration(node) { | ||
var decorators = node.decorators; | ||
if (decorators) { | ||
for (let i = 0, k = decorators.length; i < k; ++i) { | ||
this.serializeDecorator(decorators[i]); | ||
} | ||
} | ||
var sb = this.sb; | ||
this.serializeExternalModifiers(node); | ||
sb.push("type "); | ||
this.visitIdentifierExpression(node.name); | ||
var typeParameters = node.typeParameters; | ||
if (typeParameters) { | ||
let numTypeParameters = typeParameters.length; | ||
if (numTypeParameters) { | ||
sb.push("<"); | ||
for (let i = 0; i < numTypeParameters; ++i) { | ||
this.visitTypeParameter(typeParameters[i]); | ||
visitReturnStatement(node) { | ||
var value = node.value; | ||
if (value) { | ||
this.sb.push("return "); | ||
this.visitNode(value); | ||
} | ||
sb.push(">"); | ||
} | ||
else { | ||
this.sb.push("return"); | ||
} | ||
} | ||
sb.push(" = "); | ||
this.visitTypeNode(node.type); | ||
} | ||
visitVariableDeclaration(node) { | ||
this.visitIdentifierExpression(node.name); | ||
var type = node.type; | ||
var sb = this.sb; | ||
if (node.flags & 16384) { | ||
sb.push("!"); | ||
visitTrueExpression(node) { | ||
this.sb.push("true"); | ||
} | ||
if (type) { | ||
sb.push(": "); | ||
this.visitTypeNode(type); | ||
visitFalseExpression(node) { | ||
this.sb.push("false"); | ||
} | ||
var initializer = node.initializer; | ||
if (initializer) { | ||
sb.push(" = "); | ||
this.visitNode(initializer); | ||
visitNullExpression(node) { | ||
this.sb.push("null"); | ||
} | ||
} | ||
visitVariableStatement(node) { | ||
var decorators = node.decorators; | ||
if (decorators) { | ||
for (let i = 0, k = decorators.length; i < k; ++i) { | ||
this.serializeDecorator(decorators[i]); | ||
} | ||
visitSwitchCase(node) { | ||
var sb = this.sb; | ||
var label = node.label; | ||
if (label) { | ||
sb.push("case "); | ||
this.visitNode(label); | ||
sb.push(":\n"); | ||
} | ||
else { | ||
sb.push("default:\n"); | ||
} | ||
var statements = node.statements; | ||
var numStatements = statements.length; | ||
if (numStatements) { | ||
let indentLevel = ++this.indentLevel; | ||
util.indent(sb, indentLevel); | ||
this.visitNodeAndTerminate(statements[0]); | ||
for (let i = 1; i < numStatements; ++i) { | ||
util.indent(sb, indentLevel); | ||
this.visitNodeAndTerminate(statements[i]); | ||
} | ||
--this.indentLevel; | ||
} | ||
} | ||
var sb = this.sb; | ||
var declarations = node.declarations; | ||
var numDeclarations = declarations.length; | ||
var firstDeclaration = declarations[0]; | ||
this.serializeExternalModifiers(firstDeclaration); | ||
sb.push(firstDeclaration.is(8) ? "const " : firstDeclaration.is(16) ? "let " : "var "); | ||
this.visitVariableDeclaration(node.declarations[0]); | ||
for (let i = 1; i < numDeclarations; ++i) { | ||
sb.push(", "); | ||
this.visitVariableDeclaration(node.declarations[i]); | ||
visitSwitchStatement(node) { | ||
var sb = this.sb; | ||
sb.push("switch ("); | ||
this.visitNode(node.condition); | ||
sb.push(") {\n"); | ||
var indentLevel = ++this.indentLevel; | ||
var cases = node.cases; | ||
for (let i = 0, k = cases.length; i < k; ++i) { | ||
util.indent(sb, indentLevel); | ||
this.visitSwitchCase(cases[i]); | ||
sb.push("\n"); | ||
} | ||
--this.indentLevel; | ||
sb.push("}"); | ||
} | ||
} | ||
visitWhileStatement(node) { | ||
var sb = this.sb; | ||
sb.push("while ("); | ||
this.visitNode(node.condition); | ||
var statement = node.body; | ||
if (statement.kind == 34) { | ||
sb.push(")"); | ||
} else { | ||
sb.push(") "); | ||
this.visitNode(node.body); | ||
visitThrowStatement(node) { | ||
this.sb.push("throw "); | ||
this.visitNode(node.value); | ||
} | ||
} | ||
serializeDecorator(node) { | ||
var sb = this.sb; | ||
sb.push("@"); | ||
this.visitNode(node.name); | ||
var args = node.args; | ||
if (args) { | ||
sb.push("("); | ||
let numArgs = args.length; | ||
if (numArgs) { | ||
this.visitNode(args[0]); | ||
for (let i = 1; i < numArgs; ++i) { | ||
sb.push(", "); | ||
this.visitNode(args[i]); | ||
visitTryStatement(node) { | ||
var sb = this.sb; | ||
sb.push("try {\n"); | ||
var indentLevel = ++this.indentLevel; | ||
var statements = node.bodyStatements; | ||
for (let i = 0, k = statements.length; i < k; ++i) { | ||
util.indent(sb, indentLevel); | ||
this.visitNodeAndTerminate(statements[i]); | ||
} | ||
} | ||
sb.push(")\n"); | ||
} else { | ||
sb.push("\n"); | ||
var catchVariable = node.catchVariable; | ||
if (catchVariable) { | ||
util.indent(sb, indentLevel - 1); | ||
sb.push("} catch ("); | ||
this.visitIdentifierExpression(catchVariable); | ||
sb.push(") {\n"); | ||
let catchStatements = node.catchStatements; | ||
if (catchStatements) { | ||
for (let i = 0, k = catchStatements.length; i < k; ++i) { | ||
util.indent(sb, indentLevel); | ||
this.visitNodeAndTerminate(catchStatements[i]); | ||
} | ||
} | ||
} | ||
var finallyStatements = node.finallyStatements; | ||
if (finallyStatements) { | ||
util.indent(sb, indentLevel - 1); | ||
sb.push("} finally {\n"); | ||
for (let i = 0, k = finallyStatements.length; i < k; ++i) { | ||
util.indent(sb, indentLevel); | ||
this.visitNodeAndTerminate(finallyStatements[i]); | ||
} | ||
} | ||
util.indent(sb, indentLevel - 1); | ||
sb.push("}"); | ||
} | ||
util.indent(sb, this.indentLevel); | ||
} | ||
serializeParameter(node) { | ||
var sb = this.sb; | ||
var kind = node.parameterKind; | ||
var implicitFieldDeclaration = node.implicitFieldDeclaration; | ||
if (implicitFieldDeclaration) { | ||
this.serializeAccessModifiers(implicitFieldDeclaration); | ||
visitTypeDeclaration(node) { | ||
var decorators = node.decorators; | ||
if (decorators) { | ||
for (let i = 0, k = decorators.length; i < k; ++i) { | ||
this.serializeDecorator(decorators[i]); | ||
} | ||
} | ||
var sb = this.sb; | ||
this.serializeExternalModifiers(node); | ||
sb.push("type "); | ||
this.visitIdentifierExpression(node.name); | ||
var typeParameters = node.typeParameters; | ||
if (typeParameters) { | ||
let numTypeParameters = typeParameters.length; | ||
if (numTypeParameters) { | ||
sb.push("<"); | ||
for (let i = 0; i < numTypeParameters; ++i) { | ||
this.visitTypeParameter(typeParameters[i]); | ||
} | ||
sb.push(">"); | ||
} | ||
} | ||
sb.push(" = "); | ||
this.visitTypeNode(node.type); | ||
} | ||
if (kind == 2) { | ||
sb.push("..."); | ||
visitVariableDeclaration(node) { | ||
this.visitIdentifierExpression(node.name); | ||
var type = node.type; | ||
var sb = this.sb; | ||
if (node.flags & 16384) { | ||
sb.push("!"); | ||
} | ||
if (type) { | ||
sb.push(": "); | ||
this.visitTypeNode(type); | ||
} | ||
var initializer = node.initializer; | ||
if (initializer) { | ||
sb.push(" = "); | ||
this.visitNode(initializer); | ||
} | ||
} | ||
this.visitIdentifierExpression(node.name); | ||
var type = node.type; | ||
var initializer = node.initializer; | ||
if (type) { | ||
if (kind == 1 && !initializer) sb.push("?"); | ||
if (!isTypeOmitted(type)) { | ||
sb.push(": "); | ||
this.visitTypeNode(type); | ||
} | ||
visitVariableStatement(node) { | ||
var decorators = node.decorators; | ||
if (decorators) { | ||
for (let i = 0, k = decorators.length; i < k; ++i) { | ||
this.serializeDecorator(decorators[i]); | ||
} | ||
} | ||
var sb = this.sb; | ||
var declarations = node.declarations; | ||
var numDeclarations = declarations.length; | ||
var firstDeclaration = declarations[0]; | ||
this.serializeExternalModifiers(firstDeclaration); | ||
sb.push(firstDeclaration.is(8) ? "const " : firstDeclaration.is(16) ? "let " : "var "); | ||
this.visitVariableDeclaration(node.declarations[0]); | ||
for (let i = 1; i < numDeclarations; ++i) { | ||
sb.push(", "); | ||
this.visitVariableDeclaration(node.declarations[i]); | ||
} | ||
} | ||
if (initializer) { | ||
sb.push(" = "); | ||
this.visitNode(initializer); | ||
visitWhileStatement(node) { | ||
var sb = this.sb; | ||
sb.push("while ("); | ||
this.visitNode(node.condition); | ||
var statement = node.body; | ||
if (statement.kind == 34) { | ||
sb.push(")"); | ||
} | ||
else { | ||
sb.push(") "); | ||
this.visitNode(node.body); | ||
} | ||
} | ||
} | ||
serializeExternalModifiers(node) { | ||
var sb = this.sb; | ||
if (node.is(2)) { | ||
sb.push("export "); | ||
} else if (node.is(1)) { | ||
sb.push("import "); | ||
} else if (node.is(4)) { | ||
sb.push("declare "); | ||
serializeDecorator(node) { | ||
var sb = this.sb; | ||
sb.push("@"); | ||
this.visitNode(node.name); | ||
var args = node.args; | ||
if (args) { | ||
sb.push("("); | ||
let numArgs = args.length; | ||
if (numArgs) { | ||
this.visitNode(args[0]); | ||
for (let i = 1; i < numArgs; ++i) { | ||
sb.push(", "); | ||
this.visitNode(args[i]); | ||
} | ||
} | ||
sb.push(")\n"); | ||
} | ||
else { | ||
sb.push("\n"); | ||
} | ||
util.indent(sb, this.indentLevel); | ||
} | ||
} | ||
serializeAccessModifiers(node) { | ||
var sb = this.sb; | ||
if (node.is(256)) { | ||
sb.push("public "); | ||
} else if (node.is(512)) { | ||
sb.push("private "); | ||
} else if (node.is(1024)) { | ||
sb.push("protected "); | ||
serializeParameter(node) { | ||
var sb = this.sb; | ||
var kind = node.parameterKind; | ||
var implicitFieldDeclaration = node.implicitFieldDeclaration; | ||
if (implicitFieldDeclaration) { | ||
this.serializeAccessModifiers(implicitFieldDeclaration); | ||
} | ||
if (kind == 2) { | ||
sb.push("..."); | ||
} | ||
this.visitIdentifierExpression(node.name); | ||
var type = node.type; | ||
var initializer = node.initializer; | ||
if (type) { | ||
if (kind == 1 && !initializer) | ||
sb.push("?"); | ||
if (!isTypeOmitted(type)) { | ||
sb.push(": "); | ||
this.visitTypeNode(type); | ||
} | ||
} | ||
if (initializer) { | ||
sb.push(" = "); | ||
this.visitNode(initializer); | ||
} | ||
} | ||
if (node.is(32)) { | ||
sb.push("static "); | ||
} else if (node.is(128)) { | ||
sb.push("abstract "); | ||
serializeExternalModifiers(node) { | ||
var sb = this.sb; | ||
if (node.is(2)) { | ||
sb.push("export "); | ||
} | ||
else if (node.is(1)) { | ||
sb.push("import "); | ||
} | ||
else if (node.is(4)) { | ||
sb.push("declare "); | ||
} | ||
} | ||
if (node.is(64)) { | ||
sb.push("readonly "); | ||
serializeAccessModifiers(node) { | ||
var sb = this.sb; | ||
if (node.is(256)) { | ||
sb.push("public "); | ||
} | ||
else if (node.is(512)) { | ||
sb.push("private "); | ||
} | ||
else if (node.is(1024)) { | ||
sb.push("protected "); | ||
} | ||
if (node.is(32)) { | ||
sb.push("static "); | ||
} | ||
else if (node.is(128)) { | ||
sb.push("abstract "); | ||
} | ||
if (node.is(64)) { | ||
sb.push("readonly "); | ||
} | ||
} | ||
} | ||
finish() { | ||
var ret = this.sb.join(""); | ||
this.sb = []; | ||
return ret; | ||
} | ||
finish() { | ||
var ret = this.sb.join(""); | ||
this.sb = []; | ||
return ret; | ||
} | ||
} | ||
//# sourceMappingURL=builder.js.map | ||
//# sourceMappingURL=builder.js.map |
@@ -11,564 +11,634 @@ import { IdentifierExpression, Source, StringLiteralExpression, IntegerLiteralExpression, FloatLiteralExpression, NullExpression, TrueExpression, FalseExpression, Node, Tokenizer } from "assemblyscript/dist/assemblyscript.js"; | ||
class JSONTransform extends Visitor { | ||
parser; | ||
schemas = []; | ||
schema; | ||
sources = new Set(); | ||
imports = []; | ||
jsonImport = null; | ||
bsImport = null; | ||
newStmts = { simd: [] }; | ||
visitClassDeclaration(node) { | ||
if (!node.decorators?.length) return; | ||
if ( | ||
!node.decorators.some((decorator) => { | ||
const name = decorator.name.text; | ||
return name === "json" || name === "serializable"; | ||
}) | ||
) | ||
return; | ||
this.schema = new Schema(); | ||
this.schema.node = node; | ||
this.schema.name = node.name.text; | ||
this.schemas.push(this.schema); | ||
if (process.env["JSON_DEBUG"]) console.log("Created schema: " + this.schema.name); | ||
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"))]; | ||
if (node.extendsType) { | ||
const extendsName = node.extendsType?.name.identifier.text; | ||
this.schema.parent = this.schemas.find((v) => v.name == extendsName); | ||
if (!this.schema.parent) { | ||
const internalSearch = getClasses(node.range.source).find((v) => v.name.text == extendsName); | ||
if (internalSearch) { | ||
if (process.env["JSON_DEBUG"]) console.log("Found " + extendsName + " internally"); | ||
this.visitClassDeclaration(internalSearch); | ||
this.visitClassDeclaration(node); | ||
return; | ||
parser; | ||
schemas = []; | ||
schema; | ||
sources = new Set(); | ||
imports = []; | ||
jsonImport = null; | ||
bsImport = null; | ||
newStmts = { simd: [] }; | ||
visitClassDeclaration(node) { | ||
if (!node.decorators?.length) | ||
return; | ||
if (!node.decorators.some((decorator) => { | ||
const name = decorator.name.text; | ||
return name === "json" || name === "serializable"; | ||
})) | ||
return; | ||
this.schema = new Schema(); | ||
this.schema.node = node; | ||
this.schema.name = node.name.text; | ||
this.schemas.push(this.schema); | ||
if (process.env["JSON_DEBUG"]) | ||
console.log("Created schema: " + this.schema.name); | ||
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"))]; | ||
if (node.extendsType) { | ||
const extendsName = node.extendsType?.name.identifier.text; | ||
this.schema.parent = this.schemas.find((v) => v.name == extendsName); | ||
if (!this.schema.parent) { | ||
const internalSearch = getClasses(node.range.source).find((v) => v.name.text == extendsName); | ||
if (internalSearch) { | ||
if (process.env["JSON_DEBUG"]) | ||
console.log("Found " + extendsName + " internally"); | ||
this.visitClassDeclaration(internalSearch); | ||
this.visitClassDeclaration(node); | ||
return; | ||
} | ||
const externalSearch = getImportedClass(extendsName, node.range.source, this.parser); | ||
if (externalSearch) { | ||
if (process.env["JSON_DEBUG"]) | ||
console.log("Found " + extendsName + " externally"); | ||
this.visitClassDeclaration(externalSearch); | ||
this.visitClassDeclaration(node); | ||
return; | ||
} | ||
} | ||
if (this.schema.parent?.members) { | ||
for (let i = this.schema.parent.members.length - 1; i >= 0; i--) { | ||
const replace = this.schema.members.find((v) => v.name == this.schema.parent?.members[i]?.name); | ||
if (!replace) { | ||
members.unshift(this.schema.parent?.members[i].node); | ||
} | ||
} | ||
} | ||
} | ||
const externalSearch = getImportedClass(extendsName, node.range.source, this.parser); | ||
if (externalSearch) { | ||
if (process.env["JSON_DEBUG"]) console.log("Found " + extendsName + " externally"); | ||
this.visitClassDeclaration(externalSearch); | ||
this.visitClassDeclaration(node); | ||
return; | ||
if (!members.length) { | ||
this.generateEmptyMethods(node); | ||
return; | ||
} | ||
} | ||
if (this.schema.parent?.members) { | ||
for (let i = this.schema.parent.members.length - 1; i >= 0; i--) { | ||
const replace = this.schema.members.find((v) => v.name == this.schema.parent?.members[i]?.name); | ||
if (!replace) { | ||
members.unshift(this.schema.parent?.members[i].node); | ||
} | ||
this.addRequiredImports(node); | ||
for (const member of members) { | ||
if (!member.type) | ||
throwError("Fields must be strongly typed", node.range); | ||
const type = toString(member.type); | ||
const name = member.name; | ||
const value = member.initializer ? toString(member.initializer) : null; | ||
if (type.startsWith("(") && type.includes("=>")) | ||
continue; | ||
const mem = new Property(); | ||
mem.name = name.text; | ||
mem.type = type; | ||
mem.value = value; | ||
mem.node = member; | ||
mem.byteSize = sizeof(mem.type); | ||
this.schema.byteSize += mem.byteSize; | ||
if (type.includes("JSON.Raw")) | ||
mem.flags.set(PropertyFlags.Raw, null); | ||
if (member.decorators) { | ||
for (const decorator of member.decorators) { | ||
const decoratorName = decorator.name.text.toLowerCase().trim(); | ||
switch (decoratorName) { | ||
case "alias": { | ||
const args = getArgs(decorator.args); | ||
if (!args.length) | ||
throwError("@alias must have an argument of type string or number", member.range); | ||
mem.alias = args[0]; | ||
break; | ||
} | ||
case "omitif": { | ||
let arg = decorator.args[0]; | ||
if (!decorator.args?.length) | ||
throwError("@omitif must have an argument or callback that resolves to type bool", member.range); | ||
mem.flags.set(PropertyFlags.OmitIf, arg); | ||
this.schema.static = false; | ||
break; | ||
} | ||
case "omitnull": { | ||
if (isPrimitive(type)) { | ||
throwError("@omitnull cannot be used on primitive types!", member.range); | ||
} | ||
else if (!member.type.isNullable) { | ||
throwError("@omitnull cannot be used on non-nullable types!", member.range); | ||
} | ||
mem.flags.set(PropertyFlags.OmitNull, null); | ||
this.schema.static = false; | ||
break; | ||
} | ||
} | ||
} | ||
} | ||
this.schema.members.push(mem); | ||
} | ||
} | ||
} | ||
if (!members.length) { | ||
this.generateEmptyMethods(node); | ||
return; | ||
} | ||
this.addRequiredImports(node); | ||
for (const member of members) { | ||
if (!member.type) throwError("Fields must be strongly typed", node.range); | ||
const type = toString(member.type); | ||
const name = member.name; | ||
const value = member.initializer ? toString(member.initializer) : null; | ||
if (type.startsWith("(") && type.includes("=>")) continue; | ||
const mem = new Property(); | ||
mem.name = name.text; | ||
mem.type = type; | ||
mem.value = value; | ||
mem.node = member; | ||
mem.byteSize = sizeof(mem.type); | ||
this.schema.byteSize += mem.byteSize; | ||
if (type.includes("JSON.Raw")) mem.flags.set(PropertyFlags.Raw, null); | ||
if (member.decorators) { | ||
for (const decorator of member.decorators) { | ||
const decoratorName = decorator.name.text.toLowerCase().trim(); | ||
switch (decoratorName) { | ||
case "alias": { | ||
const args = getArgs(decorator.args); | ||
if (!args.length) throwError("@alias must have an argument of type string or number", member.range); | ||
mem.alias = args[0]; | ||
break; | ||
if (!this.schema.static) | ||
this.schema.members = sortMembers(this.schema.members); | ||
let SERIALIZE = "__SERIALIZE(ptr: usize): void {\n"; | ||
let INITIALIZE = "@inline __INITIALIZE(): this {\n"; | ||
let DESERIALIZE = "__DESERIALIZE(keyStart: usize, keyEnd: usize, valStart: usize, valEnd: usize, ptr: usize): void {\n switch (<u32>keyEnd - <u32>keyStart) {\n"; | ||
indent = " "; | ||
if (this.schema.static == false) { | ||
if (this.schema.members.some((v) => v.flags.has(PropertyFlags.OmitNull))) { | ||
SERIALIZE += indent + "let block: usize = 0;\n"; | ||
} | ||
case "omitif": { | ||
let arg = decorator.args[0]; | ||
if (!decorator.args?.length) throwError("@omitif must have an argument or callback that resolves to type bool", member.range); | ||
mem.flags.set(PropertyFlags.OmitIf, arg); | ||
this.schema.static = false; | ||
break; | ||
this.schema.byteSize += 2; | ||
SERIALIZE += indent + "store<u16>(bs.offset, 123, 0); // {\n"; | ||
SERIALIZE += indent + "bs.offset += 2;\n"; | ||
} | ||
for (const member of this.schema.members) { | ||
const nonNullType = member.type.replace(" | null", ""); | ||
if (!isPrimitive(nonNullType)) { | ||
const schema = this.schemas.find((v) => v.name == nonNullType); | ||
if (schema && !this.schema.deps.includes(schema)) { | ||
this.schema.deps.push(schema); | ||
this.schema.byteSize += schema.byteSize; | ||
} | ||
} | ||
case "omitnull": { | ||
if (isPrimitive(type)) { | ||
throwError("@omitnull cannot be used on primitive types!", member.range); | ||
} else if (!member.type.isNullable) { | ||
throwError("@omitnull cannot be used on non-nullable types!", member.range); | ||
} | ||
mem.flags.set(PropertyFlags.OmitNull, null); | ||
this.schema.static = false; | ||
break; | ||
} | ||
let isPure = this.schema.static; | ||
let isRegular = isPure; | ||
let isFirst = true; | ||
for (let i = 0; i < this.schema.members.length; i++) { | ||
const member = this.schema.members[i]; | ||
const aliasName = JSON.stringify(member.alias || member.name); | ||
const realName = member.name; | ||
const isLast = i == this.schema.members.length - 1; | ||
const nonNullType = member.type.replace(" | null", ""); | ||
if (member.value) { | ||
INITIALIZE += ` this.${member.name} = ${member.value};\n`; | ||
} | ||
} | ||
else if (this.schemas.find((v) => nonNullType == v.name)) { | ||
INITIALIZE += ` this.${member.name} = changetype<nonnull<${member.type}>>(__new(offsetof<nonnull<${member.type}>>(), idof<nonnull<${member.type}>>())).__INITIALIZE();\n`; | ||
} | ||
else if (member.type.startsWith("Array<") || member.type.startsWith("Map<")) { | ||
INITIALIZE += ` this.${member.name} = [];\n`; | ||
} | ||
else if (member.type == "string" || member.type == "String" || member.type == "JSON.Raw") { | ||
INITIALIZE += ` this.${member.name} = "";\n`; | ||
} | ||
if (!isRegular && !member.flags.has(PropertyFlags.OmitIf) && !member.flags.has(PropertyFlags.OmitNull)) | ||
isRegular = true; | ||
if (isRegular && isPure) { | ||
const keyPart = (isFirst ? "{" : ",") + aliasName + ":"; | ||
this.schema.byteSize += keyPart.length << 1; | ||
SERIALIZE += this.getStores(keyPart) | ||
.map((v) => indent + v + "\n") | ||
.join(""); | ||
SERIALIZE += indent + `JSON.__serialize<${member.type}>(load<${member.type}>(ptr, offsetof<this>(${JSON.stringify(realName)})));\n`; | ||
if (isFirst) | ||
isFirst = false; | ||
} | ||
else if (isRegular && !isPure) { | ||
const keyPart = (isFirst ? "" : ",") + aliasName + ":"; | ||
this.schema.byteSize += keyPart.length << 1; | ||
SERIALIZE += this.getStores(keyPart) | ||
.map((v) => indent + v + "\n") | ||
.join(""); | ||
SERIALIZE += indent + `JSON.__serialize<${member.type}>(load<${member.type}>(ptr, offsetof<this>(${JSON.stringify(realName)})));\n`; | ||
if (isFirst) | ||
isFirst = false; | ||
} | ||
else { | ||
if (member.flags.has(PropertyFlags.OmitNull)) { | ||
SERIALIZE += indent + `if ((block = load<usize>(ptr, offsetof<this>(${JSON.stringify(realName)}))) !== 0) {\n`; | ||
indentInc(); | ||
const keyPart = aliasName + ":"; | ||
this.schema.byteSize += keyPart.length << 1; | ||
SERIALIZE += this.getStores(keyPart) | ||
.map((v) => indent + v + "\n") | ||
.join(""); | ||
SERIALIZE += indent + `JSON.__serialize<${member.type}>(load<${member.type}>(ptr, offsetof<this>(${JSON.stringify(realName)})));\n`; | ||
if (!isLast) { | ||
this.schema.byteSize += 2; | ||
SERIALIZE += indent + `store<u16>(bs.offset, 44, 0); // ,\n`; | ||
SERIALIZE += indent + `bs.offset += 2;\n`; | ||
} | ||
indentDec(); | ||
this.schema.byteSize += 2; | ||
SERIALIZE += indent + `}\n`; | ||
} | ||
else if (member.flags.has(PropertyFlags.OmitIf)) { | ||
if (member.flags.get(PropertyFlags.OmitIf).kind == 14) { | ||
const arg = member.flags.get(PropertyFlags.OmitIf); | ||
arg.declaration.signature.parameters[0].type = Node.createNamedType(Node.createSimpleTypeName("this", node.range), null, false, node.range); | ||
arg.declaration.signature.returnType.name = Node.createSimpleTypeName("boolean", arg.declaration.signature.returnType.name.range); | ||
SERIALIZE += indent + `if (!(${toString(member.flags.get(PropertyFlags.OmitIf))})(this)) {\n`; | ||
} | ||
else { | ||
SERIALIZE += indent + `if (${toString(member.flags.get(PropertyFlags.OmitIf))}) {\n`; | ||
} | ||
indentInc(); | ||
SERIALIZE += this.getStores(aliasName + ":") | ||
.map((v) => indent + v + "\n") | ||
.join(""); | ||
SERIALIZE += indent + `JSON.__serialize<${member.type}>(load<${member.type}>(ptr, offsetof<this>(${JSON.stringify(realName)})));\n`; | ||
if (!isLast) { | ||
this.schema.byteSize += 2; | ||
SERIALIZE += indent + `store<u16>(bs.offset, 44, 0); // ,\n`; | ||
SERIALIZE += indent + `bs.offset += 2;\n`; | ||
} | ||
indentDec(); | ||
SERIALIZE += indent + `}\n`; | ||
} | ||
} | ||
} | ||
} | ||
this.schema.members.push(mem); | ||
} | ||
if (!this.schema.static) this.schema.members = sortMembers(this.schema.members); | ||
let SERIALIZE = "__SERIALIZE(ptr: usize): void {\n"; | ||
let INITIALIZE = "@inline __INITIALIZE(): this {\n"; | ||
let DESERIALIZE = "__DESERIALIZE(keyStart: usize, keyEnd: usize, valStart: usize, valEnd: usize, ptr: usize): void {\n switch (<u32>keyEnd - <u32>keyStart) {\n"; | ||
let ALLOCATE = "@inline __ALLOCATE(): void {\n"; | ||
indent = " "; | ||
if (this.schema.static == false) { | ||
if (this.schema.members.some((v) => v.flags.has(PropertyFlags.OmitNull))) { | ||
SERIALIZE += indent + "let block: usize = 0;\n"; | ||
} | ||
this.schema.byteSize += 2; | ||
SERIALIZE += indent + "store<u16>(bs.offset, 123, 0); // {\n"; | ||
SERIALIZE += indent + "bs.offset += 2;\n"; | ||
} | ||
for (const member of this.schema.members) { | ||
const nonNullType = member.type.replace(" | null", ""); | ||
if (!isPrimitive(nonNullType)) { | ||
const schema = this.schemas.find((v) => v.name == nonNullType); | ||
if (schema && !this.schema.deps.includes(schema)) { | ||
this.schema.deps.push(schema); | ||
this.schema.byteSize += schema.byteSize; | ||
let sortedMembers = []; | ||
let len = -1; | ||
this.schema.members | ||
.slice() | ||
.sort((a, b) => (a.alias?.length || a.name.length) - (b.alias?.length || b.name.length)) | ||
.forEach((member) => { | ||
const _nameLength = member.alias?.length || member.name.length; | ||
if (_nameLength === len) { | ||
sortedMembers[sortedMembers.length - 1].push(member); | ||
} | ||
else { | ||
sortedMembers.push([member]); | ||
len = _nameLength; | ||
} | ||
}); | ||
sortedMembers = sortedMembers.sort((a, b) => b.length - a.length); | ||
indentInc(); | ||
for (const memberGroup of sortedMembers) { | ||
const memberLen = (memberGroup[0].alias || memberGroup[0].name).length << 1; | ||
DESERIALIZE += `${indent}case ${memberLen}: {\n`; | ||
indentInc(); | ||
if (memberLen == 2) | ||
DESERIALIZE += `${indent}switch (load<u16>(keyStart)) {\n`; | ||
else if (memberLen == 4) | ||
DESERIALIZE += `${indent}switch (load<u32>(keyStart)) {\n`; | ||
else if (memberLen == 6) | ||
DESERIALIZE += `${indent}let code = load<u64>(keyStart) & 0x0000FFFFFFFFFFFF;\n`; | ||
else if (memberLen == 6) | ||
DESERIALIZE += `${indent}let code = load<u64>(keyStart);\n`; | ||
else | ||
DESERIALIZE += toMemCDecl(memberLen, indent); | ||
for (let i = 0; i < memberGroup.length; i++) { | ||
const member = memberGroup[i]; | ||
const memberName = member.alias || member.name; | ||
const dst = this.schemas.find(v => v.name == member.type) ? "ptr + offsetof<this>(\"" + member.name + "\") + 12" : "0"; | ||
if (memberLen == 2) { | ||
DESERIALIZE += `${indent} case ${memberName.charCodeAt(0)}: { // ${memberName}\n`; | ||
DESERIALIZE += `${indent} store<${member.type}>(ptr, JSON.__deserialize<${member.type}>(valStart, valEnd, ${dst}), offsetof<this>(${JSON.stringify(member.name)}));\n`; | ||
DESERIALIZE += `${indent} return;\n`; | ||
DESERIALIZE += `${indent} }\n`; | ||
} | ||
else if (memberLen == 4) { | ||
DESERIALIZE += `${indent} case ${toU32(memberName)}: { // ${memberName}\n`; | ||
DESERIALIZE += `${indent} store<${member.type}>(ptr, JSON.__deserialize<${member.type}>(valStart, valEnd, ${dst}), offsetof<this>(${JSON.stringify(member.name)}));\n`; | ||
DESERIALIZE += `${indent} return;\n`; | ||
DESERIALIZE += `${indent} }\n`; | ||
} | ||
else if (memberLen == 6) { | ||
DESERIALIZE += i == 0 ? indent : ""; | ||
DESERIALIZE += `if (code == ${toU48(memberName)}) { // ${memberName}\n`; | ||
DESERIALIZE += `${indent} store<${member.type}>(ptr, JSON.__deserialize<${member.type}>(valStart, valEnd, ${dst}), offsetof<this>(${JSON.stringify(member.name)}));\n`; | ||
DESERIALIZE += `${indent} return;\n`; | ||
DESERIALIZE += `${indent}}${i < memberGroup.length - 1 ? " else " : "\n"}`; | ||
} | ||
else if (memberLen == 8) { | ||
DESERIALIZE += i == 0 ? indent : ""; | ||
DESERIALIZE += `if (code == ${toU64(memberName)}) { // ${memberName}\n`; | ||
DESERIALIZE += `${indent} store<${member.type}>(ptr, JSON.__deserialize<${member.type}>(valStart, valEnd, ${dst}), offsetof<this>(${JSON.stringify(member.name)}));\n`; | ||
DESERIALIZE += `${indent} return;\n`; | ||
DESERIALIZE += `${indent}}${i < memberGroup.length - 1 ? " else " : "\n"}`; | ||
} | ||
else { | ||
DESERIALIZE += i == 0 ? indent : ""; | ||
DESERIALIZE += `if (${toMemCCheck(memberName)}) { // ${memberName}\n`; | ||
DESERIALIZE += `${indent} store<${member.type}>(ptr, JSON.__deserialize<${member.type}>(valStart, valEnd, ${dst}), offsetof<this>(${JSON.stringify(member.name)}));\n`; | ||
DESERIALIZE += `${indent} return;\n`; | ||
DESERIALIZE += `${indent}}${i < memberGroup.length - 1 ? " else " : "\n"}`; | ||
} | ||
} | ||
if (memberLen < 6) { | ||
DESERIALIZE += `${indent}}\n`; | ||
} | ||
indentDec(); | ||
DESERIALIZE += `${indent} return;\n`; | ||
DESERIALIZE += `${indent}}\n`; | ||
} | ||
} | ||
} | ||
let isPure = this.schema.static; | ||
let isRegular = isPure; | ||
let isFirst = true; | ||
for (let i = 0; i < this.schema.members.length; i++) { | ||
const member = this.schema.members[i]; | ||
const aliasName = JSON.stringify(member.alias || member.name); | ||
const realName = member.name; | ||
const isLast = i == this.schema.members.length - 1; | ||
const nonNullType = member.type.replace(" | null", ""); | ||
if (member.value) { | ||
INITIALIZE += ` this.${member.name} = ${member.value};\n`; | ||
} else if (this.schemas.find((v) => nonNullType == v.name)) { | ||
INITIALIZE += ` this.${member.name} = changetype<nonnull<${member.type}>>(__new(offsetof<nonnull<${member.type}>>(), idof<nonnull<${member.type}>>())).__INITIALIZE();\n`; | ||
} else if (member.type.startsWith("Array<") || member.type.startsWith("Map<")) { | ||
INITIALIZE += ` this.${member.name} = [];\n`; | ||
} else if (member.type == "string" || member.type == "String" || member.type == "JSON.Raw") { | ||
INITIALIZE += ` this.${member.name} = "";\n`; | ||
} | ||
if (!isRegular && !member.flags.has(PropertyFlags.OmitIf) && !member.flags.has(PropertyFlags.OmitNull)) isRegular = true; | ||
if (isRegular && isPure) { | ||
const keyPart = (isFirst ? "{" : ",") + aliasName + ":"; | ||
this.schema.byteSize += keyPart.length << 1; | ||
SERIALIZE += this.getStores(keyPart) | ||
.map((v) => indent + v + "\n") | ||
.join(""); | ||
SERIALIZE += indent + `JSON.__serialize<${member.type}>(load<${member.type}>(ptr, offsetof<this>(${JSON.stringify(realName)})));\n`; | ||
if (isFirst) isFirst = false; | ||
} else if (isRegular && !isPure) { | ||
const keyPart = (isFirst ? "" : ",") + aliasName + ":"; | ||
this.schema.byteSize += keyPart.length << 1; | ||
SERIALIZE += this.getStores(keyPart) | ||
.map((v) => indent + v + "\n") | ||
.join(""); | ||
SERIALIZE += indent + `JSON.__serialize<${member.type}>(load<${member.type}>(ptr, offsetof<this>(${JSON.stringify(realName)})));\n`; | ||
if (isFirst) isFirst = false; | ||
} else { | ||
if (member.flags.has(PropertyFlags.OmitNull)) { | ||
SERIALIZE += indent + `if ((block = load<usize>(ptr, offsetof<this>(${JSON.stringify(realName)}))) !== 0) {\n`; | ||
indentInc(); | ||
const keyPart = aliasName + ":"; | ||
this.schema.byteSize += keyPart.length << 1; | ||
SERIALIZE += this.getStores(keyPart) | ||
.map((v) => indent + v + "\n") | ||
.join(""); | ||
SERIALIZE += indent + `JSON.__serialize<${member.type}>(load<${member.type}>(ptr, offsetof<this>(${JSON.stringify(realName)})));\n`; | ||
if (!isLast) { | ||
this.schema.byteSize += 2; | ||
SERIALIZE += indent + `store<u16>(bs.offset, 44, 0); // ,\n`; | ||
SERIALIZE += indent + `bs.offset += 2;\n`; | ||
} | ||
indentDec(); | ||
this.schema.byteSize += 2; | ||
SERIALIZE += indent + `}\n`; | ||
} else if (member.flags.has(PropertyFlags.OmitIf)) { | ||
if (member.flags.get(PropertyFlags.OmitIf).kind == 14) { | ||
const arg = member.flags.get(PropertyFlags.OmitIf); | ||
arg.declaration.signature.returnType.name = Node.createSimpleTypeName("boolean", arg.declaration.signature.returnType.name.range); | ||
SERIALIZE += indent + `if (!(${toString(member.flags.get(PropertyFlags.OmitIf))})(this)) {\n`; | ||
} else { | ||
SERIALIZE += indent + `if (${toString(member.flags.get(PropertyFlags.OmitIf))}) {\n`; | ||
} | ||
indentInc(); | ||
SERIALIZE += this.getStores(aliasName + ":") | ||
.map((v) => indent + v + "\n") | ||
.join(""); | ||
SERIALIZE += indent + `JSON.__serialize<${member.type}>(load<${member.type}>(ptr, offsetof<this>(${JSON.stringify(realName)})));\n`; | ||
if (!isLast) { | ||
this.schema.byteSize += 2; | ||
SERIALIZE += indent + `store<u16>(bs.offset, 44, 0); // ,\n`; | ||
SERIALIZE += indent + `bs.offset += 2;\n`; | ||
} | ||
indentDec(); | ||
SERIALIZE += indent + `}\n`; | ||
indentDec(); | ||
DESERIALIZE += `${indent}}\n`; | ||
indentDec(); | ||
DESERIALIZE += `${indent}}\n`; | ||
indent = " "; | ||
this.schema.byteSize += 2; | ||
SERIALIZE += indent + "store<u16>(bs.offset, 125, 0); // }\n"; | ||
SERIALIZE += indent + "bs.offset += 2;\n"; | ||
SERIALIZE += "}"; | ||
SERIALIZE = SERIALIZE.slice(0, 32) + indent + "bs.proposeSize(" + this.schema.byteSize + ");\n" + SERIALIZE.slice(32); | ||
INITIALIZE += " return this;\n"; | ||
INITIALIZE += "}"; | ||
if (process.env["JSON_DEBUG"]) { | ||
console.log(SERIALIZE); | ||
console.log(INITIALIZE); | ||
console.log(DESERIALIZE); | ||
} | ||
} | ||
const SERIALIZE_METHOD = SimpleParser.parseClassMember(SERIALIZE, node); | ||
const INITIALIZE_METHOD = SimpleParser.parseClassMember(INITIALIZE, node); | ||
const DESERIALIZE_METHOD = SimpleParser.parseClassMember(DESERIALIZE, node); | ||
if (!node.members.find((v) => v.name.text == "__SERIALIZE")) | ||
node.members.push(SERIALIZE_METHOD); | ||
if (!node.members.find((v) => v.name.text == "__INITIALIZE")) | ||
node.members.push(INITIALIZE_METHOD); | ||
if (!node.members.find((v) => v.name.text == "__DESERIALIZE")) | ||
node.members.push(DESERIALIZE_METHOD); | ||
super.visitClassDeclaration(node); | ||
} | ||
let sortedMembers = []; | ||
let len = -1; | ||
this.schema.members | ||
.slice() | ||
.sort((a, b) => (a.alias?.length || a.name.length) - (b.alias?.length || b.name.length)) | ||
.forEach((member) => { | ||
const _nameLength = member.alias?.length || member.name.length; | ||
if (_nameLength === len) { | ||
sortedMembers[sortedMembers.length - 1].push(member); | ||
} else { | ||
sortedMembers.push([member]); | ||
len = _nameLength; | ||
generateEmptyMethods(node) { | ||
let SERIALIZE_RAW_EMPTY = '@inline __SERIALIZE(ptr: usize = changetype<usize>(this)): string {\n return "{}";\n}'; | ||
let SERIALIZE_BS_EMPTY = "@inline __SERIALIZE(ptr: usize: bool): void {\n bs.proposeSize(4);\n store<u32>(bs.offset, 8192123);\n bs.offset += 4;\n}"; | ||
let INITIALIZE_EMPTY = "@inline __INITIALIZE(): this {\n return this;\n}"; | ||
let DESERIALIZE_EMPTY = "@inline __DESERIALIZE(keyStart: usize, keyEnd: usize, valStart: usize, valEnd: usize, ptr: usize): void {\n return false;\n}"; | ||
if (process.env["JSON_DEBUG"]) { | ||
console.log(SERIALIZE_RAW_EMPTY); | ||
console.log(SERIALIZE_BS_EMPTY); | ||
console.log(INITIALIZE_EMPTY); | ||
console.log(DESERIALIZE_EMPTY); | ||
} | ||
}); | ||
sortedMembers = sortedMembers.sort((a, b) => b.length - a.length); | ||
indentInc(); | ||
for (const memberGroup of sortedMembers) { | ||
const memberLen = (memberGroup[0].alias || memberGroup[0].name).length << 1; | ||
DESERIALIZE += `${indent}case ${memberLen}: {\n`; | ||
indentInc(); | ||
if (memberLen == 2) DESERIALIZE += `${indent}switch (load<u16>(keyStart)) {\n`; | ||
else if (memberLen == 4) DESERIALIZE += `${indent}switch (load<u32>(keyStart)) {\n`; | ||
else if (memberLen == 6) DESERIALIZE += `${indent}let code = (<u64>load<u32>(keyStart) << 16) | <u64>load<u16>(keyStart, 4);\n`; | ||
else DESERIALIZE += toMemCDecl(memberLen, indent); | ||
for (let i = 0; i < memberGroup.length; i++) { | ||
const member = memberGroup[i]; | ||
const memberName = member.alias || member.name; | ||
if (memberLen == 2) { | ||
DESERIALIZE += `${indent} case ${memberName.charCodeAt(0)}: { // ${memberName}\n`; | ||
DESERIALIZE += `${indent} store<${member.type}>(ptr, JSON.__deserialize<${member.type}>(valStart, valEnd), offsetof<this>(${JSON.stringify(member.name)}));\n`; | ||
DESERIALIZE += `${indent} return;\n`; | ||
DESERIALIZE += `${indent} }\n`; | ||
} else if (memberLen == 4) { | ||
DESERIALIZE += `${indent} case ${toU32(memberName)}: { // ${memberName}\n`; | ||
DESERIALIZE += `${indent} store<${member.type}>(ptr, JSON.__deserialize<${member.type}>(valStart, valEnd), offsetof<this>(${JSON.stringify(member.name)}));\n`; | ||
DESERIALIZE += `${indent} return;\n`; | ||
DESERIALIZE += `${indent} }\n`; | ||
} else if (memberLen == 6) { | ||
DESERIALIZE += i == 0 ? indent : ""; | ||
DESERIALIZE += `if (code == ${toU48(memberName)}) { // ${memberName}\n`; | ||
DESERIALIZE += `${indent} store<${member.type}>(ptr, JSON.__deserialize<${member.type}>(valStart, valEnd), offsetof<this>(${JSON.stringify(member.name)}));\n`; | ||
DESERIALIZE += `${indent} return;\n`; | ||
DESERIALIZE += `${indent}}${i < memberGroup.length - 1 ? " else " : "\n"}`; | ||
} else { | ||
DESERIALIZE += i == 0 ? indent : ""; | ||
DESERIALIZE += `if (${toMemCCheck(memberName)}) { // ${memberName}\n`; | ||
DESERIALIZE += `${indent} store<${member.type}>(ptr, JSON.__deserialize<${member.type}>(valStart, valEnd), offsetof<this>(${JSON.stringify(member.name)}));\n`; | ||
DESERIALIZE += `${indent} return;\n`; | ||
DESERIALIZE += `${indent}}${i < memberGroup.length - 1 ? " else " : "\n"}`; | ||
} | ||
} | ||
if (memberLen < 6) { | ||
DESERIALIZE += `${indent}}\n`; | ||
} | ||
indentDec(); | ||
DESERIALIZE += `${indent} return;\n`; | ||
DESERIALIZE += `${indent}}\n`; | ||
const SERIALIZE_RAW_METHOD_EMPTY = SimpleParser.parseClassMember(SERIALIZE_RAW_EMPTY, node); | ||
const SERIALIZE_BS_METHOD_EMPTY = SimpleParser.parseClassMember(SERIALIZE_BS_EMPTY, node); | ||
const INITIALIZE_METHOD_EMPTY = SimpleParser.parseClassMember(INITIALIZE_EMPTY, node); | ||
const DESERIALIZE_METHOD_EMPTY = SimpleParser.parseClassMember(DESERIALIZE_EMPTY, node); | ||
if (!node.members.find((v) => v.name.text == "__SERIALIZE")) | ||
node.members.push(SERIALIZE_RAW_METHOD_EMPTY); | ||
if (!node.members.find((v) => v.name.text == "__SERIALIZE")) | ||
node.members.push(SERIALIZE_BS_METHOD_EMPTY); | ||
if (!node.members.find((v) => v.name.text == "__INITIALIZE")) | ||
node.members.push(INITIALIZE_METHOD_EMPTY); | ||
if (!node.members.find((v) => v.name.text == "__DESERIALIZE")) | ||
node.members.push(DESERIALIZE_METHOD_EMPTY); | ||
} | ||
indentDec(); | ||
DESERIALIZE += `${indent}}\n`; | ||
indentDec(); | ||
DESERIALIZE += `${indent}}\n`; | ||
indent = " "; | ||
this.schema.byteSize += 2; | ||
SERIALIZE += indent + "store<u16>(bs.offset, 125, 0); // }\n"; | ||
SERIALIZE += indent + "bs.offset += 2;\n"; | ||
SERIALIZE += "}"; | ||
ALLOCATE += indent + "bs.proposeSize(" + this.schema.byteSize + ");\n"; | ||
ALLOCATE += "}"; | ||
INITIALIZE += " return this;\n"; | ||
INITIALIZE += "}"; | ||
if (process.env["JSON_DEBUG"]) { | ||
console.log(SERIALIZE); | ||
console.log(INITIALIZE); | ||
console.log(DESERIALIZE); | ||
console.log(ALLOCATE); | ||
visitImportStatement(node) { | ||
super.visitImportStatement(node); | ||
const source = this.parser.sources.find((src) => src.internalPath == node.internalPath); | ||
if (!source) | ||
return; | ||
if (source.statements.some((stmt) => stmt.kind === 59 && stmt.name.text === "JSON")) | ||
this.imports.push(node); | ||
} | ||
const SERIALIZE_METHOD = SimpleParser.parseClassMember(SERIALIZE, node); | ||
const INITIALIZE_METHOD = SimpleParser.parseClassMember(INITIALIZE, node); | ||
const DESERIALIZE_METHOD = SimpleParser.parseClassMember(DESERIALIZE, node); | ||
const ALLOCATE_METHOD = SimpleParser.parseClassMember(ALLOCATE, node); | ||
if (!node.members.find((v) => v.name.text == "__SERIALIZE")) node.members.push(SERIALIZE_METHOD); | ||
if (!node.members.find((v) => v.name.text == "__INITIALIZE")) node.members.push(INITIALIZE_METHOD); | ||
if (!node.members.find((v) => v.name.text == "__DESERIALIZE")) node.members.push(DESERIALIZE_METHOD); | ||
if (!node.members.find((v) => v.name.text == "__ALLOCATE")) node.members.push(ALLOCATE_METHOD); | ||
super.visitClassDeclaration(node); | ||
} | ||
generateEmptyMethods(node) { | ||
let SERIALIZE_RAW_EMPTY = '@inline __SERIALIZE(ptr: usize = changetype<usize>(this)): string {\n return "{}";\n}'; | ||
let SERIALIZE_BS_EMPTY = "@inline __SERIALIZE(ptr: usize: bool): void {\n store<u32>(bs.offset, 8192123);\n bs.offset += 4;\n}"; | ||
let INITIALIZE_EMPTY = "@inline __INITIALIZE(): this {\n return this;\n}"; | ||
let DESERIALIZE_EMPTY = "@inline __DESERIALIZE(keyStart: usize, keyEnd: usize, valStart: usize, valEnd: usize, ptr: usize): void {\n return false;\n}"; | ||
let ALLOCATE_EMPTY = "@inline __ALLOCATE(): void {\n bs.ensureSize(4);\n}"; | ||
if (process.env["JSON_DEBUG"]) { | ||
console.log(SERIALIZE_RAW_EMPTY); | ||
console.log(SERIALIZE_BS_EMPTY); | ||
console.log(INITIALIZE_EMPTY); | ||
console.log(DESERIALIZE_EMPTY); | ||
console.log(ALLOCATE_EMPTY); | ||
visitSource(node) { | ||
this.imports = []; | ||
super.visitSource(node); | ||
} | ||
const SERIALIZE_RAW_METHOD_EMPTY = SimpleParser.parseClassMember(SERIALIZE_RAW_EMPTY, node); | ||
const SERIALIZE_BS_METHOD_EMPTY = SimpleParser.parseClassMember(SERIALIZE_BS_EMPTY, node); | ||
const INITIALIZE_METHOD_EMPTY = SimpleParser.parseClassMember(INITIALIZE_EMPTY, node); | ||
const DESERIALIZE_METHOD_EMPTY = SimpleParser.parseClassMember(DESERIALIZE_EMPTY, node); | ||
const ALLOCATE_METHOD_EMPTY = SimpleParser.parseClassMember(ALLOCATE_EMPTY, node); | ||
if (!node.members.find((v) => v.name.text == "__SERIALIZE")) node.members.push(SERIALIZE_RAW_METHOD_EMPTY); | ||
if (!node.members.find((v) => v.name.text == "__SERIALIZE")) node.members.push(SERIALIZE_BS_METHOD_EMPTY); | ||
if (!node.members.find((v) => v.name.text == "__INITIALIZE")) node.members.push(INITIALIZE_METHOD_EMPTY); | ||
if (!node.members.find((v) => v.name.text == "__DESERIALIZE")) node.members.push(DESERIALIZE_METHOD_EMPTY); | ||
if (!node.members.find((v) => v.name.text == "__ALLOCATE")) node.members.push(ALLOCATE_METHOD_EMPTY); | ||
} | ||
visitImportStatement(node) { | ||
super.visitImportStatement(node); | ||
const source = this.parser.sources.find((src) => src.internalPath == node.internalPath); | ||
if (!source) return; | ||
if (source.statements.some((stmt) => stmt.kind === 59 && stmt.name.text === "JSON")) this.imports.push(node); | ||
} | ||
visitSource(node) { | ||
this.imports = []; | ||
super.visitSource(node); | ||
} | ||
addRequiredImports(node) { | ||
if (!this.imports.find((i) => i.declarations.find((d) => d.foreignName.text == "bs"))) { | ||
const __filename = fileURLToPath(import.meta.url); | ||
const __dirname = path.dirname(__filename); | ||
let relativePath = path.relative(path.dirname(node.range.source.normalizedPath), path.resolve(__dirname, "../../modules/as-bs/")); | ||
if (!relativePath.startsWith(".") && !relativePath.startsWith("/")) relativePath = "./" + relativePath; | ||
const txt = `import { bs } from "${relativePath}";`; | ||
if (!this.bsImport) { | ||
this.bsImport = txt; | ||
if (process.env["JSON_DEBUG"]) console.log("Added as-bs import: " + txt + "\n"); | ||
} | ||
addRequiredImports(node) { | ||
if (!this.imports.find((i) => i.declarations.find((d) => d.foreignName.text == "bs"))) { | ||
const __filename = fileURLToPath(import.meta.url); | ||
const __dirname = path.dirname(__filename); | ||
let relativePath = path.relative(path.dirname(node.range.source.normalizedPath), path.resolve(__dirname, "../../modules/as-bs/")); | ||
if (!relativePath.startsWith(".") && !relativePath.startsWith("/")) | ||
relativePath = "./" + relativePath; | ||
const txt = `import { bs } from "${relativePath}";`; | ||
if (!this.bsImport) { | ||
this.bsImport = txt; | ||
if (process.env["JSON_DEBUG"]) | ||
console.log("Added as-bs import: " + txt + "\n"); | ||
} | ||
} | ||
if (!this.imports.find((i) => i.declarations.find((d) => d.foreignName.text == "JSON"))) { | ||
const __filename = fileURLToPath(import.meta.url); | ||
const __dirname = path.dirname(__filename); | ||
let relativePath = path.relative(path.dirname(node.range.source.normalizedPath), path.resolve(__dirname, "../../assembly/index.ts")); | ||
if (!relativePath.startsWith(".") && !relativePath.startsWith("/")) | ||
relativePath = "./" + relativePath; | ||
const txt = `import { JSON } from "${relativePath}";`; | ||
if (!this.jsonImport) { | ||
this.jsonImport = txt; | ||
if (process.env["JSON_DEBUG"]) | ||
console.log("Added json-as import: " + txt + "\n"); | ||
} | ||
} | ||
} | ||
if (!this.imports.find((i) => i.declarations.find((d) => d.foreignName.text == "JSON"))) { | ||
const __filename = fileURLToPath(import.meta.url); | ||
const __dirname = path.dirname(__filename); | ||
let relativePath = path.relative(path.dirname(node.range.source.normalizedPath), path.resolve(__dirname, "../../assembly/index.ts")); | ||
if (!relativePath.startsWith(".") && !relativePath.startsWith("/")) relativePath = "./" + relativePath; | ||
const txt = `import { JSON } from "${relativePath}";`; | ||
if (!this.jsonImport) { | ||
this.jsonImport = txt; | ||
if (process.env["JSON_DEBUG"]) console.log("Added json-as import: " + txt + "\n"); | ||
} | ||
getStores(data, simd = false) { | ||
const out = []; | ||
const sizes = strToNum(data, simd); | ||
let offset = 0; | ||
for (const [size, num] of sizes) { | ||
if (size == "v128") { | ||
let index = this.newStmts.simd.findIndex((v) => v.includes(num)); | ||
let name = "SIMD_" + (index == -1 ? this.newStmts.simd.length : index); | ||
if (index && !this.newStmts.simd.includes(`const ${name} = ${num};`)) | ||
this.newStmts.simd.push(`const ${name} = ${num};`); | ||
out.push("store<v128>(bs.offset, " + name + ", " + offset + "); // " + data.slice(offset >> 1, (offset >> 1) + 8)); | ||
offset += 16; | ||
} | ||
if (size == "u64") { | ||
out.push("store<u64>(bs.offset, " + num + ", " + offset + "); // " + data.slice(offset >> 1, (offset >> 1) + 4)); | ||
offset += 8; | ||
} | ||
else if (size == "u32") { | ||
out.push("store<u32>(bs.offset, " + num + ", " + offset + "); // " + data.slice(offset >> 1, (offset >> 1) + 2)); | ||
offset += 4; | ||
} | ||
else if (size == "u16") { | ||
out.push("store<u16>(bs.offset, " + num + ", " + offset + "); // " + data.slice(offset >> 1, (offset >> 1) + 1)); | ||
offset += 2; | ||
} | ||
} | ||
out.push("bs.offset += " + offset + ";"); | ||
return out; | ||
} | ||
} | ||
getStores(data, simd = false) { | ||
const out = []; | ||
const sizes = strToNum(data, simd); | ||
let offset = 0; | ||
for (const [size, num] of sizes) { | ||
if (size == "v128") { | ||
let index = this.newStmts.simd.findIndex((v) => v.includes(num)); | ||
let name = "SIMD_" + (index == -1 ? this.newStmts.simd.length : index); | ||
if (index && !this.newStmts.simd.includes(`const ${name} = ${num};`)) this.newStmts.simd.push(`const ${name} = ${num};`); | ||
out.push("store<v128>(bs.offset, " + name + ", " + offset + "); // " + data.slice(offset >> 1, (offset >> 1) + 8)); | ||
offset += 16; | ||
} | ||
if (size == "u64") { | ||
out.push("store<u64>(bs.offset, " + num + ", " + offset + "); // " + data.slice(offset >> 1, (offset >> 1) + 4)); | ||
offset += 8; | ||
} else if (size == "u32") { | ||
out.push("store<u32>(bs.offset, " + num + ", " + offset + "); // " + data.slice(offset >> 1, (offset >> 1) + 2)); | ||
offset += 4; | ||
} else if (size == "u16") { | ||
out.push("store<u16>(bs.offset, " + num + ", " + offset + "); // " + data.slice(offset >> 1, (offset >> 1) + 1)); | ||
offset += 2; | ||
} | ||
} | ||
out.push("bs.offset += " + offset + ";"); | ||
return out; | ||
} | ||
} | ||
export default class Transformer extends Transform { | ||
afterParse(parser) { | ||
const transformer = new JSONTransform(); | ||
const sources = parser.sources.sort((_a, _b) => { | ||
const a = _a.internalPath; | ||
const b = _b.internalPath; | ||
if (a[0] == "~" && b[0] !== "~") { | ||
return -1; | ||
} else if (a[0] !== "~" && b[0] == "~") { | ||
return 1; | ||
} else { | ||
return 0; | ||
} | ||
}); | ||
transformer.parser = parser; | ||
for (const source of sources) { | ||
transformer.imports = []; | ||
transformer.currentSource = source; | ||
transformer.visit(source); | ||
if (transformer.newStmts.simd) { | ||
const tokenizer = new Tokenizer(new Source(0, source.normalizedPath, transformer.newStmts.simd.join("\n"))); | ||
parser.currentSource = tokenizer.source; | ||
for (let i = 0; i < transformer.newStmts.simd.length; i++) source.statements.unshift(parser.parseTopLevelStatement(tokenizer)); | ||
parser.currentSource = source; | ||
transformer.newStmts.simd = []; | ||
} | ||
if (transformer.jsonImport) { | ||
const tokenizer = new Tokenizer(new Source(0, source.normalizedPath, transformer.jsonImport)); | ||
parser.currentSource = tokenizer.source; | ||
source.statements.unshift(parser.parseTopLevelStatement(tokenizer)); | ||
parser.currentSource = source; | ||
transformer.jsonImport = null; | ||
} | ||
if (transformer.bsImport) { | ||
const tokenizer = new Tokenizer(new Source(0, source.normalizedPath, transformer.bsImport)); | ||
parser.currentSource = tokenizer.source; | ||
source.statements.unshift(parser.parseTopLevelStatement(tokenizer)); | ||
parser.currentSource = source; | ||
transformer.bsImport = null; | ||
} | ||
afterParse(parser) { | ||
const transformer = new JSONTransform(); | ||
const sources = parser.sources.sort((_a, _b) => { | ||
const a = _a.internalPath; | ||
const b = _b.internalPath; | ||
if (a[0] == "~" && b[0] !== "~") { | ||
return -1; | ||
} | ||
else if (a[0] !== "~" && b[0] == "~") { | ||
return 1; | ||
} | ||
else { | ||
return 0; | ||
} | ||
}); | ||
transformer.parser = parser; | ||
for (const source of sources) { | ||
transformer.imports = []; | ||
transformer.currentSource = source; | ||
transformer.visit(source); | ||
if (transformer.newStmts.simd) { | ||
const tokenizer = new Tokenizer(new Source(0, source.normalizedPath, transformer.newStmts.simd.join("\n"))); | ||
parser.currentSource = tokenizer.source; | ||
for (let i = 0; i < transformer.newStmts.simd.length; i++) | ||
source.statements.unshift(parser.parseTopLevelStatement(tokenizer)); | ||
parser.currentSource = source; | ||
transformer.newStmts.simd = []; | ||
} | ||
if (transformer.jsonImport) { | ||
const tokenizer = new Tokenizer(new Source(0, source.normalizedPath, transformer.jsonImport)); | ||
parser.currentSource = tokenizer.source; | ||
source.statements.unshift(parser.parseTopLevelStatement(tokenizer)); | ||
parser.currentSource = source; | ||
transformer.jsonImport = null; | ||
} | ||
if (transformer.bsImport) { | ||
const tokenizer = new Tokenizer(new Source(0, source.normalizedPath, transformer.bsImport)); | ||
parser.currentSource = tokenizer.source; | ||
source.statements.unshift(parser.parseTopLevelStatement(tokenizer)); | ||
parser.currentSource = source; | ||
transformer.bsImport = null; | ||
} | ||
} | ||
const schemas = transformer.schemas; | ||
for (const schema of schemas) { | ||
if (schema.parent) { | ||
const parent = schemas.find((v) => v.name == schema.parent?.name); | ||
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); | ||
} | ||
} | ||
} | ||
const schemas = transformer.schemas; | ||
for (const schema of schemas) { | ||
if (schema.parent) { | ||
const parent = schemas.find((v) => v.name == schema.parent?.name); | ||
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); | ||
} | ||
} | ||
} | ||
} | ||
function sortMembers(members) { | ||
return members.sort((a, b) => { | ||
const aMove = a.flags.has(PropertyFlags.OmitIf) || a.flags.has(PropertyFlags.OmitNull); | ||
const bMove = b.flags.has(PropertyFlags.OmitIf) || b.flags.has(PropertyFlags.OmitNull); | ||
if (aMove && !bMove) { | ||
return -1; | ||
} else if (!aMove && bMove) { | ||
return 1; | ||
} else { | ||
return 0; | ||
} | ||
}); | ||
return members.sort((a, b) => { | ||
const aMove = a.flags.has(PropertyFlags.OmitIf) || a.flags.has(PropertyFlags.OmitNull); | ||
const bMove = b.flags.has(PropertyFlags.OmitIf) || b.flags.has(PropertyFlags.OmitNull); | ||
if (aMove && !bMove) { | ||
return -1; | ||
} | ||
else if (!aMove && bMove) { | ||
return 1; | ||
} | ||
else { | ||
return 0; | ||
} | ||
}); | ||
} | ||
function getArgs(args) { | ||
if (!args) return []; | ||
let out = []; | ||
for (const arg of args) { | ||
if (arg instanceof StringLiteralExpression) { | ||
out.push(arg.value); | ||
} else if (arg instanceof IntegerLiteralExpression) { | ||
out.push(i64_to_string(arg.value)); | ||
} else if (arg instanceof FloatLiteralExpression) { | ||
out.push(arg.value.toString()); | ||
} else if (arg instanceof NullExpression) { | ||
out.push(arg.text); | ||
} else if (arg instanceof TrueExpression) { | ||
out.push(arg.text); | ||
} else if (arg instanceof FalseExpression) { | ||
out.push(arg.text); | ||
} else if (arg instanceof IdentifierExpression) { | ||
out.push(arg.text); | ||
if (!args) | ||
return []; | ||
let out = []; | ||
for (const arg of args) { | ||
if (arg instanceof StringLiteralExpression) { | ||
out.push(arg.value); | ||
} | ||
else if (arg instanceof IntegerLiteralExpression) { | ||
out.push(i64_to_string(arg.value)); | ||
} | ||
else if (arg instanceof FloatLiteralExpression) { | ||
out.push(arg.value.toString()); | ||
} | ||
else if (arg instanceof NullExpression) { | ||
out.push(arg.text); | ||
} | ||
else if (arg instanceof TrueExpression) { | ||
out.push(arg.text); | ||
} | ||
else if (arg instanceof FalseExpression) { | ||
out.push(arg.text); | ||
} | ||
else if (arg instanceof IdentifierExpression) { | ||
out.push(arg.text); | ||
} | ||
} | ||
} | ||
return out; | ||
return out; | ||
} | ||
function toU16(data, offset = 0) { | ||
return data.charCodeAt(offset + 0).toString(); | ||
return data.charCodeAt(offset + 0).toString(); | ||
} | ||
function toU32(data, offset = 0) { | ||
return ((data.charCodeAt(offset + 1) << 16) | data.charCodeAt(offset + 0)).toString(); | ||
return ((data.charCodeAt(offset + 1) << 16) | data.charCodeAt(offset + 0)).toString(); | ||
} | ||
function toU48(data, offset = 0) { | ||
return ((BigInt(data.charCodeAt(offset + 2)) << 32n) | (BigInt(data.charCodeAt(offset + 1)) << 16n) | BigInt(data.charCodeAt(offset + 0))).toString(); | ||
return ((BigInt(data.charCodeAt(offset + 2)) << 32n) | (BigInt(data.charCodeAt(offset + 1)) << 16n) | BigInt(data.charCodeAt(offset + 0))).toString(); | ||
} | ||
function toU64(data, offset = 0) { | ||
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(); | ||
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(); | ||
} | ||
function toMemCDecl(n, indent) { | ||
let out = ""; | ||
let offset = 0; | ||
let index = 0; | ||
while (n >= 8) { | ||
out += `${indent}const code${index++} = load<u64>(keyStart, ${offset});\n`; | ||
offset += 8; | ||
n -= 8; | ||
} | ||
while (n >= 4) { | ||
out += `${indent}const code${index++} = load<u32>(keyStart, ${offset});\n`; | ||
offset += 4; | ||
n -= 4; | ||
} | ||
if (n == 1) out += `${indent}const code${index++} = load<u16>(keyStart, ${offset});\n`; | ||
return out; | ||
let out = ""; | ||
let offset = 0; | ||
let index = 0; | ||
while (n >= 8) { | ||
out += `${indent}const code${index++} = load<u64>(keyStart, ${offset});\n`; | ||
offset += 8; | ||
n -= 8; | ||
} | ||
while (n >= 4) { | ||
out += `${indent}const code${index++} = load<u32>(keyStart, ${offset});\n`; | ||
offset += 4; | ||
n -= 4; | ||
} | ||
if (n == 1) | ||
out += `${indent}const code${index++} = load<u16>(keyStart, ${offset});\n`; | ||
return out; | ||
} | ||
function toMemCCheck(data) { | ||
let n = data.length << 1; | ||
let out = ""; | ||
let offset = 0; | ||
let index = 0; | ||
while (n >= 8) { | ||
out += ` && code${index++} == ${toU64(data, offset >> 1)}`; | ||
offset += 8; | ||
n -= 8; | ||
} | ||
while (n >= 4) { | ||
out += ` && code${index++} == ${toU32(data, offset >> 1)}`; | ||
offset += 4; | ||
n -= 4; | ||
} | ||
if (n == 1) out += ` && code${index++} == ${toU16(data, offset >> 1)}`; | ||
return out.slice(4); | ||
let n = data.length << 1; | ||
let out = ""; | ||
let offset = 0; | ||
let index = 0; | ||
while (n >= 8) { | ||
out += ` && code${index++} == ${toU64(data, offset >> 1)}`; | ||
offset += 8; | ||
n -= 8; | ||
} | ||
while (n >= 4) { | ||
out += ` && code${index++} == ${toU32(data, offset >> 1)}`; | ||
offset += 4; | ||
n -= 4; | ||
} | ||
if (n == 1) | ||
out += ` && code${index++} == ${toU16(data, offset >> 1)}`; | ||
return out.slice(4); | ||
} | ||
function strToNum(data, simd = false, offset = 0) { | ||
const out = []; | ||
let n = data.length; | ||
while (n >= 8 && simd) { | ||
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) + ")"]); | ||
offset += 8; | ||
n -= 8; | ||
} | ||
while (n >= 4) { | ||
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)); | ||
out.push(["u64", value.toString()]); | ||
offset += 4; | ||
n -= 4; | ||
} | ||
while (n >= 2) { | ||
const value = (data.charCodeAt(offset + 1) << 16) | data.charCodeAt(offset + 0); | ||
out.push(["u32", value.toString()]); | ||
offset += 2; | ||
n -= 2; | ||
} | ||
if (n === 1) { | ||
const value = data.charCodeAt(offset + 0); | ||
out.push(["u16", value.toString()]); | ||
} | ||
return out; | ||
const out = []; | ||
let n = data.length; | ||
while (n >= 8 && simd) { | ||
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) + ")"]); | ||
offset += 8; | ||
n -= 8; | ||
} | ||
while (n >= 4) { | ||
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)); | ||
out.push(["u64", value.toString()]); | ||
offset += 4; | ||
n -= 4; | ||
} | ||
while (n >= 2) { | ||
const value = (data.charCodeAt(offset + 1) << 16) | data.charCodeAt(offset + 0); | ||
out.push(["u32", value.toString()]); | ||
offset += 2; | ||
n -= 2; | ||
} | ||
if (n === 1) { | ||
const value = data.charCodeAt(offset + 0); | ||
out.push(["u16", value.toString()]); | ||
} | ||
return out; | ||
} | ||
function isPrimitive(type) { | ||
const primitiveTypes = ["u8", "u16", "u32", "u64", "i8", "i16", "i32", "i64", "f32", "f64", "bool", "boolean"]; | ||
return primitiveTypes.some((v) => type.includes(v)); | ||
const primitiveTypes = ["u8", "u16", "u32", "u64", "i8", "i16", "i32", "i64", "f32", "f64", "bool", "boolean"]; | ||
return primitiveTypes.some((v) => type.includes(v)); | ||
} | ||
function throwError(message, range) { | ||
const err = new Error(); | ||
err.stack = `${message}\n at ${range.source.normalizedPath}:${range.source.lineAt(range.start)}:${range.source.columnAt()}\n`; | ||
throw err; | ||
const err = new Error(); | ||
err.stack = `${message}\n at ${range.source.normalizedPath}:${range.source.lineAt(range.start)}:${range.source.columnAt()}\n`; | ||
throw err; | ||
} | ||
function indentInc() { | ||
indent += " "; | ||
indent += " "; | ||
} | ||
function indentDec() { | ||
indent = indent.slice(0, Math.max(0, indent.length - 2)); | ||
indent = indent.slice(0, Math.max(0, indent.length - 2)); | ||
} | ||
function sizeof(type) { | ||
if (type == "u8") return 6; | ||
else if (type == "i8") return 8; | ||
else if (type == "u16") return 10; | ||
else if (type == "i16") return 12; | ||
else if (type == "u32") return 20; | ||
else if (type == "i32") return 22; | ||
else if (type == "u64") return 40; | ||
else if (type == "i64") return 40; | ||
else if (type == "bool" || type == "boolean") return 10; | ||
else return 0; | ||
if (type == "u8") | ||
return 6; | ||
else if (type == "i8") | ||
return 8; | ||
else if (type == "u16") | ||
return 10; | ||
else if (type == "i16") | ||
return 12; | ||
else if (type == "u32") | ||
return 20; | ||
else if (type == "i32") | ||
return 22; | ||
else if (type == "u64") | ||
return 40; | ||
else if (type == "i64") | ||
return 40; | ||
else if (type == "bool" || type == "boolean") | ||
return 10; | ||
else | ||
return 0; | ||
} | ||
function allPrimitive(schema) { | ||
return !schema.members.some((p) => p.byteSize == 0); | ||
return !schema.members.some((p) => p.byteSize == 0); | ||
} | ||
//# sourceMappingURL=index.js.map | ||
//# sourceMappingURL=index.js.map |
export function getImports(source) { | ||
return source.statements.filter((v) => v.kind === 42); | ||
return source.statements.filter((v) => v.kind === 42); | ||
} | ||
export function getImportedClass(name, source, parser) { | ||
for (const stmt of getImports(source)) { | ||
const externalSource = parser.sources.find((src) => src.internalPath === stmt.internalPath); | ||
if (!externalSource) continue; | ||
const classDeclaration = externalSource.statements.find((s) => s.kind === 51 && s.name.text === name); | ||
if (classDeclaration) return classDeclaration; | ||
} | ||
return null; | ||
for (const stmt of getImports(source)) { | ||
const externalSource = parser.sources.find((src) => src.internalPath === stmt.internalPath); | ||
if (!externalSource) | ||
continue; | ||
const classDeclaration = externalSource.statements.find((s) => s.kind === 51 && s.name.text === name); | ||
if (classDeclaration) | ||
return classDeclaration; | ||
} | ||
return null; | ||
} | ||
export function getClasses(source) { | ||
return source.statements.filter((v) => v.kind === 51); | ||
return source.statements.filter((v) => v.kind === 51); | ||
} | ||
//# sourceMappingURL=linker.js.map | ||
//# sourceMappingURL=linker.js.map |
export var PropertyFlags; | ||
(function (PropertyFlags) { | ||
PropertyFlags[(PropertyFlags["OmitNull"] = 0)] = "OmitNull"; | ||
PropertyFlags[(PropertyFlags["OmitIf"] = 1)] = "OmitIf"; | ||
PropertyFlags[(PropertyFlags["Raw"] = 2)] = "Raw"; | ||
PropertyFlags[PropertyFlags["OmitNull"] = 0] = "OmitNull"; | ||
PropertyFlags[PropertyFlags["OmitIf"] = 1] = "OmitIf"; | ||
PropertyFlags[PropertyFlags["Raw"] = 2] = "Raw"; | ||
})(PropertyFlags || (PropertyFlags = {})); | ||
export class Property { | ||
name = ""; | ||
alias = null; | ||
type = ""; | ||
value = null; | ||
flags = new Map(); | ||
node; | ||
byteSize = 0; | ||
name = ""; | ||
alias = null; | ||
type = ""; | ||
value = null; | ||
flags = new Map(); | ||
node; | ||
byteSize = 0; | ||
} | ||
export class Schema { | ||
static = true; | ||
name = ""; | ||
members = []; | ||
parent = null; | ||
node; | ||
needsLink = null; | ||
byteSize = 0; | ||
deps = []; | ||
static = true; | ||
name = ""; | ||
members = []; | ||
parent = null; | ||
node; | ||
needsLink = null; | ||
byteSize = 0; | ||
deps = []; | ||
} | ||
//# sourceMappingURL=types.js.map | ||
//# sourceMappingURL=types.js.map |
import { Parser, Tokenizer, Source } from "assemblyscript/dist/assemblyscript.js"; | ||
import { ASTBuilder } from "./builder.js"; | ||
export class SimpleParser { | ||
static get parser() { | ||
return new Parser(); | ||
} | ||
static getTokenizer(s, file = "index.ts") { | ||
return new Tokenizer(new Source(0, file, s)); | ||
} | ||
static parseExpression(s) { | ||
const res = this.parser.parseExpression(this.getTokenizer(s)); | ||
if (res == null) { | ||
throw new Error("Failed to parse the expression: '" + s + "'"); | ||
static get parser() { | ||
return new Parser(); | ||
} | ||
return res; | ||
} | ||
static parseStatement(s, topLevel = false) { | ||
const res = this.parser.parseStatement(this.getTokenizer(s), topLevel); | ||
if (res == null) { | ||
throw new Error("Failed to parse the statement: '" + s + "'"); | ||
static getTokenizer(s, file = "index.ts") { | ||
return new Tokenizer(new Source(0, file, s)); | ||
} | ||
return res; | ||
} | ||
static parseTopLevelStatement(s, namespace) { | ||
const res = this.parser.parseTopLevelStatement(this.getTokenizer(s), namespace); | ||
if (res == null) { | ||
throw new Error("Failed to parse the top level statement: '" + s + "'"); | ||
static parseExpression(s) { | ||
const res = this.parser.parseExpression(this.getTokenizer(s)); | ||
if (res == null) { | ||
throw new Error("Failed to parse the expression: '" + s + "'"); | ||
} | ||
return res; | ||
} | ||
return res; | ||
} | ||
static parseClassMember(s, _class) { | ||
let res = this.parser.parseClassMember(this.getTokenizer(s, _class.range.source.normalizedPath), _class); | ||
if (res == null) { | ||
throw new Error("Failed to parse the class member: '" + s + "'"); | ||
static parseStatement(s, topLevel = false) { | ||
const res = this.parser.parseStatement(this.getTokenizer(s), topLevel); | ||
if (res == null) { | ||
throw new Error("Failed to parse the statement: '" + s + "'"); | ||
} | ||
return res; | ||
} | ||
return res; | ||
} | ||
static parseTopLevelStatement(s, namespace) { | ||
const res = this.parser.parseTopLevelStatement(this.getTokenizer(s), namespace); | ||
if (res == null) { | ||
throw new Error("Failed to parse the top level statement: '" + s + "'"); | ||
} | ||
return res; | ||
} | ||
static parseClassMember(s, _class) { | ||
let res = this.parser.parseClassMember(this.getTokenizer(s, _class.range.source.normalizedPath), _class); | ||
if (res == null) { | ||
throw new Error("Failed to parse the class member: '" + s + "'"); | ||
} | ||
return res; | ||
} | ||
} | ||
let isStdlibRegex = /\~lib\/(?:array|arraybuffer|atomics|builtins|crypto|console|compat|dataview|date|diagnostics|error|function|iterator|map|math|number|object|process|reference|regexp|set|staticarray|string|symbol|table|typedarray|vector|rt\/?|bindings\/|shared\/typeinfo)|util\/|uri|polyfills|memory/; | ||
export function isStdlib(s) { | ||
let source = s instanceof Source ? s : s.range.source; | ||
return isStdlibRegex.test(source.internalPath); | ||
let source = s instanceof Source ? s : s.range.source; | ||
return isStdlibRegex.test(source.internalPath); | ||
} | ||
export function toString(node) { | ||
return ASTBuilder.build(node); | ||
return ASTBuilder.build(node); | ||
} | ||
//# sourceMappingURL=util.js.map | ||
//# sourceMappingURL=util.js.map |
export class Visitor { | ||
currentSource = null; | ||
visit(node, ref = null) { | ||
if (node == null) return; | ||
if (node instanceof Array) { | ||
for (const n of node) { | ||
this._visit(n, ref); | ||
} | ||
} else { | ||
this._visit(node, ref); | ||
currentSource = null; | ||
visit(node, ref = null) { | ||
if (node == null) | ||
return; | ||
if (node instanceof Array) { | ||
for (const n of node) { | ||
this._visit(n, ref); | ||
} | ||
} | ||
else { | ||
this._visit(node, ref); | ||
} | ||
} | ||
} | ||
_visit(node, ref) { | ||
switch (node.kind) { | ||
case 0: | ||
this.visitSource(node, ref); | ||
break; | ||
case 1: | ||
this.visitNamedTypeNode(node, ref); | ||
break; | ||
case 2: | ||
this.visitFunctionTypeNode(node, ref); | ||
break; | ||
case 3: | ||
this.visitTypeName(node, ref); | ||
break; | ||
case 4: | ||
this.visitTypeParameter(node, ref); | ||
break; | ||
case 6: | ||
this.visitIdentifierExpression(node, ref); | ||
break; | ||
case 7: | ||
this.visitAssertionExpression(node, ref); | ||
break; | ||
case 8: | ||
this.visitBinaryExpression(node, ref); | ||
break; | ||
case 9: | ||
this.visitCallExpression(node, ref); | ||
break; | ||
case 10: | ||
this.visitClassExpression(node, ref); | ||
break; | ||
case 11: | ||
this.visitCommaExpression(node, ref); | ||
break; | ||
case 12: | ||
this.visitElementAccessExpression(node, ref); | ||
break; | ||
case 14: | ||
this.visitFunctionExpression(node, ref); | ||
break; | ||
case 15: | ||
this.visitInstanceOfExpression(node, ref); | ||
break; | ||
case 16: | ||
this.visitLiteralExpression(node, ref); | ||
break; | ||
case 17: | ||
this.visitNewExpression(node, ref); | ||
break; | ||
case 20: | ||
this.visitParenthesizedExpression(node, ref); | ||
break; | ||
case 21: | ||
this.visitPropertyAccessExpression(node, ref); | ||
break; | ||
case 22: | ||
this.visitTernaryExpression(node, ref); | ||
break; | ||
case 27: | ||
this.visitUnaryPostfixExpression(node, ref); | ||
break; | ||
case 28: | ||
this.visitUnaryPrefixExpression(node, ref); | ||
break; | ||
case 30: | ||
this.visitBlockStatement(node, ref); | ||
break; | ||
case 31: | ||
this.visitBreakStatement(node, ref); | ||
break; | ||
case 32: | ||
this.visitContinueStatement(node, ref); | ||
break; | ||
case 33: | ||
this.visitDoStatement(node, ref); | ||
break; | ||
case 34: | ||
this.visitEmptyStatement(node, ref); | ||
break; | ||
case 35: | ||
this.visitExportStatement(node, ref); | ||
break; | ||
case 36: | ||
this.visitExportDefaultStatement(node, ref); | ||
break; | ||
case 37: | ||
this.visitExportImportStatement(node, ref); | ||
break; | ||
case 38: | ||
this.visitExpressionStatement(node, ref); | ||
break; | ||
case 39: | ||
this.visitForStatement(node, ref); | ||
break; | ||
case 41: | ||
this.visitIfStatement(node, ref); | ||
break; | ||
case 42: | ||
this.visitImportStatement(node, ref); | ||
break; | ||
case 43: | ||
this.visitReturnStatement(node, ref); | ||
break; | ||
case 44: | ||
this.visitSwitchStatement(node, ref); | ||
break; | ||
case 45: | ||
this.visitThrowStatement(node, ref); | ||
break; | ||
case 46: | ||
this.visitTryStatement(node, ref); | ||
break; | ||
case 47: | ||
this.visitVariableStatement(node, ref); | ||
break; | ||
case 49: | ||
this.visitWhileStatement(node, ref); | ||
break; | ||
case 51: | ||
this.visitClassDeclaration(node, false, ref); | ||
break; | ||
case 52: | ||
this.visitEnumDeclaration(node, false, ref); | ||
break; | ||
case 53: | ||
this.visitEnumValueDeclaration(node, ref); | ||
break; | ||
case 54: | ||
this.visitFieldDeclaration(node, ref); | ||
break; | ||
case 55: | ||
this.visitFunctionDeclaration(node, false, ref); | ||
break; | ||
case 56: | ||
this.visitImportDeclaration(node, ref); | ||
break; | ||
case 57: | ||
this.visitInterfaceDeclaration(node, false, ref); | ||
break; | ||
case 58: | ||
this.visitMethodDeclaration(node, ref); | ||
break; | ||
case 59: | ||
this.visitNamespaceDeclaration(node, false, ref); | ||
break; | ||
case 60: | ||
this.visitTypeDeclaration(node, ref); | ||
break; | ||
case 61: | ||
this.visitVariableDeclaration(node, ref); | ||
break; | ||
case 62: | ||
this.visitDecoratorNode(node, ref); | ||
break; | ||
case 63: | ||
this.visitExportMember(node, ref); | ||
break; | ||
case 64: | ||
this.visitSwitchCase(node, ref); | ||
break; | ||
case 65: | ||
this.visitIndexSignature(node, ref); | ||
break; | ||
case 18: | ||
this.visitNullExpression(node, ref); | ||
break; | ||
case 25: { | ||
this.visitTrueExpression(node, ref); | ||
break; | ||
} | ||
case 13: { | ||
this.visitFalseExpression(node, ref); | ||
break; | ||
} | ||
case 29: { | ||
this.visitCompiledExpression(node, ref); | ||
break; | ||
} | ||
case 26: { | ||
this.visitConstructorExpression(node, ref); | ||
break; | ||
} | ||
case 66: { | ||
this.visitComment(node, ref); | ||
break; | ||
} | ||
case 40: { | ||
this.visitForOfStatement(node, ref); | ||
break; | ||
} | ||
case 50: { | ||
this.visitModuleDeclaration(node, ref); | ||
break; | ||
} | ||
case 19: { | ||
this.visitOmittedExpression(node, ref); | ||
break; | ||
} | ||
case 5: { | ||
this.visitParameter(node, ref); | ||
break; | ||
} | ||
case 23: { | ||
this.visitSuperExpression(node, ref); | ||
break; | ||
} | ||
case 24: { | ||
this.visitThisExpression(node, ref); | ||
break; | ||
} | ||
case 48: { | ||
this.visitVoidStatement(node, ref); | ||
break; | ||
} | ||
default: | ||
throw new Error("Could not visit invalid type!"); | ||
_visit(node, ref) { | ||
switch (node.kind) { | ||
case 0: | ||
this.visitSource(node, ref); | ||
break; | ||
case 1: | ||
this.visitNamedTypeNode(node, ref); | ||
break; | ||
case 2: | ||
this.visitFunctionTypeNode(node, ref); | ||
break; | ||
case 3: | ||
this.visitTypeName(node, ref); | ||
break; | ||
case 4: | ||
this.visitTypeParameter(node, ref); | ||
break; | ||
case 6: | ||
this.visitIdentifierExpression(node, ref); | ||
break; | ||
case 7: | ||
this.visitAssertionExpression(node, ref); | ||
break; | ||
case 8: | ||
this.visitBinaryExpression(node, ref); | ||
break; | ||
case 9: | ||
this.visitCallExpression(node, ref); | ||
break; | ||
case 10: | ||
this.visitClassExpression(node, ref); | ||
break; | ||
case 11: | ||
this.visitCommaExpression(node, ref); | ||
break; | ||
case 12: | ||
this.visitElementAccessExpression(node, ref); | ||
break; | ||
case 14: | ||
this.visitFunctionExpression(node, ref); | ||
break; | ||
case 15: | ||
this.visitInstanceOfExpression(node, ref); | ||
break; | ||
case 16: | ||
this.visitLiteralExpression(node, ref); | ||
break; | ||
case 17: | ||
this.visitNewExpression(node, ref); | ||
break; | ||
case 20: | ||
this.visitParenthesizedExpression(node, ref); | ||
break; | ||
case 21: | ||
this.visitPropertyAccessExpression(node, ref); | ||
break; | ||
case 22: | ||
this.visitTernaryExpression(node, ref); | ||
break; | ||
case 27: | ||
this.visitUnaryPostfixExpression(node, ref); | ||
break; | ||
case 28: | ||
this.visitUnaryPrefixExpression(node, ref); | ||
break; | ||
case 30: | ||
this.visitBlockStatement(node, ref); | ||
break; | ||
case 31: | ||
this.visitBreakStatement(node, ref); | ||
break; | ||
case 32: | ||
this.visitContinueStatement(node, ref); | ||
break; | ||
case 33: | ||
this.visitDoStatement(node, ref); | ||
break; | ||
case 34: | ||
this.visitEmptyStatement(node, ref); | ||
break; | ||
case 35: | ||
this.visitExportStatement(node, ref); | ||
break; | ||
case 36: | ||
this.visitExportDefaultStatement(node, ref); | ||
break; | ||
case 37: | ||
this.visitExportImportStatement(node, ref); | ||
break; | ||
case 38: | ||
this.visitExpressionStatement(node, ref); | ||
break; | ||
case 39: | ||
this.visitForStatement(node, ref); | ||
break; | ||
case 41: | ||
this.visitIfStatement(node, ref); | ||
break; | ||
case 42: | ||
this.visitImportStatement(node, ref); | ||
break; | ||
case 43: | ||
this.visitReturnStatement(node, ref); | ||
break; | ||
case 44: | ||
this.visitSwitchStatement(node, ref); | ||
break; | ||
case 45: | ||
this.visitThrowStatement(node, ref); | ||
break; | ||
case 46: | ||
this.visitTryStatement(node, ref); | ||
break; | ||
case 47: | ||
this.visitVariableStatement(node, ref); | ||
break; | ||
case 49: | ||
this.visitWhileStatement(node, ref); | ||
break; | ||
case 51: | ||
this.visitClassDeclaration(node, false, ref); | ||
break; | ||
case 52: | ||
this.visitEnumDeclaration(node, false, ref); | ||
break; | ||
case 53: | ||
this.visitEnumValueDeclaration(node, ref); | ||
break; | ||
case 54: | ||
this.visitFieldDeclaration(node, ref); | ||
break; | ||
case 55: | ||
this.visitFunctionDeclaration(node, false, ref); | ||
break; | ||
case 56: | ||
this.visitImportDeclaration(node, ref); | ||
break; | ||
case 57: | ||
this.visitInterfaceDeclaration(node, false, ref); | ||
break; | ||
case 58: | ||
this.visitMethodDeclaration(node, ref); | ||
break; | ||
case 59: | ||
this.visitNamespaceDeclaration(node, false, ref); | ||
break; | ||
case 60: | ||
this.visitTypeDeclaration(node, ref); | ||
break; | ||
case 61: | ||
this.visitVariableDeclaration(node, ref); | ||
break; | ||
case 62: | ||
this.visitDecoratorNode(node, ref); | ||
break; | ||
case 63: | ||
this.visitExportMember(node, ref); | ||
break; | ||
case 64: | ||
this.visitSwitchCase(node, ref); | ||
break; | ||
case 65: | ||
this.visitIndexSignature(node, ref); | ||
break; | ||
case 18: | ||
this.visitNullExpression(node, ref); | ||
break; | ||
case 25: { | ||
this.visitTrueExpression(node, ref); | ||
break; | ||
} | ||
case 13: { | ||
this.visitFalseExpression(node, ref); | ||
break; | ||
} | ||
case 29: { | ||
this.visitCompiledExpression(node, ref); | ||
break; | ||
} | ||
case 26: { | ||
this.visitConstructorExpression(node, ref); | ||
break; | ||
} | ||
case 66: { | ||
this.visitComment(node, ref); | ||
break; | ||
} | ||
case 40: { | ||
this.visitForOfStatement(node, ref); | ||
break; | ||
} | ||
case 50: { | ||
this.visitModuleDeclaration(node, ref); | ||
break; | ||
} | ||
case 19: { | ||
this.visitOmittedExpression(node, ref); | ||
break; | ||
} | ||
case 5: { | ||
this.visitParameter(node, ref); | ||
break; | ||
} | ||
case 23: { | ||
this.visitSuperExpression(node, ref); | ||
break; | ||
} | ||
case 24: { | ||
this.visitThisExpression(node, ref); | ||
break; | ||
} | ||
case 48: { | ||
this.visitVoidStatement(node, ref); | ||
break; | ||
} | ||
default: | ||
throw new Error("Could not visit invalid type!"); | ||
} | ||
} | ||
} | ||
visitSource(node, ref = null) { | ||
this.currentSource = node; | ||
this.visit(node.statements, node); | ||
this.currentSource = null; | ||
} | ||
visitTypeNode(node, ref = null) {} | ||
visitTypeName(node, ref = null) { | ||
this.visit(node.identifier, node); | ||
this.visit(node.next, node); | ||
} | ||
visitNamedTypeNode(node, ref = null) { | ||
this.visit(node.name, node); | ||
this.visit(node.typeArguments, node); | ||
} | ||
visitFunctionTypeNode(node, ref = null) { | ||
this.visit(node.parameters, node); | ||
this.visit(node.returnType, node); | ||
this.visit(node.explicitThisType, node); | ||
} | ||
visitTypeParameter(node, ref = null) { | ||
this.visit(node.name, node); | ||
this.visit(node.extendsType, node); | ||
this.visit(node.defaultType, node); | ||
} | ||
visitIdentifierExpression(node, ref = null) {} | ||
visitArrayLiteralExpression(node, ref = null) { | ||
this.visit(node.elementExpressions, node); | ||
} | ||
visitObjectLiteralExpression(node, ref = null) { | ||
this.visit(node.names, node); | ||
this.visit(node.values, node); | ||
} | ||
visitAssertionExpression(node, ref = null) { | ||
this.visit(node.toType, node); | ||
this.visit(node.expression, node); | ||
} | ||
visitBinaryExpression(node, ref = null) { | ||
this.visit(node.left, node); | ||
this.visit(node.right, node); | ||
} | ||
visitCallExpression(node, ref = null) { | ||
this.visit(node.expression, node); | ||
this.visit(node.typeArguments, node); | ||
this.visit(node.args, node); | ||
} | ||
visitClassExpression(node, ref = null) { | ||
this.visit(node.declaration, node); | ||
} | ||
visitCommaExpression(node, ref = null) { | ||
this.visit(node.expressions, node); | ||
} | ||
visitElementAccessExpression(node, ref = null) { | ||
this.visit(node.elementExpression, node); | ||
this.visit(node.expression, node); | ||
} | ||
visitFunctionExpression(node, ref = null) { | ||
this.visit(node.declaration, node); | ||
} | ||
visitLiteralExpression(node, ref = null) { | ||
switch (node.literalKind) { | ||
case 0: | ||
this.visitFloatLiteralExpression(node); | ||
break; | ||
case 1: | ||
this.visitIntegerLiteralExpression(node); | ||
break; | ||
case 2: | ||
this.visitStringLiteralExpression(node); | ||
break; | ||
case 3: | ||
this.visitTemplateLiteralExpression(node); | ||
break; | ||
case 4: | ||
this.visitRegexpLiteralExpression(node); | ||
break; | ||
case 5: | ||
this.visitArrayLiteralExpression(node); | ||
break; | ||
case 6: | ||
this.visitObjectLiteralExpression(node); | ||
break; | ||
default: | ||
throw new Error("Invalid LiteralKind at visitLiteralExpression(): " + node.literalKind); | ||
visitSource(node, ref = null) { | ||
this.currentSource = node; | ||
this.visit(node.statements, node); | ||
this.currentSource = null; | ||
} | ||
} | ||
visitFloatLiteralExpression(node, ref = null) {} | ||
visitInstanceOfExpression(node, ref = null) { | ||
this.visit(node.expression, node); | ||
this.visit(node.isType, node); | ||
} | ||
visitIntegerLiteralExpression(node, ref = null) {} | ||
visitStringLiteralExpression(node, ref = null) {} | ||
visitTemplateLiteralExpression(node, ref = null) {} | ||
visitRegexpLiteralExpression(node, ref = null) {} | ||
visitNewExpression(node, ref = null) { | ||
this.visit(node.typeName, node); | ||
this.visit(node.typeArguments, node); | ||
this.visit(node.args, node); | ||
} | ||
visitParenthesizedExpression(node, ref = null) { | ||
this.visit(node.expression, node); | ||
} | ||
visitPropertyAccessExpression(node, ref = null) { | ||
this.visit(node.property, node); | ||
this.visit(node.expression, node); | ||
} | ||
visitTernaryExpression(node, ref = null) { | ||
this.visit(node.condition, node); | ||
this.visit(node.ifThen, node); | ||
this.visit(node.ifElse, node); | ||
} | ||
visitUnaryExpression(node, ref = null) { | ||
this.visit(node.operand, node); | ||
} | ||
visitUnaryPostfixExpression(node, ref = null) { | ||
this.visit(node.operand, node); | ||
} | ||
visitUnaryPrefixExpression(node, ref = null) { | ||
this.visit(node.operand, node); | ||
} | ||
visitSuperExpression(node, ref = null) {} | ||
visitFalseExpression(node, ref = null) {} | ||
visitTrueExpression(node, ref = null) {} | ||
visitThisExpression(node, ref = null) {} | ||
visitNullExpression(node, ref = null) {} | ||
visitConstructorExpression(node, ref = null) {} | ||
visitNodeAndTerminate(statement, ref = null) {} | ||
visitBlockStatement(node, ref = null) { | ||
this.visit(node.statements, node); | ||
} | ||
visitBreakStatement(node, ref = null) { | ||
this.visit(node.label, node); | ||
} | ||
visitContinueStatement(node, ref = null) { | ||
this.visit(node.label, node); | ||
} | ||
visitClassDeclaration(node, isDefault = false, ref = null) { | ||
this.visit(node.name, node); | ||
this.visit(node.decorators, node); | ||
if (node.isGeneric ? node.typeParameters != null : node.typeParameters == null) { | ||
this.visit(node.typeParameters, node); | ||
this.visit(node.extendsType, node); | ||
this.visit(node.implementsTypes, node); | ||
this.visit(node.members, node); | ||
} else { | ||
throw new Error("Expected to type parameters to match class declaration, but found type mismatch instead!"); | ||
visitTypeNode(node, ref = null) { } | ||
visitTypeName(node, ref = null) { | ||
this.visit(node.identifier, node); | ||
this.visit(node.next, node); | ||
} | ||
} | ||
visitDoStatement(node, ref = null) { | ||
this.visit(node.condition, node); | ||
this.visit(node.body, node); | ||
} | ||
visitEmptyStatement(node, ref = null) {} | ||
visitEnumDeclaration(node, isDefault = false, ref = null) { | ||
this.visit(node.name, node); | ||
this.visit(node.decorators, node); | ||
this.visit(node.values, node); | ||
} | ||
visitEnumValueDeclaration(node, ref = null) { | ||
this.visit(node.name, node); | ||
this.visit(node.initializer, node); | ||
} | ||
visitExportImportStatement(node, ref = null) { | ||
this.visit(node.name, node); | ||
this.visit(node.externalName, node); | ||
} | ||
visitExportMember(node, ref = null) { | ||
this.visit(node.localName, node); | ||
this.visit(node.exportedName, node); | ||
} | ||
visitExportStatement(node, ref = null) { | ||
this.visit(node.path, node); | ||
this.visit(node.members, node); | ||
} | ||
visitExportDefaultStatement(node, ref = null) { | ||
this.visit(node.declaration, node); | ||
} | ||
visitExpressionStatement(node, ref = null) { | ||
this.visit(node.expression, ref); | ||
} | ||
visitFieldDeclaration(node, ref = null) { | ||
this.visit(node.name, node); | ||
this.visit(node.type, node); | ||
this.visit(node.initializer, node); | ||
this.visit(node.decorators, node); | ||
} | ||
visitForStatement(node, ref = null) { | ||
this.visit(node.initializer, node); | ||
this.visit(node.condition, node); | ||
this.visit(node.incrementor, node); | ||
this.visit(node.body, node); | ||
} | ||
visitFunctionDeclaration(node, isDefault = false, ref = null) { | ||
this.visit(node.name, node); | ||
this.visit(node.decorators, node); | ||
this.visit(node.typeParameters, node); | ||
this.visit(node.signature, node); | ||
this.visit(node.body, node); | ||
} | ||
visitIfStatement(node, ref = null) { | ||
this.visit(node.condition, node); | ||
this.visit(node.ifTrue, node); | ||
this.visit(node.ifFalse, node); | ||
} | ||
visitImportDeclaration(node, ref = null) { | ||
this.visit(node.foreignName, node); | ||
this.visit(node.name, node); | ||
this.visit(node.decorators, node); | ||
} | ||
visitImportStatement(node, ref = null) { | ||
this.visit(node.namespaceName, node); | ||
this.visit(node.declarations, node); | ||
} | ||
visitIndexSignature(node, ref = null) { | ||
this.visit(node.keyType, node); | ||
this.visit(node.valueType, node); | ||
} | ||
visitInterfaceDeclaration(node, isDefault = false, ref = null) { | ||
this.visit(node.name, node); | ||
this.visit(node.typeParameters, node); | ||
this.visit(node.implementsTypes, node); | ||
this.visit(node.extendsType, node); | ||
this.visit(node.members, node); | ||
} | ||
visitMethodDeclaration(node, ref = null) { | ||
this.visit(node.name, node); | ||
this.visit(node.typeParameters, node); | ||
this.visit(node.signature, node); | ||
this.visit(node.decorators, node); | ||
this.visit(node.body, node); | ||
} | ||
visitNamespaceDeclaration(node, isDefault = false, ref = null) { | ||
this.visit(node.name, node); | ||
this.visit(node.decorators, node); | ||
this.visit(node.members, node); | ||
} | ||
visitReturnStatement(node, ref = null) { | ||
this.visit(node.value, node); | ||
} | ||
visitSwitchCase(node, ref = null) { | ||
this.visit(node.label, node); | ||
this.visit(node.statements, node); | ||
} | ||
visitSwitchStatement(node, ref = null) { | ||
this.visit(node.condition, node); | ||
this.visit(node.cases, node); | ||
} | ||
visitThrowStatement(node, ref = null) { | ||
this.visit(node.value, node); | ||
} | ||
visitTryStatement(node, ref = null) { | ||
this.visit(node.bodyStatements, node); | ||
this.visit(node.catchVariable, node); | ||
this.visit(node.catchStatements, node); | ||
this.visit(node.finallyStatements, node); | ||
} | ||
visitTypeDeclaration(node, ref = null) { | ||
this.visit(node.name, node); | ||
this.visit(node.decorators, node); | ||
this.visit(node.type, node); | ||
this.visit(node.typeParameters, node); | ||
} | ||
visitVariableDeclaration(node, ref = null) { | ||
this.visit(node.name, node); | ||
this.visit(node.type, node); | ||
this.visit(node.initializer, node); | ||
} | ||
visitVariableStatement(node, ref = null) { | ||
this.visit(node.decorators, node); | ||
this.visit(node.declarations, node); | ||
} | ||
visitWhileStatement(node, ref = null) { | ||
this.visit(node.condition, node); | ||
this.visit(node.body, node); | ||
} | ||
visitVoidStatement(node, ref = null) {} | ||
visitComment(node, ref = null) {} | ||
visitDecoratorNode(node, ref = null) { | ||
this.visit(node.name, node); | ||
this.visit(node.args, node); | ||
} | ||
visitParameter(node, ref = null) { | ||
this.visit(node.name, node); | ||
this.visit(node.implicitFieldDeclaration, node); | ||
this.visit(node.initializer, node); | ||
this.visit(node.type, node); | ||
} | ||
visitCompiledExpression(node, ref = null) {} | ||
visitForOfStatement(node, ref = null) { | ||
this.visit(node.body, node); | ||
this.visit(node.variable, node); | ||
this.visit(node.iterable, node); | ||
} | ||
visitModuleDeclaration(node, ref = null) {} | ||
visitOmittedExpression(node, ref = null) {} | ||
visitNamedTypeNode(node, ref = null) { | ||
this.visit(node.name, node); | ||
this.visit(node.typeArguments, node); | ||
} | ||
visitFunctionTypeNode(node, ref = null) { | ||
this.visit(node.parameters, node); | ||
this.visit(node.returnType, node); | ||
this.visit(node.explicitThisType, node); | ||
} | ||
visitTypeParameter(node, ref = null) { | ||
this.visit(node.name, node); | ||
this.visit(node.extendsType, node); | ||
this.visit(node.defaultType, node); | ||
} | ||
visitIdentifierExpression(node, ref = null) { } | ||
visitArrayLiteralExpression(node, ref = null) { | ||
this.visit(node.elementExpressions, node); | ||
} | ||
visitObjectLiteralExpression(node, ref = null) { | ||
this.visit(node.names, node); | ||
this.visit(node.values, node); | ||
} | ||
visitAssertionExpression(node, ref = null) { | ||
this.visit(node.toType, node); | ||
this.visit(node.expression, node); | ||
} | ||
visitBinaryExpression(node, ref = null) { | ||
this.visit(node.left, node); | ||
this.visit(node.right, node); | ||
} | ||
visitCallExpression(node, ref = null) { | ||
this.visit(node.expression, node); | ||
this.visit(node.typeArguments, node); | ||
this.visit(node.args, node); | ||
} | ||
visitClassExpression(node, ref = null) { | ||
this.visit(node.declaration, node); | ||
} | ||
visitCommaExpression(node, ref = null) { | ||
this.visit(node.expressions, node); | ||
} | ||
visitElementAccessExpression(node, ref = null) { | ||
this.visit(node.elementExpression, node); | ||
this.visit(node.expression, node); | ||
} | ||
visitFunctionExpression(node, ref = null) { | ||
this.visit(node.declaration, node); | ||
} | ||
visitLiteralExpression(node, ref = null) { | ||
switch (node.literalKind) { | ||
case 0: | ||
this.visitFloatLiteralExpression(node); | ||
break; | ||
case 1: | ||
this.visitIntegerLiteralExpression(node); | ||
break; | ||
case 2: | ||
this.visitStringLiteralExpression(node); | ||
break; | ||
case 3: | ||
this.visitTemplateLiteralExpression(node); | ||
break; | ||
case 4: | ||
this.visitRegexpLiteralExpression(node); | ||
break; | ||
case 5: | ||
this.visitArrayLiteralExpression(node); | ||
break; | ||
case 6: | ||
this.visitObjectLiteralExpression(node); | ||
break; | ||
default: | ||
throw new Error("Invalid LiteralKind at visitLiteralExpression(): " + node.literalKind); | ||
} | ||
} | ||
visitFloatLiteralExpression(node, ref = null) { } | ||
visitInstanceOfExpression(node, ref = null) { | ||
this.visit(node.expression, node); | ||
this.visit(node.isType, node); | ||
} | ||
visitIntegerLiteralExpression(node, ref = null) { } | ||
visitStringLiteralExpression(node, ref = null) { } | ||
visitTemplateLiteralExpression(node, ref = null) { } | ||
visitRegexpLiteralExpression(node, ref = null) { } | ||
visitNewExpression(node, ref = null) { | ||
this.visit(node.typeName, node); | ||
this.visit(node.typeArguments, node); | ||
this.visit(node.args, node); | ||
} | ||
visitParenthesizedExpression(node, ref = null) { | ||
this.visit(node.expression, node); | ||
} | ||
visitPropertyAccessExpression(node, ref = null) { | ||
this.visit(node.property, node); | ||
this.visit(node.expression, node); | ||
} | ||
visitTernaryExpression(node, ref = null) { | ||
this.visit(node.condition, node); | ||
this.visit(node.ifThen, node); | ||
this.visit(node.ifElse, node); | ||
} | ||
visitUnaryExpression(node, ref = null) { | ||
this.visit(node.operand, node); | ||
} | ||
visitUnaryPostfixExpression(node, ref = null) { | ||
this.visit(node.operand, node); | ||
} | ||
visitUnaryPrefixExpression(node, ref = null) { | ||
this.visit(node.operand, node); | ||
} | ||
visitSuperExpression(node, ref = null) { } | ||
visitFalseExpression(node, ref = null) { } | ||
visitTrueExpression(node, ref = null) { } | ||
visitThisExpression(node, ref = null) { } | ||
visitNullExpression(node, ref = null) { } | ||
visitConstructorExpression(node, ref = null) { } | ||
visitNodeAndTerminate(statement, ref = null) { } | ||
visitBlockStatement(node, ref = null) { | ||
this.visit(node.statements, node); | ||
} | ||
visitBreakStatement(node, ref = null) { | ||
this.visit(node.label, node); | ||
} | ||
visitContinueStatement(node, ref = null) { | ||
this.visit(node.label, node); | ||
} | ||
visitClassDeclaration(node, isDefault = false, ref = null) { | ||
this.visit(node.name, node); | ||
this.visit(node.decorators, node); | ||
if (node.isGeneric ? node.typeParameters != null : node.typeParameters == null) { | ||
this.visit(node.typeParameters, node); | ||
this.visit(node.extendsType, node); | ||
this.visit(node.implementsTypes, node); | ||
this.visit(node.members, node); | ||
} | ||
else { | ||
throw new Error("Expected to type parameters to match class declaration, but found type mismatch instead!"); | ||
} | ||
} | ||
visitDoStatement(node, ref = null) { | ||
this.visit(node.condition, node); | ||
this.visit(node.body, node); | ||
} | ||
visitEmptyStatement(node, ref = null) { } | ||
visitEnumDeclaration(node, isDefault = false, ref = null) { | ||
this.visit(node.name, node); | ||
this.visit(node.decorators, node); | ||
this.visit(node.values, node); | ||
} | ||
visitEnumValueDeclaration(node, ref = null) { | ||
this.visit(node.name, node); | ||
this.visit(node.initializer, node); | ||
} | ||
visitExportImportStatement(node, ref = null) { | ||
this.visit(node.name, node); | ||
this.visit(node.externalName, node); | ||
} | ||
visitExportMember(node, ref = null) { | ||
this.visit(node.localName, node); | ||
this.visit(node.exportedName, node); | ||
} | ||
visitExportStatement(node, ref = null) { | ||
this.visit(node.path, node); | ||
this.visit(node.members, node); | ||
} | ||
visitExportDefaultStatement(node, ref = null) { | ||
this.visit(node.declaration, node); | ||
} | ||
visitExpressionStatement(node, ref = null) { | ||
this.visit(node.expression, ref); | ||
} | ||
visitFieldDeclaration(node, ref = null) { | ||
this.visit(node.name, node); | ||
this.visit(node.type, node); | ||
this.visit(node.initializer, node); | ||
this.visit(node.decorators, node); | ||
} | ||
visitForStatement(node, ref = null) { | ||
this.visit(node.initializer, node); | ||
this.visit(node.condition, node); | ||
this.visit(node.incrementor, node); | ||
this.visit(node.body, node); | ||
} | ||
visitFunctionDeclaration(node, isDefault = false, ref = null) { | ||
this.visit(node.name, node); | ||
this.visit(node.decorators, node); | ||
this.visit(node.typeParameters, node); | ||
this.visit(node.signature, node); | ||
this.visit(node.body, node); | ||
} | ||
visitIfStatement(node, ref = null) { | ||
this.visit(node.condition, node); | ||
this.visit(node.ifTrue, node); | ||
this.visit(node.ifFalse, node); | ||
} | ||
visitImportDeclaration(node, ref = null) { | ||
this.visit(node.foreignName, node); | ||
this.visit(node.name, node); | ||
this.visit(node.decorators, node); | ||
} | ||
visitImportStatement(node, ref = null) { | ||
this.visit(node.namespaceName, node); | ||
this.visit(node.declarations, node); | ||
} | ||
visitIndexSignature(node, ref = null) { | ||
this.visit(node.keyType, node); | ||
this.visit(node.valueType, node); | ||
} | ||
visitInterfaceDeclaration(node, isDefault = false, ref = null) { | ||
this.visit(node.name, node); | ||
this.visit(node.typeParameters, node); | ||
this.visit(node.implementsTypes, node); | ||
this.visit(node.extendsType, node); | ||
this.visit(node.members, node); | ||
} | ||
visitMethodDeclaration(node, ref = null) { | ||
this.visit(node.name, node); | ||
this.visit(node.typeParameters, node); | ||
this.visit(node.signature, node); | ||
this.visit(node.decorators, node); | ||
this.visit(node.body, node); | ||
} | ||
visitNamespaceDeclaration(node, isDefault = false, ref = null) { | ||
this.visit(node.name, node); | ||
this.visit(node.decorators, node); | ||
this.visit(node.members, node); | ||
} | ||
visitReturnStatement(node, ref = null) { | ||
this.visit(node.value, node); | ||
} | ||
visitSwitchCase(node, ref = null) { | ||
this.visit(node.label, node); | ||
this.visit(node.statements, node); | ||
} | ||
visitSwitchStatement(node, ref = null) { | ||
this.visit(node.condition, node); | ||
this.visit(node.cases, node); | ||
} | ||
visitThrowStatement(node, ref = null) { | ||
this.visit(node.value, node); | ||
} | ||
visitTryStatement(node, ref = null) { | ||
this.visit(node.bodyStatements, node); | ||
this.visit(node.catchVariable, node); | ||
this.visit(node.catchStatements, node); | ||
this.visit(node.finallyStatements, node); | ||
} | ||
visitTypeDeclaration(node, ref = null) { | ||
this.visit(node.name, node); | ||
this.visit(node.decorators, node); | ||
this.visit(node.type, node); | ||
this.visit(node.typeParameters, node); | ||
} | ||
visitVariableDeclaration(node, ref = null) { | ||
this.visit(node.name, node); | ||
this.visit(node.type, node); | ||
this.visit(node.initializer, node); | ||
} | ||
visitVariableStatement(node, ref = null) { | ||
this.visit(node.decorators, node); | ||
this.visit(node.declarations, node); | ||
} | ||
visitWhileStatement(node, ref = null) { | ||
this.visit(node.condition, node); | ||
this.visit(node.body, node); | ||
} | ||
visitVoidStatement(node, ref = null) { } | ||
visitComment(node, ref = null) { } | ||
visitDecoratorNode(node, ref = null) { | ||
this.visit(node.name, node); | ||
this.visit(node.args, node); | ||
} | ||
visitParameter(node, ref = null) { | ||
this.visit(node.name, node); | ||
this.visit(node.implicitFieldDeclaration, node); | ||
this.visit(node.initializer, node); | ||
this.visit(node.type, node); | ||
} | ||
visitCompiledExpression(node, ref = null) { } | ||
visitForOfStatement(node, ref = null) { | ||
this.visit(node.body, node); | ||
this.visit(node.variable, node); | ||
this.visit(node.iterable, node); | ||
} | ||
visitModuleDeclaration(node, ref = null) { } | ||
visitOmittedExpression(node, ref = null) { } | ||
} | ||
//# sourceMappingURL=visitor.js.map | ||
//# sourceMappingURL=visitor.js.map |
@@ -141,3 +141,2 @@ import { ClassDeclaration, FieldDeclaration, IdentifierExpression, Parser, Source, NodeKind, Expression, CommonFlags, StringLiteralExpression, IntegerLiteralExpression, FloatLiteralExpression, NullExpression, TrueExpression, FalseExpression, CallExpression, ImportStatement, NamespaceDeclaration, Node, Statement, Tokenizer, SourceKind, PropertyAccessExpression, Token, CommentHandler, ExpressionStatement, BinaryExpression, NamedTypeNode, Range, FEATURE_SIMD, FunctionExpression } from "assemblyscript/dist/assemblyscript.js"; | ||
let DESERIALIZE = "__DESERIALIZE(keyStart: usize, keyEnd: usize, valStart: usize, valEnd: usize, ptr: usize): void {\n switch (<u32>keyEnd - <u32>keyStart) {\n"; | ||
let ALLOCATE = "@inline __ALLOCATE(): void {\n"; | ||
@@ -228,2 +227,9 @@ indent = " "; | ||
// @ts-ignore: type | ||
arg.declaration.signature.parameters[0].type = Node.createNamedType( | ||
Node.createSimpleTypeName("this", node.range), | ||
null, | ||
false, | ||
node.range | ||
); | ||
// @ts-ignore: type | ||
arg.declaration.signature.returnType.name = Node.createSimpleTypeName("boolean", arg.declaration.signature.returnType.name.range); | ||
@@ -277,3 +283,4 @@ SERIALIZE += indent + `if (!(${toString(member.flags.get(PropertyFlags.OmitIf))})(this)) {\n`; | ||
else if (memberLen == 4) DESERIALIZE += `${indent}switch (load<u32>(keyStart)) {\n`; | ||
else if (memberLen == 6) DESERIALIZE += `${indent}let code = (<u64>load<u32>(keyStart) << 16) | <u64>load<u16>(keyStart, 4);\n`; | ||
else if (memberLen == 6) DESERIALIZE += `${indent}let code = load<u64>(keyStart) & 0x0000FFFFFFFFFFFF;\n`; | ||
else if (memberLen == 6) DESERIALIZE += `${indent}let code = load<u64>(keyStart);\n`; | ||
else DESERIALIZE += toMemCDecl(memberLen, indent); | ||
@@ -283,5 +290,6 @@ for (let i = 0; i < memberGroup.length; i++) { | ||
const memberName = member.alias || member.name; | ||
const dst = this.schemas.find(v => v.name == member.type) ? "ptr + offsetof<this>(\"" + member.name + "\") + 12" : "0"; | ||
if (memberLen == 2) { | ||
DESERIALIZE += `${indent} case ${memberName.charCodeAt(0)}: { // ${memberName}\n`; | ||
DESERIALIZE += `${indent} store<${member.type}>(ptr, JSON.__deserialize<${member.type}>(valStart, valEnd), offsetof<this>(${JSON.stringify(member.name)}));\n`; | ||
DESERIALIZE += `${indent} store<${member.type}>(ptr, JSON.__deserialize<${member.type}>(valStart, valEnd, ${dst}), offsetof<this>(${JSON.stringify(member.name)}));\n`; | ||
DESERIALIZE += `${indent} return;\n`; | ||
@@ -291,3 +299,3 @@ DESERIALIZE += `${indent} }\n`; | ||
DESERIALIZE += `${indent} case ${toU32(memberName)}: { // ${memberName}\n`; | ||
DESERIALIZE += `${indent} store<${member.type}>(ptr, JSON.__deserialize<${member.type}>(valStart, valEnd), offsetof<this>(${JSON.stringify(member.name)}));\n`; | ||
DESERIALIZE += `${indent} store<${member.type}>(ptr, JSON.__deserialize<${member.type}>(valStart, valEnd, ${dst}), offsetof<this>(${JSON.stringify(member.name)}));\n`; | ||
DESERIALIZE += `${indent} return;\n`; | ||
@@ -298,9 +306,15 @@ DESERIALIZE += `${indent} }\n`; | ||
DESERIALIZE += `if (code == ${toU48(memberName)}) { // ${memberName}\n`; | ||
DESERIALIZE += `${indent} store<${member.type}>(ptr, JSON.__deserialize<${member.type}>(valStart, valEnd), offsetof<this>(${JSON.stringify(member.name)}));\n`; | ||
DESERIALIZE += `${indent} store<${member.type}>(ptr, JSON.__deserialize<${member.type}>(valStart, valEnd, ${dst}), offsetof<this>(${JSON.stringify(member.name)}));\n`; | ||
DESERIALIZE += `${indent} return;\n`; | ||
DESERIALIZE += `${indent}}${i < memberGroup.length - 1 ? " else " : "\n"}`; | ||
} else if (memberLen == 8) { | ||
DESERIALIZE += i == 0 ? indent : ""; | ||
DESERIALIZE += `if (code == ${toU64(memberName)}) { // ${memberName}\n`; | ||
DESERIALIZE += `${indent} store<${member.type}>(ptr, JSON.__deserialize<${member.type}>(valStart, valEnd, ${dst}), offsetof<this>(${JSON.stringify(member.name)}));\n`; | ||
DESERIALIZE += `${indent} return;\n`; | ||
DESERIALIZE += `${indent}}${i < memberGroup.length - 1 ? " else " : "\n"}`; | ||
} else { | ||
DESERIALIZE += i == 0 ? indent : ""; | ||
DESERIALIZE += `if (${toMemCCheck(memberName)}) { // ${memberName}\n`; | ||
DESERIALIZE += `${indent} store<${member.type}>(ptr, JSON.__deserialize<${member.type}>(valStart, valEnd), offsetof<this>(${JSON.stringify(member.name)}));\n`; | ||
DESERIALIZE += `${indent} store<${member.type}>(ptr, JSON.__deserialize<${member.type}>(valStart, valEnd, ${dst}), offsetof<this>(${JSON.stringify(member.name)}));\n`; | ||
DESERIALIZE += `${indent} return;\n`; | ||
@@ -330,4 +344,3 @@ DESERIALIZE += `${indent}}${i < memberGroup.length - 1 ? " else " : "\n"}`; | ||
ALLOCATE += indent + "bs.proposeSize(" + this.schema.byteSize + ");\n"; | ||
ALLOCATE += "}"; | ||
SERIALIZE = SERIALIZE.slice(0, 32) + indent + "bs.proposeSize(" + this.schema.byteSize + ");\n" + SERIALIZE.slice(32); | ||
@@ -341,3 +354,2 @@ INITIALIZE += " return this;\n"; | ||
console.log(DESERIALIZE); | ||
console.log(ALLOCATE); | ||
} | ||
@@ -348,3 +360,2 @@ | ||
const DESERIALIZE_METHOD = SimpleParser.parseClassMember(DESERIALIZE, node); | ||
const ALLOCATE_METHOD = SimpleParser.parseClassMember(ALLOCATE, node); | ||
@@ -354,3 +365,2 @@ if (!node.members.find((v) => v.name.text == "__SERIALIZE")) node.members.push(SERIALIZE_METHOD); | ||
if (!node.members.find((v) => v.name.text == "__DESERIALIZE")) node.members.push(DESERIALIZE_METHOD); | ||
if (!node.members.find((v) => v.name.text == "__ALLOCATE")) node.members.push(ALLOCATE_METHOD); | ||
super.visitClassDeclaration(node); | ||
@@ -360,6 +370,5 @@ } | ||
let SERIALIZE_RAW_EMPTY = '@inline __SERIALIZE(ptr: usize = changetype<usize>(this)): string {\n return "{}";\n}'; | ||
let SERIALIZE_BS_EMPTY = "@inline __SERIALIZE(ptr: usize: bool): void {\n store<u32>(bs.offset, 8192123);\n bs.offset += 4;\n}"; | ||
let SERIALIZE_BS_EMPTY = "@inline __SERIALIZE(ptr: usize: bool): void {\n bs.proposeSize(4);\n store<u32>(bs.offset, 8192123);\n bs.offset += 4;\n}"; | ||
let INITIALIZE_EMPTY = "@inline __INITIALIZE(): this {\n return this;\n}"; | ||
let DESERIALIZE_EMPTY = "@inline __DESERIALIZE(keyStart: usize, keyEnd: usize, valStart: usize, valEnd: usize, ptr: usize): void {\n return false;\n}"; | ||
let ALLOCATE_EMPTY = "@inline __ALLOCATE(): void {\n bs.ensureSize(4);\n}"; | ||
@@ -371,3 +380,2 @@ if (process.env["JSON_DEBUG"]) { | ||
console.log(DESERIALIZE_EMPTY); | ||
console.log(ALLOCATE_EMPTY); | ||
} | ||
@@ -379,3 +387,2 @@ | ||
const DESERIALIZE_METHOD_EMPTY = SimpleParser.parseClassMember(DESERIALIZE_EMPTY, node); | ||
const ALLOCATE_METHOD_EMPTY = SimpleParser.parseClassMember(ALLOCATE_EMPTY, node); | ||
@@ -386,3 +393,2 @@ if (!node.members.find((v) => v.name.text == "__SERIALIZE")) node.members.push(SERIALIZE_RAW_METHOD_EMPTY); | ||
if (!node.members.find((v) => v.name.text == "__DESERIALIZE")) node.members.push(DESERIALIZE_METHOD_EMPTY); | ||
if (!node.members.find((v) => v.name.text == "__ALLOCATE")) node.members.push(ALLOCATE_METHOD_EMPTY); | ||
} | ||
@@ -389,0 +395,0 @@ // visitCallExpression(node: CallExpression, ref: Node): void { |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
441492
5.72%103
1.98%8472
3.82%152
8.57%