Skip to content

Commit

Permalink
feat(wasm-api-bindgen): add support for external types
Browse files Browse the repository at this point in the history
- update ICodeGen interface & all impls (C, TS, Zig)
  • Loading branch information
postspectacular committed Aug 21, 2024
1 parent bb50061 commit af1a44d
Show file tree
Hide file tree
Showing 7 changed files with 93 additions and 24 deletions.
82 changes: 60 additions & 22 deletions packages/wasm-api-bindgen/src/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ export interface TopLevelType extends TypeInfo {
* The {@link TYPESCRIPT} codegen doesn't emit function pointer types
* themselves and only supports them indirectly, e.g. as struct fields.
*/
type: "enum" | "funcptr" | "struct" | "union";
type: "enum" | "ext" | "funcptr" | "struct" | "union";
/**
* Optional object of user provided source codes to be injected into the
* generated type (language dependent, only structs or unions, after
Expand All @@ -78,6 +78,18 @@ export interface InjectedBody {
impl?: string | string[];
}

export interface External extends TopLevelType {
type: "ext";
/**
* Type alignment (in bytes)
*/
align: number;
/**
* Type's byte size
*/
size: number;
}

export interface Struct extends TopLevelType {
type: "struct";
/**
Expand Down Expand Up @@ -376,48 +388,74 @@ export interface ICodeGen {
*/
post?: Fn2<TypeColl, CodeGenOpts, string>;
/**
* Docstring codegen
* Codegen for docstrings.
*
* @param doc
* @param acc
* @param opts
* @param topLevel
*/
doc: (
doc(
doc: string | string[],
acc: string[],
opts: CodeGenOpts,
topLevel?: boolean
) => void;
): void;
/**
* Codegen for enum types.
*
* @param type
* @param coll
* @param acc
* @param opts
*/
enum(type: Enum, coll: TypeColl, acc: string[], opts: CodeGenOpts): void;
/**
* Codegen for external types.
*
* @param type
* @param coll
* @param acc
* @param opts
*/
enum: (
type: Enum,
ext(type: External, coll: TypeColl, acc: string[], opts: CodeGenOpts): void;
/**
* Code gen for function pointers.
*
* @param type
* @param coll
* @param acc
* @param opts
*/
funcptr(
type: FuncPointer,
coll: TypeColl,
acc: string[],
opts: CodeGenOpts
) => void;
): void;
/**
* Codegen for struct types.
*
* @param type
* @param coll
* @param acc
* @param opts
*/
struct: (
struct(
type: Struct,
coll: TypeColl,
acc: string[],
opts: CodeGenOpts
) => void;
): void;
/**
* Codegen for union types.
*
* @param type
* @param coll
* @param acc
* @param opts
*/
union: (
type: Union,
coll: TypeColl,
acc: string[],
opts: CodeGenOpts
) => void;

funcptr: (
type: FuncPointer,
coll: TypeColl,
acc: string[],
opts: CodeGenOpts
) => void;
union(type: Union, coll: TypeColl, acc: string[], opts: CodeGenOpts): void;
}

export interface WasmTarget {
Expand Down
8 changes: 7 additions & 1 deletion packages/wasm-api-bindgen/src/c11.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ export const C11 = (opts: Partial<C11Opts> = {}) => {
res.push(
__funcptr(<FuncPointer>type, coll, opts, typePrefix)
);
} else {
} else if (type.type !== "ext") {
res.push(
`\ntypedef ${type.type} ${typePrefix}${type.name} ${typePrefix}${type.name};`
);
Expand Down Expand Up @@ -122,6 +122,12 @@ export const C11 = (opts: Partial<C11Opts> = {}) => {
acc.push(...prefixLines("// ", doc, opts.lineWidth));
},

ext: (e, _, acc) => {
acc.push(
`// external type: ${e.name} (size: ${e.size}, align: ${e.align})`
);
},

enum: (e, _, acc, opts) => {
if (!(e.tag === "i32" || e.tag === "u32")) {
unsupported(
Expand Down
4 changes: 3 additions & 1 deletion packages/wasm-api-bindgen/src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import type {
import { C11, type C11Opts } from "./c11.js";
import { generateTypes } from "./codegen.js";
import {
isExternal,
isOpaque,
isPadding,
isSizeT,
Expand Down Expand Up @@ -141,7 +142,7 @@ const addTypeSpec = (
spec: TopLevelType
) => {
if (!(spec.name && spec.type)) invalidSpec(path);
if (!["enum", "funcptr", "struct", "union"].includes(spec.type))
if (!["enum", "ext", "funcptr", "struct", "union"].includes(spec.type))
invalidSpec(path, `${spec.name} type: ${spec.type}`);
if (coll[spec.name]) invalidSpec(path, `duplicate name: ${spec.name}`);

Expand Down Expand Up @@ -171,6 +172,7 @@ const validateTypeRefs = (coll: TypeColl) => {
isSizeT(f.type) ||
isOpaque(f.type) ||
isWasmString(f.type) ||
isExternal(f.type, coll) ||
coll[f.type]
)
) {
Expand Down
8 changes: 8 additions & 0 deletions packages/wasm-api-bindgen/src/codegen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
type AlignStrategy,
type CodeGenOpts,
type Enum,
type External,
type Field,
type FuncPointer,
type ICodeGen,
Expand Down Expand Up @@ -88,6 +89,8 @@ const __sizeOf = defmulti<
return (field.__size = align.size(size, field.__align!));
},

ext: (type) => (type.__size = (<External>type).size),

enum: (type) => {
if (type.__size) return type.__size;
return (type.__size = SIZEOF[(<Enum>type).tag]);
Expand Down Expand Up @@ -154,6 +157,11 @@ const __alignOf = defmulti<
));
},

ext: (type) => {
const e = <External>type;
return (e.__align = <Pow2>e.align);
},

enum: (type, _, align) => {
const e = <Enum>type;
if (!e.tag) e.tag = "i32";
Expand Down
3 changes: 3 additions & 0 deletions packages/wasm-api-bindgen/src/internal/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ export const isFuncPointer = (type: string, coll: TypeColl) =>
export const isEnum = (type: string, coll: TypeColl) =>
coll[type]?.type === "enum";

export const isExternal = (type: string, coll: TypeColl) =>
coll[type]?.type === "ext";

export const isSlice = (x: Field["tag"]): x is "slice" => x === "slice";

export const isOpaque = (x: string): x is "opaque" => x === "opaque";
Expand Down
6 changes: 6 additions & 0 deletions packages/wasm-api-bindgen/src/typescript.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,12 @@ export const TYPESCRIPT = (opts: Partial<TSOpts> = {}) => {
acc.push("/**", ...prefixLines(" * ", doc, opts.lineWidth), " */");
},

ext: (e, _, acc) => {
acc.push(
`// external type: ${e.name} (size: ${e.size}, align: ${e.align})`
);
},

enum: (e, _, acc, opts) => {
const res: string[] = [];
res.push(`export enum ${e.name} {`);
Expand Down
6 changes: 6 additions & 0 deletions packages/wasm-api-bindgen/src/zig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,12 @@ export const ZIG = (opts: Partial<ZigOpts> = {}) => {
);
},

ext: (e, _, acc) => {
acc.push(
`// external type: ${e.name} (size: ${e.size}, align: ${e.align})`
);
},

enum: (e, _, acc, opts) => {
const lines: string[] = [];
lines.push(`pub const ${e.name} = enum(${e.tag}) {`);
Expand Down

0 comments on commit af1a44d

Please sign in to comment.