Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Support Set/Map for binding generator #2340

Draft
wants to merge 20 commits into
base: main
Choose a base branch
from
654 changes: 324 additions & 330 deletions src/bindings/js.ts

Large diffs are not rendered by default.

98 changes: 23 additions & 75 deletions src/bindings/tsd.ts
Expand Up @@ -20,9 +20,9 @@ import {
} from "../types";

import {
CharCode,
escapeString,
indent, isIdentifier
indent,
isIdentifier
} from "../util";

import {
Expand Down Expand Up @@ -54,28 +54,17 @@ export class TSDBuilder extends ExportsWalker {
var type = element.type;
var tsType = this.toTypeScriptType(type, Mode.EXPORT);
indent(sb, this.indentLevel);
sb.push("/** ");
sb.push(element.internalName);
sb.push(" */\n");
sb.push(`/** ${element.internalName} */\n`);
indent(sb, this.indentLevel);
sb.push("export ");
if (this.esm) sb.push("declare ");
sb.push("const ");
sb.push(name);
sb.push(": {\n");
sb.push(`export ${ this.esm ? "declare " : ""}const ${name}: {\n`);
indent(sb, ++this.indentLevel);
sb.push("/** @type `");
sb.push(type.toString());
sb.push("` */\n");
sb.push(`/** @type \`${type}\` */\n`);
indent(sb, this.indentLevel);
sb.push("get value(): ");
sb.push(tsType);
sb.push(`get value(): ${tsType}`);
if (!element.is(CommonFlags.CONST)) {
sb.push(";\n");
indent(sb, this.indentLevel);
sb.push("set value(value: ");
sb.push(tsType);
sb.push(");\n");
sb.push(`set value(value: ${tsType});\n`);
} else {
sb.push("\n");
}
Expand All @@ -86,15 +75,9 @@ export class TSDBuilder extends ExportsWalker {
visitEnum(name: string, element: Enum): void {
var sb = this.sb;
indent(sb, this.indentLevel);
sb.push("/** ");
sb.push(element.internalName);
sb.push(" */\n");
sb.push(`/** ${element.internalName} */\n`);
indent(sb, this.indentLevel++);
sb.push("export ");
if (this.esm) sb.push("declare ");
sb.push("enum ");
sb.push(name);
sb.push(" {\n");
sb.push(`export ${ this.esm ? "declare " : ""}enum ${name} {\n`);
var members = element.members;
if (members) {
// TODO: for (let [memberName, member] of members) {
Expand All @@ -105,8 +88,7 @@ export class TSDBuilder extends ExportsWalker {
indent(sb, this.indentLevel);
sb.push("/** @type `i32` */\n");
indent(sb, this.indentLevel);
sb.push(memberName);
sb.push(",\n");
sb.push(`${memberName},\n`);
}
}
indent(sb, --this.indentLevel);
Expand All @@ -119,45 +101,30 @@ export class TSDBuilder extends ExportsWalker {
indent(sb, this.indentLevel);
sb.push("/**\n");
indent(sb, this.indentLevel);
sb.push(" * ");
sb.push(element.internalName);
sb.push("\n");
sb.push(` * ${element.internalName}\n`);
var parameterTypes = signature.parameterTypes;
var numParameters = parameterTypes.length;
for (let i = 0; i < numParameters; ++i) {
indent(sb, this.indentLevel);
sb.push(" * @param ");
sb.push(element.getParameterName(i));
sb.push(" `");
sb.push(parameterTypes[i].toString());
sb.push("`\n");
sb.push(` * @param ${element.getParameterName(i)} \`${parameterTypes[i]}\`\n`);
}
var returnType = signature.returnType;
if (returnType != Type.void) {
indent(sb, this.indentLevel);
sb.push(" * @returns `");
sb.push(returnType.toString());
sb.push("`\n");
sb.push(` * @returns \`${returnType}\`\n`);
}
indent(sb, this.indentLevel);
sb.push(" */\n");
indent(sb, this.indentLevel);
sb.push("export ");
if (this.esm) sb.push("declare ");
sb.push("function ");
sb.push(name);
sb.push("(");
sb.push(`export ${this.esm ? "declare " : ""}function ${name}(`);
var requiredParameters = signature.requiredParameters;
for (let i = 0; i < numParameters; ++i) {
if (i) sb.push(", ");
sb.push(element.getParameterName(i));
if (i >= requiredParameters) sb.push("?");
sb.push(": ");
sb.push(this.toTypeScriptType(parameterTypes[i], Mode.IMPORT));
sb.push(`: ${this.toTypeScriptType(parameterTypes[i], Mode.IMPORT)}`);
}
sb.push("): ");
sb.push(this.toTypeScriptType(returnType, Mode.EXPORT));
sb.push(";\n");
sb.push(`): ${this.toTypeScriptType(returnType, Mode.EXPORT)};\n`);
}

visitClass(name: string, element: Class): void {
Expand Down Expand Up @@ -205,9 +172,7 @@ export class TSDBuilder extends ExportsWalker {
if (isIdentifier(moduleName)) {
sb.push(moduleName);
} else {
sb.push("\"");
sb.push(escapeString(moduleName, CharCode.DOUBLEQUOTE));
sb.push("\"");
sb.push(`"${escapeString(moduleName)}"`);
}
sb.push(": unknown,\n");
}
Expand Down Expand Up @@ -246,9 +211,7 @@ export class TSDBuilder extends ExportsWalker {
clazz.extends(this.program.staticArrayPrototype)
) {
const valueType = clazz.getArrayValueType();
sb.push("Array<");
sb.push(this.toTypeScriptType(valueType, mode));
sb.push(">");
sb.push(`Array<${this.toTypeScriptType(valueType, mode)}>`);
} else if (clazz.extends(this.program.arrayBufferViewInstance.prototype)) {
const valueType = clazz.getArrayValueType();
if (valueType == Type.i8) {
Expand Down Expand Up @@ -325,23 +288,14 @@ export class TSDBuilder extends ExportsWalker {
makeRecordType(clazz: Class, mode: Mode): string {
var sb = new Array<string>();
var members = clazz.members;
sb.push("/** ");
sb.push(clazz.internalName);
sb.push(" */\ndeclare interface __Record");
sb.push(clazz.id.toString());
sb.push("<TOmittable> {\n");
sb.push(`/** ${clazz.internalName} */\ndeclare interface __Record${clazz.id}<TOmittable> {\n`);
if (members) {
for (let _keys = Map_keys(members), i = 0, k = _keys.length; i < k; ++i) {
let memberName = _keys[i];
let member = assert(members.get(memberName));
if (member.kind != ElementKind.FIELD) continue;
let field = <Field>member;
sb.push(" /** @type `");
sb.push(field.type.toString());
sb.push("` */\n ");
sb.push(field.name);
sb.push(": ");
sb.push(this.toTypeScriptType(field.type, mode));
sb.push(` /** @type \`${field.type}\` */\n ${field.name}: ${this.toTypeScriptType(field.type, mode)}`);
if (this.fieldAcceptsUndefined(field.type)) {
sb.push(" | TOmittable");
}
Expand All @@ -361,17 +315,11 @@ export class TSDBuilder extends ExportsWalker {

makeInternrefType(clazz: Class): string {
var sb = new Array<string>();
sb.push("/** ");
sb.push(clazz.internalName);
sb.push(" */\n");
sb.push("declare class __Internref");
sb.push(clazz.id.toString());
sb.push(" extends Number {\n");
sb.push(`/** ${clazz.internalName} */\n`);
sb.push(`declare class __Internref${clazz.id} extends Number {\n`);
var base: Class | null = clazz;
do {
sb.push(" private __nominal");
sb.push(base.id.toString());
sb.push(": symbol;\n");
sb.push(` private __nominal${base.id}: symbol;\n`);
base = base.base;
} while (base);
sb.push("}\n");
Expand Down
4 changes: 2 additions & 2 deletions src/extra/ast.ts
Expand Up @@ -684,7 +684,7 @@ export class ASTBuilder {
visitStringLiteral(str: string): void {
var sb = this.sb;
sb.push("\"");
sb.push(escapeString(str, CharCode.DOUBLEQUOTE));
sb.push(escapeString(str));
sb.push("\"");
}

Expand Down Expand Up @@ -1482,7 +1482,7 @@ export class ASTBuilder {
sb.push("declare ");
}
sb.push("module \"");
sb.push(escapeString(node.moduleName, CharCode.DOUBLEQUOTE));
sb.push(escapeString(node.moduleName));
sb.push("\"");
}

Expand Down
2 changes: 1 addition & 1 deletion src/util/text.ts
Expand Up @@ -453,7 +453,7 @@ export function indent(sb: string[], level: i32): void {
}

/** Escapes a string using the specified kind of quote. */
export function escapeString(str: string, quote: CharCode): string {
export function escapeString(str: string, quote: CharCode = CharCode.DOUBLEQUOTE): string {
var sb = new Array<string>();
var off = 0;
var i = 0;
Expand Down
66 changes: 60 additions & 6 deletions tests/compiler/bindings/esm.debug.d.ts
Expand Up @@ -94,27 +94,81 @@ export declare function staticarrayFunction(a: Array<number>, b: Array<number>):
* @returns `~lib/array/Array<i32>`
*/
export declare function arrayFunction(a: Array<number>, b: Array<number>): Array<number>;
/**
* bindings/esm/setU8Function
* @returns `~lib/set/Set<u8>`
*/
export declare function setU8Function(): __Internref8;
/**
* bindings/esm/setI32Function
* @returns `~lib/set/Set<i32>`
*/
export declare function setI32Function(): __Internref9;
/**
* bindings/esm/setF64Function
* @returns `~lib/set/Set<f64>`
*/
export declare function setF64Function(): __Internref10;
/**
* bindings/esm/mapStringU8Function
* @returns `~lib/map/Map<~lib/string/String,u8>`
*/
export declare function mapStringU8Function(): __Internref11;
/**
* bindings/esm/mapI32F64Function
* @returns `~lib/map/Map<i32,f64>`
*/
export declare function mapI32F64Function(): __Internref12;
/**
* bindings/esm/mapU16I64Function
* @returns `~lib/map/Map<u16,i64>`
*/
export declare function mapU16I64Function(): __Internref13;
/**
* bindings/esm/objectFunction
* @param a `bindings/esm/PlainObject`
* @param b `bindings/esm/PlainObject`
* @returns `bindings/esm/PlainObject`
*/
export declare function objectFunction(a: __Record8<undefined>, b: __Record8<undefined>): __Record8<never>;
export declare function objectFunction(a: __Record14<undefined>, b: __Record14<undefined>): __Record14<never>;
/**
* bindings/esm/newInternref
* @returns `bindings/esm/NonPlainObject`
*/
export declare function newInternref(): __Internref11;
export declare function newInternref(): __Internref17;
/**
* bindings/esm/internrefFunction
* @param a `bindings/esm/NonPlainObject`
* @param b `bindings/esm/NonPlainObject`
* @returns `bindings/esm/NonPlainObject`
*/
export declare function internrefFunction(a: __Internref11, b: __Internref11): __Internref11;
export declare function internrefFunction(a: __Internref17, b: __Internref17): __Internref17;
/** ~lib/set/Set<u8> */
declare class __Internref8 extends Number {
private __nominal8: symbol;
}
/** ~lib/set/Set<i32> */
declare class __Internref9 extends Number {
private __nominal9: symbol;
}
/** ~lib/set/Set<f64> */
declare class __Internref10 extends Number {
private __nominal10: symbol;
}
/** ~lib/map/Map<~lib/string/String,u8> */
declare class __Internref11 extends Number {
private __nominal11: symbol;
}
/** ~lib/map/Map<i32,f64> */
declare class __Internref12 extends Number {
private __nominal12: symbol;
}
/** ~lib/map/Map<u16,i64> */
declare class __Internref13 extends Number {
private __nominal13: symbol;
}
/** bindings/esm/PlainObject */
declare interface __Record8<TOmittable> {
declare interface __Record14<TOmittable> {
/** @type `i8` */
a: number | TOmittable;
/** @type `i16` */
Expand Down Expand Up @@ -149,6 +203,6 @@ declare interface __Record8<TOmittable> {
p: Array<string> | null | TOmittable;
}
/** bindings/esm/NonPlainObject */
declare class __Internref11 extends Number {
private __nominal11: symbol;
declare class __Internref17 extends Number {
private __nominal17: symbol;
}