glre 0.28.0 → 0.29.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/dist/index.cjs +32 -28
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +88 -52
- package/dist/index.js +32 -28
- package/dist/index.js.map +1 -1
- package/dist/native.cjs +32 -28
- package/dist/native.cjs.map +1 -1
- package/dist/native.d.cts +10 -9
- package/dist/native.js +32 -28
- package/dist/native.js.map +1 -1
- package/dist/react.cjs +32 -28
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +2 -1
- package/dist/react.js +32 -28
- package/dist/react.js.map +1 -1
- package/dist/solid.cjs +32 -28
- package/dist/solid.cjs.map +1 -1
- package/dist/solid.d.cts +2 -1
- package/dist/solid.js +32 -28
- package/dist/solid.js.map +1 -1
- package/package.json +1 -1
- package/src/node/code.ts +51 -50
- package/src/node/const.ts +41 -2
- package/src/node/index.ts +48 -31
- package/src/node/infer.ts +26 -23
- package/src/node/node.ts +29 -38
- package/src/node/scope.ts +43 -62
- package/src/node/types.ts +8 -13
- package/src/node/utils.ts +25 -10
- package/src/types.ts +7 -7
- package/src/utils/pipeline.ts +6 -6
- package/src/utils/program.ts +6 -6
- package/src/webgl.ts +1 -2
package/src/node/code.ts
CHANGED
|
@@ -1,67 +1,72 @@
|
|
|
1
1
|
import { is } from '../utils/helpers'
|
|
2
2
|
import { infer } from './infer'
|
|
3
|
-
import { joins, getOperator, formatConversions } from './utils'
|
|
3
|
+
import { joins, getOperator, formatConversions, generateDefine } from './utils'
|
|
4
|
+
import { WGSL_TO_GLSL_BUILTIN } from './const'
|
|
4
5
|
import type { NodeConfig, X } from './types'
|
|
5
6
|
|
|
6
7
|
export const code = (target: X, c?: NodeConfig | null): string => {
|
|
7
8
|
if (!c) c = {}
|
|
8
|
-
if (!c.
|
|
9
|
-
if (!c.functions) c.functions = new Set()
|
|
10
|
-
if (is.num(target)) return target.toFixed(1)
|
|
9
|
+
if (!c.headers) c.headers = new Map()
|
|
11
10
|
if (is.str(target)) return target
|
|
12
|
-
if (is.
|
|
11
|
+
if (is.num(target)) return target.toFixed(1)
|
|
12
|
+
if (is.bol(target)) return target ? 'true' : 'false'
|
|
13
13
|
if (!target) return '' // ignore if no target
|
|
14
14
|
const { type, props } = target
|
|
15
15
|
const { id = '', children = [] } = props
|
|
16
16
|
const [x, y, z] = children
|
|
17
|
+
let head = ''
|
|
17
18
|
if (type === 'uniform') {
|
|
19
|
+
if (c.headers.has(id)) return id
|
|
20
|
+
if (!c.binding) c.binding = 0
|
|
18
21
|
const varType = infer(target, c)
|
|
19
|
-
c.
|
|
20
|
-
|
|
22
|
+
head = c.isWebGL
|
|
23
|
+
? `uniform ${varType} ${id};`
|
|
24
|
+
: `@group(0) @binding(${c.binding++}) var<uniform> ${id}: ${formatConversions(varType, c)};`
|
|
25
|
+
}
|
|
26
|
+
if (type === 'attribute') {
|
|
27
|
+
if (c.headers.has(id)) return id
|
|
28
|
+
head = `${infer(target, c)} ${id}`
|
|
29
|
+
}
|
|
30
|
+
if (type === 'constant') {
|
|
31
|
+
if (c.headers.has(id)) return id
|
|
32
|
+
head = `${infer(target, c)} ${id}`
|
|
33
|
+
}
|
|
34
|
+
if (type === 'varying') {
|
|
35
|
+
if (c.headers.has(id)) return id
|
|
36
|
+
head = `${infer(target, c)} ${id}`
|
|
37
|
+
}
|
|
38
|
+
if (head) {
|
|
39
|
+
c.headers.set(id, head)
|
|
40
|
+
c.onMount?.(id, props.value)
|
|
21
41
|
return id
|
|
22
42
|
}
|
|
23
|
-
if (type === 'variable'
|
|
24
|
-
if (type === 'vertex_stage') return code(x, c)
|
|
43
|
+
if (type === 'variable') return id
|
|
25
44
|
if (type === 'swizzle') return `${code(y, c)}.${code(x, c)}`
|
|
26
45
|
if (type === 'operator') {
|
|
27
46
|
if (x === 'not' || x === 'bitNot') return `!${code(y, c)}`
|
|
28
47
|
return `(${code(y, c)} ${getOperator(x)} ${code(z, c)})`
|
|
29
48
|
}
|
|
30
|
-
if (type === '
|
|
31
|
-
|
|
49
|
+
if (type === 'function') {
|
|
50
|
+
// Handle special functions that need to be converted to operators
|
|
51
|
+
if (x === 'negate') return `(-${joins(children.slice(1), c)})`
|
|
52
|
+
return `${x}(${joins(children.slice(1), c)})`
|
|
53
|
+
}
|
|
54
|
+
if (type === 'conversion') return `${formatConversions(x, c)}(${joins(children.slice(1), c)})`
|
|
32
55
|
if (type === 'scope') return children.map((child: any) => code(child, c)).join('\n')
|
|
33
56
|
if (type === 'assign') return `${code(x, c)} = ${code(y, c)};`
|
|
34
|
-
if (type === '
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
}
|
|
41
|
-
if (type === 'fn_def') {
|
|
42
|
-
const { paramInfo = [], returnType } = props
|
|
43
|
-
const scopeCode = code(x, c)
|
|
44
|
-
const returnCode = y ? `return ${code(y, c)};` : ''
|
|
45
|
-
if (c?.isWebGL) {
|
|
46
|
-
const params = paramInfo.map(({ name, type }) => `${type} ${name}`).join(', ')
|
|
47
|
-
return `${returnType} ${id}(${params}) {\n${scopeCode}\n${returnCode}\n}`
|
|
48
|
-
} else {
|
|
49
|
-
const wgslReturnType = formatConversions(returnType, c)
|
|
50
|
-
const wgslParams = paramInfo
|
|
51
|
-
.map(({ name, type }) => {
|
|
52
|
-
const wgslParamType = formatConversions(type, c)
|
|
53
|
-
return `${name}: ${wgslParamType}`
|
|
54
|
-
})
|
|
55
|
-
.join(', ')
|
|
56
|
-
return `fn ${id}(${wgslParams}) -> ${wgslReturnType} {\n${scopeCode}\n${returnCode}\n}`
|
|
57
|
-
}
|
|
57
|
+
if (type === 'define') {
|
|
58
|
+
const args = children.slice(2)
|
|
59
|
+
const ret = `${id}(${args.map((arg) => code(arg, c))})`
|
|
60
|
+
if (c.headers.has(id)) return ret
|
|
61
|
+
c.headers.set(id, generateDefine(props, c))
|
|
62
|
+
return ret
|
|
58
63
|
}
|
|
59
64
|
if (type === 'loop') return `for (int i = 0; i < ${x}; i++) {\n${code(y, c)}\n}`
|
|
60
65
|
if (type === 'if') {
|
|
61
66
|
let ret = `if (${code(x, c)}) {\n${code(y, c)}\n}`
|
|
62
67
|
for (let i = 2; i < children.length; i += 2) {
|
|
63
|
-
const
|
|
64
|
-
ret += !
|
|
68
|
+
const isElseIf = i >= children.length - 1
|
|
69
|
+
ret += !isElseIf
|
|
65
70
|
? ` else if (${code(children[i], c)}) {\n${code(children[i + 1], c)}\n}`
|
|
66
71
|
: ` else {\n${code(children[i], c)}\n}`
|
|
67
72
|
}
|
|
@@ -69,21 +74,16 @@ export const code = (target: X, c?: NodeConfig | null): string => {
|
|
|
69
74
|
}
|
|
70
75
|
if (type === 'switch') {
|
|
71
76
|
let ret = `switch (${code(x, c)}) {\n`
|
|
72
|
-
for (
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
const scope = children[children.length - 1]
|
|
79
|
-
let ret = ''
|
|
80
|
-
for (const value of values) {
|
|
81
|
-
ret += `case ${code(value, c)}:\n`
|
|
77
|
+
for (let i = 1; i < children.length; i += 2) {
|
|
78
|
+
const isDefault = i >= children.length - 1
|
|
79
|
+
if (isDefault && children.length % 2 === 0) {
|
|
80
|
+
ret += `default:\n${code(children[i], c)}\nbreak;\n`
|
|
81
|
+
} else if (i + 1 < children.length)
|
|
82
|
+
ret += `case ${code(children[i], c)}:\n${code(children[i + 1], c)}\nbreak;\n`
|
|
82
83
|
}
|
|
83
|
-
ret +=
|
|
84
|
+
ret += '}'
|
|
84
85
|
return ret
|
|
85
86
|
}
|
|
86
|
-
if (type === 'default') `default:\n${code(x, c)}\nbreak;\n`
|
|
87
87
|
if (type === 'ternary') return `(${code(x, c)} ? ${code(y, c)} : ${code(z, c)})`
|
|
88
88
|
if (type === 'declare') {
|
|
89
89
|
const varType = infer(y, c)
|
|
@@ -94,7 +94,8 @@ export const code = (target: X, c?: NodeConfig | null): string => {
|
|
|
94
94
|
}
|
|
95
95
|
if (type === 'builtin') {
|
|
96
96
|
if (c?.isWebGL) {
|
|
97
|
-
|
|
97
|
+
const glslBuiltin = WGSL_TO_GLSL_BUILTIN[id as keyof typeof WGSL_TO_GLSL_BUILTIN]
|
|
98
|
+
if (glslBuiltin) return glslBuiltin
|
|
98
99
|
if (id === 'uv') return 'gl_FragCoord.xy'
|
|
99
100
|
}
|
|
100
101
|
return id
|
package/src/node/const.ts
CHANGED
|
@@ -69,7 +69,6 @@ export const OPERATORS = {
|
|
|
69
69
|
|
|
70
70
|
export const OPERATOR_KEYS = Object.keys(OPERATORS) as (keyof typeof OPERATORS)[]
|
|
71
71
|
|
|
72
|
-
// Function return type classification
|
|
73
72
|
export const SCALAR_RETURN_FUNCTIONS = ['dot', 'distance', 'length', 'lengthSq', 'determinant', 'luminance'] as const
|
|
74
73
|
|
|
75
74
|
export const BOOL_RETURN_FUNCTIONS = ['all', 'any'] as const
|
|
@@ -171,8 +170,37 @@ export const COMPONENT_COUNT_TO_TYPE = {
|
|
|
171
170
|
} as const
|
|
172
171
|
|
|
173
172
|
export const BUILTIN_TYPES = {
|
|
173
|
+
// WGSL builtin variables
|
|
174
|
+
position: 'vec4',
|
|
175
|
+
vertex_index: 'uint',
|
|
176
|
+
instance_index: 'uint',
|
|
177
|
+
front_facing: 'bool',
|
|
178
|
+
frag_depth: 'float',
|
|
179
|
+
sample_index: 'uint',
|
|
180
|
+
sample_mask: 'uint',
|
|
181
|
+
point_coord: 'vec2',
|
|
182
|
+
|
|
183
|
+
// TSL compatible variables
|
|
184
|
+
positionLocal: 'vec3',
|
|
185
|
+
positionWorld: 'vec3',
|
|
186
|
+
positionView: 'vec3',
|
|
187
|
+
normalLocal: 'vec3',
|
|
188
|
+
normalWorld: 'vec3',
|
|
189
|
+
normalView: 'vec3',
|
|
190
|
+
screenCoordinate: 'vec2',
|
|
191
|
+
screenUV: 'vec2',
|
|
192
|
+
|
|
193
|
+
// Legacy GLSL variables (for backward compatibility)
|
|
174
194
|
gl_FragCoord: 'vec4',
|
|
175
|
-
|
|
195
|
+
gl_VertexID: 'uint',
|
|
196
|
+
gl_InstanceID: 'uint',
|
|
197
|
+
gl_FrontFacing: 'bool',
|
|
198
|
+
gl_FragDepth: 'float',
|
|
199
|
+
gl_SampleID: 'uint',
|
|
200
|
+
gl_SampleMask: 'uint',
|
|
201
|
+
gl_PointCoord: 'vec2',
|
|
202
|
+
|
|
203
|
+
// Common variables
|
|
176
204
|
normal: 'vec3',
|
|
177
205
|
uv: 'vec2',
|
|
178
206
|
color: 'vec4',
|
|
@@ -188,3 +216,14 @@ export const COMPARISON_OPERATORS = [
|
|
|
188
216
|
] as const
|
|
189
217
|
|
|
190
218
|
export const LOGICAL_OPERATORS = ['and', 'or'] as const
|
|
219
|
+
|
|
220
|
+
export const WGSL_TO_GLSL_BUILTIN = {
|
|
221
|
+
position: 'gl_FragCoord',
|
|
222
|
+
vertex_index: 'gl_VertexID',
|
|
223
|
+
instance_index: 'gl_InstanceID',
|
|
224
|
+
front_facing: 'gl_FrontFacing',
|
|
225
|
+
frag_depth: 'gl_FragDepth',
|
|
226
|
+
sample_index: 'gl_SampleID',
|
|
227
|
+
sample_mask: 'gl_SampleMask',
|
|
228
|
+
point_coord: 'gl_PointCoord',
|
|
229
|
+
} as const
|
package/src/node/index.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { conversion as c, function_ as f, node } from './node'
|
|
2
2
|
import { hex2rgb } from './utils'
|
|
3
3
|
import { is } from '../utils/helpers'
|
|
4
4
|
import type { X } from './types'
|
|
@@ -10,20 +10,33 @@ export * from './scope'
|
|
|
10
10
|
export * from './types'
|
|
11
11
|
export * from './utils'
|
|
12
12
|
|
|
13
|
+
// x ? y : z
|
|
14
|
+
export const select = (x: X, y: X, z: X) => node('ternary', null, x, y, z)
|
|
15
|
+
|
|
16
|
+
// uniform and attribute
|
|
17
|
+
export const uniform = (value: number | number[], id?: string) => node('uniform', { id, value })
|
|
18
|
+
export const varying = (value: number | number[], id?: string) => node('varying', { id, value })
|
|
19
|
+
export const attribute = (value: number | number[], id?: string) => node('varying', { id, value })
|
|
20
|
+
export const variable = (id: string) => node('variable', { id })
|
|
21
|
+
export const builtin = (id: string) => node('builtin', { id })
|
|
22
|
+
|
|
13
23
|
// Default uniforms
|
|
14
|
-
export const iResolution =
|
|
15
|
-
export const iMouse =
|
|
16
|
-
export const iTime =
|
|
17
|
-
export const position = node('variable', { id: 'gl_FragCoord' })
|
|
24
|
+
export const iResolution = uniform([1280, 800], 'iResolution')
|
|
25
|
+
export const iMouse = uniform([0, 0], 'iMouse')
|
|
26
|
+
export const iTime = uniform(0, 'iTime')
|
|
18
27
|
|
|
19
|
-
//
|
|
20
|
-
export const
|
|
21
|
-
export const
|
|
22
|
-
export const
|
|
23
|
-
export const
|
|
28
|
+
// Builtin Variables
|
|
29
|
+
export const position = node('builtin', { id: 'position' })
|
|
30
|
+
export const vertexIndex = node('builtin', { id: 'vertex_index' })
|
|
31
|
+
export const instanceIndex = node('builtin', { id: 'instance_index' })
|
|
32
|
+
export const frontFacing = node('builtin', { id: 'front_facing' })
|
|
33
|
+
export const fragDepth = node('builtin', { id: 'frag_depth' })
|
|
34
|
+
export const sampleIndex = node('builtin', { id: 'sample_index' })
|
|
35
|
+
export const sampleMask = node('builtin', { id: 'sample_mask' })
|
|
36
|
+
export const pointCoord = node('builtin', { id: 'point_coord' })
|
|
24
37
|
|
|
25
|
-
//
|
|
26
|
-
export const positionLocal = node('builtin', { id: '
|
|
38
|
+
// TSL Compatible Builtin Variables
|
|
39
|
+
export const positionLocal = node('builtin', { id: 'position' })
|
|
27
40
|
export const positionWorld = node('builtin', { id: 'positionWorld' })
|
|
28
41
|
export const positionView = node('builtin', { id: 'positionView' })
|
|
29
42
|
export const normalLocal = node('builtin', { id: 'normalLocal' })
|
|
@@ -32,26 +45,30 @@ export const normalView = node('builtin', { id: 'normalView' })
|
|
|
32
45
|
export const screenCoordinate = node('builtin', { id: 'screenCoordinate' })
|
|
33
46
|
export const screenUV = node('builtin', { id: 'screenUV' })
|
|
34
47
|
|
|
48
|
+
// Legacy aliases for backward compatibility
|
|
49
|
+
export const fragCoord = position
|
|
50
|
+
export const vertexId = vertexIndex
|
|
51
|
+
|
|
35
52
|
// Type constructors
|
|
36
|
-
export const float = (x: X) =>
|
|
37
|
-
export const int = (x: X) =>
|
|
38
|
-
export const uint = (x: X) =>
|
|
39
|
-
export const bool = (x: X) =>
|
|
40
|
-
export const vec2 = (x?: X, y?: X) =>
|
|
41
|
-
export const vec3 = (x?: X, y?: X, z?: X) =>
|
|
42
|
-
export const vec4 = (x?: X, y?: X, z?: X, w?: X) =>
|
|
43
|
-
export const mat2 = (...args: X[]) =>
|
|
44
|
-
export const mat3 = (...args: X[]) =>
|
|
45
|
-
export const mat4 = (...args: X[]) =>
|
|
46
|
-
export const ivec2 = (x?: X, y?: X) =>
|
|
47
|
-
export const ivec3 = (x?: X, y?: X, z?: X) =>
|
|
48
|
-
export const ivec4 = (x?: X, y?: X, z?: X, w?: X) =>
|
|
49
|
-
export const uvec2 = (x?: X, y?: X) =>
|
|
50
|
-
export const uvec3 = (x?: X, y?: X, z?: X) =>
|
|
51
|
-
export const uvec4 = (x?: X, y?: X, z?: X, w?: X) =>
|
|
52
|
-
export const bvec2 = (x?: X, y?: X) =>
|
|
53
|
-
export const bvec3 = (x?: X, y?: X, z?: X) =>
|
|
54
|
-
export const bvec4 = (x?: X, y?: X, z?: X, w?: X) =>
|
|
53
|
+
export const float = (x: X) => c('float', x)
|
|
54
|
+
export const int = (x: X) => c('int', x)
|
|
55
|
+
export const uint = (x: X) => c('uint', x)
|
|
56
|
+
export const bool = (x: X) => c('bool', x)
|
|
57
|
+
export const vec2 = (x?: X, y?: X) => c('vec2', x, y)
|
|
58
|
+
export const vec3 = (x?: X, y?: X, z?: X) => c('vec3', x, y, z)
|
|
59
|
+
export const vec4 = (x?: X, y?: X, z?: X, w?: X) => c('vec4', x, y, z, w)
|
|
60
|
+
export const mat2 = (...args: X[]) => c('mat2', ...args)
|
|
61
|
+
export const mat3 = (...args: X[]) => c('mat3', ...args)
|
|
62
|
+
export const mat4 = (...args: X[]) => c('mat4', ...args)
|
|
63
|
+
export const ivec2 = (x?: X, y?: X) => c('ivec2', x, y)
|
|
64
|
+
export const ivec3 = (x?: X, y?: X, z?: X) => c('ivec3', x, y, z)
|
|
65
|
+
export const ivec4 = (x?: X, y?: X, z?: X, w?: X) => c('ivec4', x, y, z, w)
|
|
66
|
+
export const uvec2 = (x?: X, y?: X) => c('uvec2', x, y)
|
|
67
|
+
export const uvec3 = (x?: X, y?: X, z?: X) => c('uvec3', x, y, z)
|
|
68
|
+
export const uvec4 = (x?: X, y?: X, z?: X, w?: X) => c('uvec4', x, y, z, w)
|
|
69
|
+
export const bvec2 = (x?: X, y?: X) => c('bvec2', x, y)
|
|
70
|
+
export const bvec3 = (x?: X, y?: X, z?: X) => c('bvec3', x, y, z)
|
|
71
|
+
export const bvec4 = (x?: X, y?: X, z?: X, w?: X) => c('bvec4', x, y, z, w)
|
|
55
72
|
export const color = (r?: X, g?: X, b?: X) => {
|
|
56
73
|
if (is.num(r) && is.und(g) && is.und(b)) return vec3(...hex2rgb(r))
|
|
57
74
|
return vec3(r, g, b)
|
package/src/node/infer.ts
CHANGED
|
@@ -14,11 +14,11 @@ import {
|
|
|
14
14
|
COMPONENT_COUNT_TO_TYPE,
|
|
15
15
|
BUILTIN_TYPES,
|
|
16
16
|
} from './const'
|
|
17
|
-
import type { Constants, NodeConfig, X } from './types'
|
|
17
|
+
import type { Constants, NodeConfig, NodeProxy, X } from './types'
|
|
18
18
|
|
|
19
19
|
const inferPrimitiveType = (x: any): Constants => {
|
|
20
20
|
if (is.bol(x)) return 'bool'
|
|
21
|
-
if (is.num(x)) return Number.isInteger(x) ? 'int' : 'float'
|
|
21
|
+
if (is.num(x)) return 'float' // Number.isInteger(x) ? 'int' : 'float' // @TODO FIX
|
|
22
22
|
if (is.arr(x)) return COMPONENT_COUNT_TO_TYPE[x.length as keyof typeof COMPONENT_COUNT_TO_TYPE] || 'float'
|
|
23
23
|
return 'float'
|
|
24
24
|
}
|
|
@@ -34,40 +34,38 @@ const inferBinaryOpType = (leftType: string, rightType: string, op: string): Con
|
|
|
34
34
|
return (leftPriority >= rightPriority ? leftType : rightType) as Constants
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
-
const getHighestPriorityType = (args: X[]) => {
|
|
37
|
+
const getHighestPriorityType = (args: X[], c: NodeConfig) => {
|
|
38
38
|
return args.reduce((highest, current) => {
|
|
39
|
-
const currentType = infer(current)
|
|
39
|
+
const currentType = infer(current, c)
|
|
40
40
|
const highestPriority = CONSTANTS.indexOf(highest as any)
|
|
41
41
|
const currentPriority = CONSTANTS.indexOf(currentType as any)
|
|
42
42
|
return currentPriority > highestPriority ? currentType : highest
|
|
43
|
-
}, 'float')
|
|
43
|
+
}, 'float') as Constants
|
|
44
44
|
}
|
|
45
|
+
|
|
45
46
|
const inferSwizzleType = (count: number): Constants => {
|
|
46
|
-
return COMPONENT_COUNT_TO_TYPE[count as keyof typeof COMPONENT_COUNT_TO_TYPE]
|
|
47
|
+
return COMPONENT_COUNT_TO_TYPE[count as keyof typeof COMPONENT_COUNT_TO_TYPE]!
|
|
47
48
|
}
|
|
48
49
|
|
|
49
50
|
const inferBuiltinType = (id: string | undefined): Constants => {
|
|
50
|
-
if (!id) return 'vec3'
|
|
51
51
|
return BUILTIN_TYPES[id as keyof typeof BUILTIN_TYPES]!
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
-
const inferMathType = (funcName: string, args: X[]): Constants => {
|
|
55
|
-
const firstArgType = args.length > 0 ? infer(args[0]) : 'float'
|
|
56
|
-
if (FIRST_ARG_TYPE_FUNCTIONS.includes(funcName as any)) return firstArgType
|
|
54
|
+
const inferMathType = (funcName: string, args: X[], c: NodeConfig): Constants => {
|
|
55
|
+
const firstArgType = args.length > 0 ? infer(args[0], c) : 'float'
|
|
56
|
+
if (FIRST_ARG_TYPE_FUNCTIONS.includes(funcName as any)) return firstArgType
|
|
57
57
|
if (SCALAR_RETURN_FUNCTIONS.includes(funcName as any)) return 'float'
|
|
58
58
|
if (BOOL_RETURN_FUNCTIONS.includes(funcName as any)) return 'bool'
|
|
59
|
-
if (PRESERVE_TYPE_FUNCTIONS.includes(funcName as any)) return firstArgType
|
|
59
|
+
if (PRESERVE_TYPE_FUNCTIONS.includes(funcName as any)) return firstArgType
|
|
60
60
|
if (VEC3_RETURN_FUNCTIONS.includes(funcName as any)) return 'vec3'
|
|
61
61
|
if (VEC4_RETURN_FUNCTIONS.includes(funcName as any)) return 'vec4'
|
|
62
|
-
if (HIGHEST_TYPE_FUNCTIONS.includes(funcName as any)) return getHighestPriorityType(args)
|
|
63
|
-
return firstArgType
|
|
62
|
+
if (HIGHEST_TYPE_FUNCTIONS.includes(funcName as any)) return getHighestPriorityType(args, c)
|
|
63
|
+
return firstArgType
|
|
64
64
|
}
|
|
65
65
|
|
|
66
|
-
export const
|
|
67
|
-
if (!target) throw ``
|
|
68
|
-
if (!isNodeProxy(target)) return inferPrimitiveType(target)
|
|
66
|
+
export const inferImpl = (target: NodeProxy, c: NodeConfig): Constants => {
|
|
69
67
|
const { type, props } = target
|
|
70
|
-
const { id, children = [], value
|
|
68
|
+
const { id, children = [], value } = props
|
|
71
69
|
const [x, y, z] = children
|
|
72
70
|
if (
|
|
73
71
|
type === 'uniform' ||
|
|
@@ -77,17 +75,22 @@ export const infer = (target: X, c?: NodeConfig): Constants => {
|
|
|
77
75
|
type === 'varying'
|
|
78
76
|
)
|
|
79
77
|
return inferPrimitiveType(value)
|
|
80
|
-
if (type === '
|
|
78
|
+
if (type === 'conversion') return x as Constants
|
|
81
79
|
if (type === 'operator') return inferBinaryOpType(infer(y, c), infer(z, c), x as string)
|
|
82
|
-
if (type === '
|
|
80
|
+
if (type === 'function') return inferMathType(x as string, children.slice(1), c)
|
|
83
81
|
if (type === 'swizzle') return inferSwizzleType((x as string).length)
|
|
84
82
|
if (type === 'ternary') return inferBinaryOpType(infer(y, c), infer(z, c), 'add')
|
|
85
|
-
if (type === '
|
|
86
|
-
if (type === 'fn_def') return returnType!
|
|
83
|
+
if (type === 'define') return y ? infer(y, c) : 'void'
|
|
87
84
|
if (type === 'builtin') return inferBuiltinType(id)
|
|
88
85
|
return 'float'
|
|
89
86
|
}
|
|
90
87
|
|
|
91
|
-
export const
|
|
92
|
-
|
|
88
|
+
export const infer = (target: X, c: NodeConfig | null): Constants => {
|
|
89
|
+
if (!c) c = {}
|
|
90
|
+
if (!isNodeProxy(target)) return inferPrimitiveType(target)
|
|
91
|
+
if (!c.infers) c.infers = new WeakMap<NodeProxy, Constants>()
|
|
92
|
+
if (c.infers.has(target)) return c.infers.get(target)!
|
|
93
|
+
const ret = inferImpl(target, c)
|
|
94
|
+
c.infers.set(target, ret)
|
|
95
|
+
return ret
|
|
93
96
|
}
|
package/src/node/node.ts
CHANGED
|
@@ -1,51 +1,42 @@
|
|
|
1
1
|
import { code } from './code'
|
|
2
|
-
import { assign, toVar
|
|
2
|
+
import { assign, toVar } from './scope'
|
|
3
3
|
import { getId, isConversion, isFunction, isOperator, isSwizzle } from './utils'
|
|
4
4
|
import type { Functions, NodeProps, NodeProxy, NodeTypes, Operators, Swizzles, X } from './types'
|
|
5
5
|
|
|
6
|
-
const toPrimitive = (x: X) => {
|
|
7
|
-
|
|
8
|
-
if (hint === 'string') return code(x)
|
|
9
|
-
}
|
|
6
|
+
const toPrimitive = (x: X, hint: string) => {
|
|
7
|
+
if (hint === 'string') return code(x)
|
|
10
8
|
}
|
|
11
9
|
|
|
12
10
|
export const node = (type: NodeTypes, props?: NodeProps | null, ...args: X[]) => {
|
|
13
11
|
if (!props) props = {}
|
|
14
12
|
if (args.length) props.children = args
|
|
15
|
-
const
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
},
|
|
37
|
-
}) as unknown as NodeProxy
|
|
13
|
+
const get = (_: unknown, key: string | Symbol) => {
|
|
14
|
+
if (key === 'type') return type
|
|
15
|
+
if (key === 'props') return props
|
|
16
|
+
if (key === 'toVar') return toVar.bind(null, x)
|
|
17
|
+
if (key === 'assign') return assign.bind(null, x)
|
|
18
|
+
if (key === 'isProxy') return true
|
|
19
|
+
if (key === 'toString') return code.bind(null, x)
|
|
20
|
+
if (key === Symbol.toPrimitive) return toPrimitive.bind(null, x)
|
|
21
|
+
if (isSwizzle(key)) return swizzle(key, x)
|
|
22
|
+
if (isOperator(key)) return (...y: X[]) => operator(key, x, ...y)
|
|
23
|
+
if (isFunction(key)) return (...y: X[]) => function_(key, x, ...y)
|
|
24
|
+
if (isConversion(key)) return conversion(key, x)
|
|
25
|
+
}
|
|
26
|
+
const set = (_: unknown, key: string, value: X) => {
|
|
27
|
+
if (isSwizzle(key)) {
|
|
28
|
+
swizzle(key, x).assign(value)
|
|
29
|
+
return true
|
|
30
|
+
}
|
|
31
|
+
return false
|
|
32
|
+
}
|
|
33
|
+
const x = new Proxy({}, { get, set }) as unknown as NodeProxy
|
|
38
34
|
return x
|
|
39
35
|
}
|
|
40
36
|
|
|
41
37
|
// Node shorthands
|
|
42
|
-
export const
|
|
43
|
-
export const
|
|
44
|
-
export const
|
|
45
|
-
export const
|
|
46
|
-
export const
|
|
47
|
-
|
|
48
|
-
// uniform and attribute
|
|
49
|
-
export const u = (id: string, value?: number | number[] | boolean) => node('uniform', { id, value })
|
|
50
|
-
|
|
51
|
-
export const select = (x: X, y: X, z: X) => node('ternary', null, x, y, z)
|
|
38
|
+
export const variable = (...args: X[]) => node('variable', { id: getId() }, ...args)
|
|
39
|
+
export const swizzle = (key: Swizzles, arg: X) => node('swizzle', null, key, arg)
|
|
40
|
+
export const operator = (key: Operators, ...args: X[]) => node('operator', null, key, ...args)
|
|
41
|
+
export const function_ = (key: Functions, ...args: X[]) => node('function', null, key, ...args)
|
|
42
|
+
export const conversion = (key: string, ...args: X[]) => node('conversion', null, key, ...args)
|
package/src/node/scope.ts
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
|
-
import { infer } from './infer'
|
|
2
1
|
import { node } from './node'
|
|
3
2
|
import { getId } from './utils'
|
|
4
3
|
import type { NodeProxy, X } from './types'
|
|
5
4
|
|
|
6
5
|
let _scope: NodeProxy | null = null
|
|
7
6
|
|
|
8
|
-
const scoped = (x: NodeProxy | null,
|
|
7
|
+
const scoped = (x: NodeProxy | null, fun = () => {}) => {
|
|
9
8
|
const prev = _scope
|
|
10
9
|
_scope = x
|
|
11
|
-
|
|
10
|
+
fun()
|
|
12
11
|
_scope = prev
|
|
13
12
|
}
|
|
14
13
|
|
|
@@ -18,30 +17,44 @@ const addToScope = (x: NodeProxy) => {
|
|
|
18
17
|
_scope.props.children.push(x)
|
|
19
18
|
}
|
|
20
19
|
|
|
21
|
-
export const
|
|
20
|
+
export const toVar = (x: X, id?: string) => {
|
|
21
|
+
if (!id) id = getId()
|
|
22
|
+
const y = node('variable', { id })
|
|
23
|
+
const z = node('declare', null, y, x)
|
|
24
|
+
addToScope(z)
|
|
25
|
+
return y
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export const assign = (x: X, y: X) => {
|
|
29
|
+
const z = node('assign', null, x, y)
|
|
30
|
+
addToScope(z)
|
|
31
|
+
return x
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export const If = (condition: X, fun: () => void) => {
|
|
22
35
|
const scope = node('scope')
|
|
23
|
-
scoped(scope,
|
|
36
|
+
scoped(scope, fun)
|
|
24
37
|
const ifNode = node('if', null, condition, scope)
|
|
25
38
|
addToScope(ifNode)
|
|
26
39
|
const createChain = () => ({
|
|
27
|
-
ElseIf: (
|
|
28
|
-
const
|
|
29
|
-
scoped(
|
|
30
|
-
ifNode.props.children!.push(
|
|
40
|
+
ElseIf: (x: X, _fun: () => void) => {
|
|
41
|
+
const y = node('scope')
|
|
42
|
+
scoped(y, _fun)
|
|
43
|
+
ifNode.props.children!.push(x, y)
|
|
31
44
|
return createChain()
|
|
32
45
|
},
|
|
33
|
-
Else: (
|
|
34
|
-
const
|
|
35
|
-
scoped(
|
|
36
|
-
ifNode.props.children!.push(
|
|
46
|
+
Else: (_fun: () => void) => {
|
|
47
|
+
const x = node('scope')
|
|
48
|
+
scoped(x, _fun)
|
|
49
|
+
ifNode.props.children!.push(x)
|
|
37
50
|
},
|
|
38
51
|
})
|
|
39
52
|
return createChain()
|
|
40
53
|
}
|
|
41
54
|
|
|
42
|
-
export const Loop = (x: X,
|
|
55
|
+
export const Loop = (x: X, fun: (params: { i?: NodeProxy }) => void) => {
|
|
43
56
|
const y = node('scope')
|
|
44
|
-
scoped(y, () =>
|
|
57
|
+
scoped(y, () => fun({ i: node('variable', { id: 'i' }) }))
|
|
45
58
|
const ret = node('loop', null, x, y)
|
|
46
59
|
addToScope(ret)
|
|
47
60
|
return ret
|
|
@@ -52,28 +65,29 @@ export const Switch = (value: X) => {
|
|
|
52
65
|
addToScope(switchNode)
|
|
53
66
|
const createChain = () => ({
|
|
54
67
|
Case: (...values: X[]) => {
|
|
55
|
-
return (
|
|
56
|
-
const
|
|
57
|
-
scoped(
|
|
58
|
-
|
|
59
|
-
|
|
68
|
+
return (fun: () => void) => {
|
|
69
|
+
const scope = node('scope')
|
|
70
|
+
scoped(scope, fun)
|
|
71
|
+
// 複数のcase値を処理
|
|
72
|
+
for (const val of values) {
|
|
73
|
+
switchNode.props.children!.push(val, scope)
|
|
74
|
+
}
|
|
60
75
|
return createChain()
|
|
61
76
|
}
|
|
62
77
|
},
|
|
63
|
-
Default: (
|
|
64
|
-
const
|
|
65
|
-
scoped(
|
|
66
|
-
|
|
67
|
-
switchNode.props.children!.push(defaultNode)
|
|
78
|
+
Default: (fun: () => void) => {
|
|
79
|
+
const scope = node('scope')
|
|
80
|
+
scoped(scope, fun)
|
|
81
|
+
switchNode.props.children!.push(scope)
|
|
68
82
|
},
|
|
69
83
|
})
|
|
70
84
|
|
|
71
85
|
return createChain()
|
|
72
86
|
}
|
|
73
87
|
|
|
74
|
-
export const Fn = (
|
|
88
|
+
export const Fn = (fun: (paramVars: NodeProxy[]) => NodeProxy) => {
|
|
75
89
|
const id = getId()
|
|
76
|
-
return (...args:
|
|
90
|
+
return (...args: X[]) => {
|
|
77
91
|
const x = node('scope')
|
|
78
92
|
let y: NodeProxy | undefined
|
|
79
93
|
const paramVars: NodeProxy[] = []
|
|
@@ -82,40 +96,7 @@ export const Fn = (callback: (args: NodeProxy[]) => NodeProxy) => {
|
|
|
82
96
|
const paramVar = node('variable', { id: paramId })
|
|
83
97
|
paramVars.push(paramVar)
|
|
84
98
|
}
|
|
85
|
-
scoped(x, () => (y =
|
|
86
|
-
|
|
87
|
-
const paramInfo = args.map((arg, i) => ({ name: `p${i}`, type: infer(arg) }))
|
|
88
|
-
const def = node('fn_def', { id, returnType, paramInfo, args }, x, y)
|
|
89
|
-
return node('fn_run', { id, returnType }, def, ...paramVars)
|
|
99
|
+
scoped(x, () => (y = fun(paramVars)))
|
|
100
|
+
return node('define', { id }, x, y, ...args)
|
|
90
101
|
}
|
|
91
102
|
}
|
|
92
|
-
|
|
93
|
-
export const toVar = (x: X) => (id?: string) => {
|
|
94
|
-
if (!id) id = getId()
|
|
95
|
-
const y = node('variable', { id })
|
|
96
|
-
const z = node('declare', null, y, x)
|
|
97
|
-
addToScope(z)
|
|
98
|
-
return y
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
export const toConst = (x: X) => (id?: string) => {
|
|
102
|
-
if (!id) id = getId()
|
|
103
|
-
const y = node('constant', { id })
|
|
104
|
-
const z = node('declare', null, y, x)
|
|
105
|
-
addToScope(z)
|
|
106
|
-
return y
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
export const assign = (x: X) => (y: X) => {
|
|
110
|
-
const assignNode = node('assign', null, x, y)
|
|
111
|
-
addToScope(assignNode)
|
|
112
|
-
return x
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
export const varying = (value: X, name?: string) => {
|
|
116
|
-
if (!name) name = getId()
|
|
117
|
-
const varyingVar = node('varying', { id: name })
|
|
118
|
-
const declaration = node('declare', null, varyingVar, value)
|
|
119
|
-
addToScope(declaration)
|
|
120
|
-
return varyingVar
|
|
121
|
-
}
|