/
sym.ts
114 lines (108 loc) · 3.41 KB
/
sym.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
import { assert } from "@thi.ng/api";
import { isString } from "@thi.ng/checks";
import { illegalArgs } from "@thi.ng/errors";
import type { Lit, Sym, Term } from "../api/nodes";
import type { SymOpts } from "../api/syms";
import type { ArrayTypeMap, Type } from "../api/types";
import { gensym } from "./idgen";
export function sym<T extends Type>(init: Term<T>): Sym<T>;
export function sym<T extends Type>(type: T): Sym<T>;
export function sym<T extends Type>(type: T, opts: SymOpts): Sym<T>;
export function sym<T extends Type>(type: T, init: Term<T>): Sym<T>;
export function sym<T extends Type>(type: T, id: string): Sym<T>;
// prettier-ignore
export function sym<T extends Type>(type: T, id: string, opts: SymOpts): Sym<T>;
// prettier-ignore
export function sym<T extends Type>(type: T, opts: SymOpts, init: Term<T>): Sym<T>;
// prettier-ignore
export function sym<T extends Type>(type: T, id: string, opts: SymOpts, init: Term<T>): Sym<T>;
export function sym<T extends Type>(type: any, ...xs: any[]): Sym<any> {
let id: string;
let opts: SymOpts;
let init: Term<T>;
switch (xs.length) {
case 0:
if (!isString(type)) {
init = type;
type = init.type;
}
break;
case 1:
if (isString(xs[0])) {
id = xs[0];
} else if (xs[0].tag) {
init = xs[0];
} else {
opts = xs[0];
}
break;
case 2:
if (isString(xs[0])) {
[id, opts] = xs;
} else {
[opts, init] = xs;
}
break;
case 3:
[id, opts, init] = xs;
break;
default:
illegalArgs();
}
return {
tag: "sym",
type,
id: id! || gensym(),
opts: opts! || {},
init: init!,
};
}
export const constSym = <T extends Type>(
type: T,
id?: string,
opts?: SymOpts,
init?: Term<T>
) => sym(type, id || gensym(), { const: true, ...opts }, init!);
/**
* Defines a new symbol with optional initial array values.
*
* Important: Array initializers are UNSUPPORTED in GLSL ES v1 (WebGL),
* any code using such initializers will only work under WebGL2 or other
* targets.
*/
export const arraySym = <T extends keyof ArrayTypeMap>(
type: T,
id?: string,
opts: SymOpts = {},
init?: (Lit<T> | Sym<T>)[]
): Sym<ArrayTypeMap[T]> => {
if (init && opts.num == null) {
opts.num = init.length;
}
assert(opts.num != null, "missing array length");
init &&
assert(
opts.num === init.length,
`expected ${opts.num} items in array, but got ${init.length}`
);
const atype = <Type>(type + "[]");
return <any>{
tag: "sym",
type: atype,
id: id || gensym(),
opts,
init: init
? {
tag: "array_init",
type: atype,
init,
}
: undefined,
};
};
export const input = <T extends Type>(type: T, id: string, opts?: SymOpts) =>
sym(type, id, { q: "in", type: "in", ...opts });
export const output = <T extends Type>(type: T, id: string, opts?: SymOpts) =>
sym(type, id, { q: "out", type: "out", ...opts });
export const uniform = <T extends Type>(type: T, id: string, opts?: SymOpts) =>
sym(type, id, { q: "in", type: "uni", ...opts });