Skip to content

Commit 6d74bc7

Browse files
tool(vectors): initial import static source codegen (#497)
- this new code generator consumes existing vector fns and re-emits them as source files - initial proof-of-concept only, WIP
1 parent 2bd9fe8 commit 6d74bc7

File tree

1 file changed

+155
-0
lines changed

1 file changed

+155
-0
lines changed

packages/vectors/tools/codegen.ts

+155
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
import type { IObjectOf } from "@thi.ng/api";
2+
import { writeText } from "@thi.ng/file-io";
3+
import { ConsoleLogger } from "@thi.ng/logger";
4+
import { interpolate, wordWrapLines } from "@thi.ng/strings";
5+
import * as v from "@thi.ng/vectors";
6+
7+
const OUT_DIR = "src2";
8+
const LOGGER = new ConsoleLogger("codegen");
9+
10+
interface FnSpec {
11+
name: string;
12+
type: string;
13+
dispatch?: number;
14+
doc?: string[];
15+
params?: IObjectOf<string>;
16+
}
17+
const formatFunction = (
18+
name: string,
19+
body: string,
20+
type: string,
21+
header = `export const ${name}: ${type} = `
22+
) => {
23+
body = body
24+
.replace("function anonymous", header)
25+
.replace("\n) {", ") => {");
26+
return body;
27+
};
28+
29+
const formatDocs = (
30+
docs: string,
31+
d: string | number,
32+
params: FnSpec["params"]
33+
) => {
34+
const wrappedDocs = wordWrapLines(interpolate(docs, d), {
35+
width: 76,
36+
});
37+
const res = ["/**", " * " + wrappedDocs.join("\n * ")];
38+
if (params) {
39+
res.push(" *");
40+
for (let [id, desc] of Object.entries(params))
41+
res.push(` * @param ${id} - ${desc}`);
42+
}
43+
res.push(" */");
44+
return res;
45+
};
46+
47+
const emitFamily = ({ name, type, dispatch = 1, doc = [], params }: FnSpec) => {
48+
const nakedType = type.replace(/<[a-z0-9,]+>$/i, "");
49+
const $import = `import type { ${nakedType} } from "../src/api.js";`;
50+
const imports = [`import { vop } from "../src/vop.js";`];
51+
const $docs = doc.join("");
52+
const adds = [
53+
...formatDocs(
54+
"Multi-method. " +
55+
$docs +
56+
" Auto-delegates to optimized versions where possible.",
57+
"n",
58+
params
59+
),
60+
`export const ${name}: Multi${type} = vop(${dispatch});`,
61+
`${name}.default(${formatFunction(
62+
name,
63+
(<any>v)[name].impl().toString(),
64+
type,
65+
""
66+
)});`,
67+
];
68+
for (let d of [2, 3, 4]) {
69+
const id = name + d;
70+
if (!(<any>v)[id]) continue;
71+
imports.push(`import { ${id} } from "./${id}.js";`);
72+
writeText(
73+
`${OUT_DIR}/${id}.ts`,
74+
[
75+
$import,
76+
"",
77+
...formatDocs($docs, d, params),
78+
formatFunction(id, (<any>v)[id].toString(), type) + ";",
79+
],
80+
LOGGER
81+
);
82+
adds.push(`${name}.add(${d}, ${id});`);
83+
}
84+
writeText(
85+
`${OUT_DIR}/${name}.ts`,
86+
[
87+
`import type { Multi${nakedType} } from "../src/api.js";`,
88+
...imports,
89+
"",
90+
...adds,
91+
],
92+
LOGGER
93+
);
94+
};
95+
96+
const PARAMS_VV = { o: "output vector", a: "input vector", b: "input vector" };
97+
const PARAMS_VN = { o: "output vector", a: "input vector", n: "scalar" };
98+
99+
const SPECS: FnSpec[] = [
100+
{
101+
name: "add",
102+
type: "VecOpVV",
103+
doc: ["Componentwise {0}D vector addition."],
104+
params: PARAMS_VV,
105+
},
106+
{
107+
name: "sub",
108+
type: "VecOpVV",
109+
doc: ["Componentwise {0}D vector subtraction."],
110+
params: PARAMS_VV,
111+
},
112+
{
113+
name: "mul",
114+
type: "VecOpVV",
115+
doc: ["Componentwise {0}D vector multiplication."],
116+
params: PARAMS_VV,
117+
},
118+
{
119+
name: "div",
120+
type: "VecOpVV",
121+
doc: ["Componentwise {0}D vector division."],
122+
params: PARAMS_VV,
123+
},
124+
{
125+
name: "addN",
126+
type: "VecOpVN",
127+
doc: ["Componentwise {0}D vector addition with a uniform scalar."],
128+
params: PARAMS_VN,
129+
},
130+
{
131+
name: "subN",
132+
type: "VecOpVN",
133+
doc: ["Componentwise {0}D vector subtraction with a uniform scalar."],
134+
params: PARAMS_VN,
135+
},
136+
{
137+
name: "mulN",
138+
type: "VecOpVN",
139+
doc: [
140+
"Componentwise {0}D vector multiplication with a uniform scalar.",
141+
],
142+
params: PARAMS_VN,
143+
},
144+
{
145+
name: "divN",
146+
type: "VecOpVN",
147+
doc: ["Componentwise {0}D vector division with a uniform scalar."],
148+
params: PARAMS_VN,
149+
},
150+
{ name: "distChebyshev", type: "VecOpRoVV<number>", dispatch: 0 },
151+
];
152+
153+
for (let spec of SPECS) {
154+
emitFamily(spec);
155+
}

0 commit comments

Comments
 (0)