@thi.ng/wasm-api 0.18.1 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/codegen.js DELETED
@@ -1,198 +0,0 @@
1
- import { SIZEOF } from "@thi.ng/api/typedarray";
2
- import { compareByKey } from "@thi.ng/compare/keys";
3
- import { compareNumDesc } from "@thi.ng/compare/numeric";
4
- import { DEFAULT, defmulti } from "@thi.ng/defmulti/defmulti";
5
- import { illegalArgs } from "@thi.ng/errors/illegal-arguments";
6
- import { PKG_NAME, WASM32, } from "./api.js";
7
- import { selectAlignment } from "./codegen/align.js";
8
- import { isBigNumeric, isNumeric, isPointer, isPointerLike, isSlice, isStringSlice, isWasmString, } from "./codegen/utils.js";
9
- export const DEFAULT_CODEGEN_OPTS = {
10
- debug: false,
11
- header: true,
12
- lineWidth: 80,
13
- stringType: "slice",
14
- target: WASM32,
15
- uppercaseEnums: true,
16
- };
17
- const sizeOf = defmulti((x) => x.type, {}, {
18
- [DEFAULT]: (field, types, align, opts) => {
19
- if (field.__size)
20
- return field.__size;
21
- if (field.pad != null) {
22
- field.pad < 1 && illegalArgs(`pad size must be > 0`);
23
- return (field.__size = field.pad);
24
- }
25
- let size = 0;
26
- if (isPointer(field)) {
27
- size = opts.target.usizeBytes;
28
- }
29
- else if (isSlice(field)) {
30
- size = opts.target.usizeBytes * 2;
31
- }
32
- else {
33
- size =
34
- isNumeric(field.type) || isBigNumeric(field.type)
35
- ? SIZEOF[field.type]
36
- : isWasmString(field.type)
37
- ? opts.target.usizeBytes *
38
- (isStringSlice(opts.stringType) ? 2 : 1)
39
- : sizeOf(types[field.type], types, align, opts);
40
- if (field.tag == "array" || field.tag === "vec") {
41
- size *= field.len;
42
- if (field.sentinel !== undefined && field.tag === "array") {
43
- size += SIZEOF[field.type];
44
- }
45
- }
46
- }
47
- return (field.__size = align.size(size, field.__align));
48
- },
49
- enum: (type) => {
50
- if (type.__size)
51
- return type.__size;
52
- return (type.__size = SIZEOF[type.tag]);
53
- },
54
- struct: (type, types, align, opts) => {
55
- if (type.__size)
56
- return type.__size;
57
- let offset = 0;
58
- for (let f of type.fields) {
59
- offset = align.offset(offset, f.__align);
60
- f.__offset = offset;
61
- offset += sizeOf(f, types, align, opts);
62
- }
63
- return (type.__size = align.size(offset, type.__align));
64
- },
65
- union: (type, types, align, opts) => {
66
- if (type.__size)
67
- return type.__size;
68
- let maxSize = 0;
69
- for (let f of type.fields) {
70
- f.__offset = 0;
71
- maxSize = Math.max(maxSize, sizeOf(f, types, align, opts));
72
- }
73
- return (type.__size = align.size(maxSize, type.__align));
74
- },
75
- });
76
- const alignOf = defmulti((x) => x.type, {}, {
77
- [DEFAULT]: (field, types, align, opts) => {
78
- if (field.__align)
79
- return field.__align;
80
- if (field.type === "usize") {
81
- field.type = opts.target.usize;
82
- }
83
- if (field.pad)
84
- return (field.__align = 1);
85
- return (field.__align = isPointerLike(field)
86
- ? align.align({ type: opts.target.usize })
87
- : isNumeric(field.type) || isBigNumeric(field.type)
88
- ? align.align(field)
89
- : alignOf(types[field.type], types, selectAlignment(types[field.type]), opts));
90
- },
91
- enum: (type, _, align) => {
92
- const e = type;
93
- if (!e.tag)
94
- e.tag = "i32";
95
- return (e.__align = align.align({
96
- type: e.tag,
97
- }));
98
- },
99
- struct: (type, types, align, opts) => {
100
- let maxAlign = 1;
101
- for (let f of type.fields) {
102
- maxAlign = Math.max(maxAlign, alignOf(f, types, align, opts));
103
- }
104
- return (type.__align = maxAlign);
105
- },
106
- union: (type, types, align, opts) => {
107
- let maxAlign = 1;
108
- for (let f of type.fields) {
109
- maxAlign = Math.max(maxAlign, alignOf(f, types, align, opts));
110
- }
111
- return (type.__align = maxAlign);
112
- },
113
- });
114
- const prepareType = defmulti((x) => x.type, {}, {
115
- [DEFAULT]: (x, types, alignImpl, opts) => {
116
- if (x.__align)
117
- return;
118
- alignOf(x, types, alignImpl, opts);
119
- sizeOf(x, types, alignImpl, opts);
120
- },
121
- struct: (x, types, align, opts) => {
122
- if (x.__align)
123
- return;
124
- const struct = x;
125
- alignOf(struct, types, align, opts);
126
- if (struct.auto) {
127
- struct.fields.sort(compareByKey("__align", compareNumDesc));
128
- }
129
- for (let f of struct.fields) {
130
- const type = types[f.type];
131
- if (type) {
132
- prepareType(type, types, selectAlignment(type), opts);
133
- }
134
- }
135
- sizeOf(struct, types, align, opts);
136
- },
137
- });
138
- /**
139
- * Takes a type collection and analyzes each analyzed to compute individual
140
- * alignments and sizes.
141
- *
142
- * @remarks
143
- * This function is idempotent and called automatically by
144
- * {@link generateTypes}. Only exported for dev/debug purposes.
145
- *
146
- * @param types
147
- *
148
- * @internal
149
- */
150
- export const prepareTypes = (types, opts) => {
151
- for (let id in types) {
152
- prepareType(types[id], types, selectAlignment(types[id]), opts);
153
- }
154
- return types;
155
- };
156
- /**
157
- * Code generator main entry point. Takes an object of {@link TopLevelType}
158
- * definitions, an actual code generator implementation for a single target
159
- * language and (optional) global codegen options. Returns generated source code
160
- * for all given types as a single string.
161
- *
162
- * @remarks
163
- * Before actual code generation the types are first analyzed to compute their
164
- * alignments and sizes. This is only ever done once (idempotent), even if
165
- * `generateTypes()` is called multiple times for different target langs.
166
- *
167
- * @param types
168
- * @param codegen
169
- * @param opts
170
- */
171
- export const generateTypes = (types, codegen, opts = {}) => {
172
- const $opts = {
173
- ...DEFAULT_CODEGEN_OPTS,
174
- ...opts,
175
- };
176
- prepareTypes(types, $opts);
177
- const res = [];
178
- if ($opts.header) {
179
- codegen.doc(`Generated by ${PKG_NAME} at ${new Date().toISOString()} - DO NOT EDIT!`, res, $opts, true);
180
- res.push("");
181
- }
182
- if (codegen.pre) {
183
- const pre = codegen.pre($opts);
184
- pre && res.push(pre, "");
185
- }
186
- $opts.pre && res.push($opts.pre, "");
187
- for (let id in types) {
188
- const type = types[id];
189
- type.doc && codegen.doc(type.doc, res, $opts);
190
- codegen[type.type](type, types, res, $opts);
191
- }
192
- $opts.post && res.push("", $opts.post);
193
- if (codegen.post) {
194
- const post = codegen.post($opts);
195
- post && res.push("", post);
196
- }
197
- return res.join("\n");
198
- };