thi-ng / umbrella

⛱ Broadly scoped ecosystem & mono-repository of 199 TypeScript projects (and ~180 examples) for general purpose, functional, data driven development
https://thi.ng
Apache License 2.0
3.41k stars 151 forks source link

[shader-ast] Exhaustive types for swizzle #438

Open sylee957 opened 10 months ago

sylee957 commented 10 months ago

I think that r, g, b, a or s, t, p, q swizzles are missing from the type definition, which can be useful.

It is also possible to use template literal types to exhaustively list all the combinations of swizzles.

postspectacular commented 10 months ago

Thank you for this PR (and the other one too) - I've actually used template literal types for swizzles, but then have been consciously avoiding them after discovering they're causing very bad auto-complete performance (IDE freezes/hangs), especially if there're multiple types with hundreds or thousands of shared possibilities. Also language server RAM usage seems to blow up when using those template types. Maybe something has changed/improved in recent TS versions, but this will require further user testing (and bandwidth to do so). For now I'm happy to accept a PR for the rgba aliases, but only using non-templated versions...

sylee957 commented 10 months ago

I have a suggestion that like here that we can keep the template literals in other places to verify the shipped types, which can be useful. I think that it is possible to run tsc for test files to check only the types, but I may need help to integrate this on build scripts. I am open to other suggestions to test or generate the types as well.

postspectacular commented 10 months ago

Thank you for these updates, I will take a closer look at this in the next few days. I'm sorry you feel this is a "stupid" demand to not use template literals here. As I said earlier, I'm not totally opposed to them, just want to err on the side of caution due to very bad previous experience with them (IMHO they don't seem to be intended for cases with hundreds or more of variations each). Just need to do more testing (in situ, on existing projects and with recent TS versions)...

FWIW Here's the full code generator for the swizzle types, now updated to include your proposed new variations. These types are based on the cartesian product (aka permutations()) of the available swizzle symbols, so guaranteed to be exhaustive and I don't see any need for verifying this exhaustiveness with additional tests (also trying to keep my long term maintenance effort at bay here). I just also noticed that I've never checked that codegen into Git and will do so ASAP — posting here for your convenience/information:

import { writeText } from "@thi.ng/file-io";
import { ConsoleLogger } from "@thi.ng/logger";
import { upper } from "@thi.ng/strings";
import {
    map,
    permutations,
    range2d,
    repeat,
    str,
    transduce,
} from "@thi.ng/transducers";

const variations = ["xyzw", "rgba", "stpq"];

const types: string[][] = [];

const body = [`// generated by /tools/swizzle-gen.ts - DO NOT EDIT!\n`];

for (let syms of variations) {
    // iterate over target & source vector sizes
    for (let [src, dest] of range2d(2, 5, 1, 5)) {
        const type = `Swizzle${upper(syms)}_${src}_${dest}`;
        const swizzles = transduce(
            map((x) => `"${str("", x)}"`),
            str(" | "),
            permutations(...repeat(syms.substring(0, src), dest))
        );
        body.push(`// prettier-ignore`, `export type ${type} = ${swizzles};`);
        if (!types[src]) types[src] = [];
        types[src].push(type);
    }
}

for (let i = 2; i < 5; i++) {
    body.push(
        `// prettier-ignore`,
        `export type Swizzle${i} = ${str(" | ", types[i])};`
    );
}

// write results to source file
writeText("src/api/swizzles.ts", body, new ConsoleLogger("swizzlegen"));

The codegen is supposed to be run from the shader-ast pkg root, e.g.:

(cd packages/shader-ast && bun tools/swizzle-gen.ts)

Also, another thing to bear in mind here is that this proposed change will also require some updates to the swizzle implementations in the shader-ast-js package

sylee957 commented 10 months ago

I assume that the place to change code to implement swizzle, could be but let me know if it is right place, or I need additional work.

https://github.com/thi-ng/umbrella/pull/438/commits/acda7f42528e1924e975375dafcb8a4a14e991d0

Also, I want to see if tests could be implemented for js target.