glre 0.29.0 → 0.31.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 +34 -34
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +62 -30
- package/dist/index.js +35 -35
- package/dist/index.js.map +1 -1
- package/dist/native.cjs +34 -34
- package/dist/native.cjs.map +1 -1
- package/dist/native.d.cts +1 -2
- package/dist/native.js +35 -35
- package/dist/native.js.map +1 -1
- package/dist/react.cjs +34 -34
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +1 -2
- package/dist/react.js +35 -35
- package/dist/react.js.map +1 -1
- package/dist/solid.cjs +34 -34
- package/dist/solid.cjs.map +1 -1
- package/dist/solid.d.cts +1 -2
- package/dist/solid.js +35 -35
- package/dist/solid.js.map +1 -1
- package/package.json +23 -23
- package/src/node/code.ts +36 -25
- package/src/node/const.ts +19 -18
- package/src/node/index.ts +22 -36
- package/src/node/infer.ts +46 -50
- package/src/node/node.ts +15 -5
- package/src/node/scope.ts +48 -39
- package/src/node/types.ts +45 -13
- package/src/node/utils.ts +77 -27
package/src/node/code.ts
CHANGED
|
@@ -1,20 +1,30 @@
|
|
|
1
1
|
import { is } from '../utils/helpers'
|
|
2
2
|
import { infer } from './infer'
|
|
3
|
-
import {
|
|
4
|
-
import { WGSL_TO_GLSL_BUILTIN } from './const'
|
|
3
|
+
import { getBluiltin, getOperator, generateDefine, formatConversions, joins } from './utils'
|
|
5
4
|
import type { NodeConfig, X } from './types'
|
|
6
5
|
|
|
7
6
|
export const code = (target: X, c?: NodeConfig | null): string => {
|
|
8
7
|
if (!c) c = {}
|
|
9
8
|
if (!c.headers) c.headers = new Map()
|
|
10
9
|
if (is.str(target)) return target
|
|
11
|
-
if (is.num(target))
|
|
10
|
+
if (is.num(target)) {
|
|
11
|
+
const ret = `${target}`
|
|
12
|
+
if (ret.includes('.')) return ret
|
|
13
|
+
return ret + '.0'
|
|
14
|
+
}
|
|
12
15
|
if (is.bol(target)) return target ? 'true' : 'false'
|
|
13
16
|
if (!target) return '' // ignore if no target
|
|
14
17
|
const { type, props } = target
|
|
15
18
|
const { id = '', children = [] } = props
|
|
16
19
|
const [x, y, z] = children
|
|
20
|
+
/**
|
|
21
|
+
* headers
|
|
22
|
+
*/
|
|
17
23
|
let head = ''
|
|
24
|
+
if (type === 'attribute') {
|
|
25
|
+
if (c.headers.has(id)) return id
|
|
26
|
+
head = `${infer(target, c)} ${id}`
|
|
27
|
+
}
|
|
18
28
|
if (type === 'uniform') {
|
|
19
29
|
if (c.headers.has(id)) return id
|
|
20
30
|
if (!c.binding) c.binding = 0
|
|
@@ -23,13 +33,13 @@ export const code = (target: X, c?: NodeConfig | null): string => {
|
|
|
23
33
|
? `uniform ${varType} ${id};`
|
|
24
34
|
: `@group(0) @binding(${c.binding++}) var<uniform> ${id}: ${formatConversions(varType, c)};`
|
|
25
35
|
}
|
|
26
|
-
if (type === 'attribute') {
|
|
27
|
-
if (c.headers.has(id)) return id
|
|
28
|
-
head = `${infer(target, c)} ${id}`
|
|
29
|
-
}
|
|
30
36
|
if (type === 'constant') {
|
|
31
37
|
if (c.headers.has(id)) return id
|
|
32
|
-
|
|
38
|
+
const varType = infer(target, c)
|
|
39
|
+
const value = code(x, c)
|
|
40
|
+
head = c.isWebGL
|
|
41
|
+
? `const ${varType} ${id} = ${value};`
|
|
42
|
+
: `const ${id}: ${formatConversions(varType, c)} = ${value};`
|
|
33
43
|
}
|
|
34
44
|
if (type === 'varying') {
|
|
35
45
|
if (c.headers.has(id)) return id
|
|
@@ -37,23 +47,34 @@ export const code = (target: X, c?: NodeConfig | null): string => {
|
|
|
37
47
|
}
|
|
38
48
|
if (head) {
|
|
39
49
|
c.headers.set(id, head)
|
|
40
|
-
c.onMount?.(id
|
|
50
|
+
c.onMount?.(id)
|
|
41
51
|
return id
|
|
42
52
|
}
|
|
53
|
+
/**
|
|
54
|
+
* variables
|
|
55
|
+
*/
|
|
43
56
|
if (type === 'variable') return id
|
|
44
57
|
if (type === 'swizzle') return `${code(y, c)}.${code(x, c)}`
|
|
58
|
+
if (type === 'ternary') return `(${code(x, c)} ? ${code(y, c)} : ${code(z, c)})`
|
|
59
|
+
if (type === 'builtin') return c?.isWebGL ? getBluiltin(id) : id
|
|
60
|
+
if (type === 'conversion') return `${formatConversions(x, c)}(${joins(children.slice(1), c)})`
|
|
45
61
|
if (type === 'operator') {
|
|
46
62
|
if (x === 'not' || x === 'bitNot') return `!${code(y, c)}`
|
|
47
63
|
return `(${code(y, c)} ${getOperator(x)} ${code(z, c)})`
|
|
48
64
|
}
|
|
49
65
|
if (type === 'function') {
|
|
50
|
-
// Handle special functions that need to be converted to operators
|
|
51
66
|
if (x === 'negate') return `(-${joins(children.slice(1), c)})`
|
|
52
67
|
return `${x}(${joins(children.slice(1), c)})`
|
|
53
68
|
}
|
|
54
|
-
|
|
69
|
+
/**
|
|
70
|
+
* scopes
|
|
71
|
+
*/
|
|
55
72
|
if (type === 'scope') return children.map((child: any) => code(child, c)).join('\n')
|
|
56
73
|
if (type === 'assign') return `${code(x, c)} = ${code(y, c)};`
|
|
74
|
+
if (type === 'loop')
|
|
75
|
+
return c.isWebGL
|
|
76
|
+
? `for (int i = 0; i < ${x}; i += 1) {\n${code(y, c)}\n}`
|
|
77
|
+
: `for (var i: i32 = 0; i < ${x}; i++) {\n${code(y, c)}\n}`
|
|
57
78
|
if (type === 'define') {
|
|
58
79
|
const args = children.slice(2)
|
|
59
80
|
const ret = `${id}(${args.map((arg) => code(arg, c))})`
|
|
@@ -61,7 +82,6 @@ export const code = (target: X, c?: NodeConfig | null): string => {
|
|
|
61
82
|
c.headers.set(id, generateDefine(props, c))
|
|
62
83
|
return ret
|
|
63
84
|
}
|
|
64
|
-
if (type === 'loop') return `for (int i = 0; i < ${x}; i++) {\n${code(y, c)}\n}`
|
|
65
85
|
if (type === 'if') {
|
|
66
86
|
let ret = `if (${code(x, c)}) {\n${code(y, c)}\n}`
|
|
67
87
|
for (let i = 2; i < children.length; i += 2) {
|
|
@@ -84,21 +104,12 @@ export const code = (target: X, c?: NodeConfig | null): string => {
|
|
|
84
104
|
ret += '}'
|
|
85
105
|
return ret
|
|
86
106
|
}
|
|
87
|
-
if (type === 'ternary') return `(${code(x, c)} ? ${code(y, c)} : ${code(z, c)})`
|
|
88
107
|
if (type === 'declare') {
|
|
89
|
-
const varType = infer(
|
|
90
|
-
const varName = (
|
|
91
|
-
if (c.isWebGL) return `${varType} ${varName} = ${code(
|
|
108
|
+
const varType = infer(x, c)
|
|
109
|
+
const varName = (y as any)?.props?.id
|
|
110
|
+
if (c.isWebGL) return `${varType} ${varName} = ${code(x, c)};`
|
|
92
111
|
const wgslType = formatConversions(varType)
|
|
93
|
-
return `var ${varName}: ${wgslType} = ${code(
|
|
94
|
-
}
|
|
95
|
-
if (type === 'builtin') {
|
|
96
|
-
if (c?.isWebGL) {
|
|
97
|
-
const glslBuiltin = WGSL_TO_GLSL_BUILTIN[id as keyof typeof WGSL_TO_GLSL_BUILTIN]
|
|
98
|
-
if (glslBuiltin) return glslBuiltin
|
|
99
|
-
if (id === 'uv') return 'gl_FragCoord.xy'
|
|
100
|
-
}
|
|
101
|
-
return id
|
|
112
|
+
return `var ${varName}: ${wgslType} = ${code(x, c)};`
|
|
102
113
|
}
|
|
103
114
|
return code(x, c)
|
|
104
115
|
}
|
package/src/node/const.ts
CHANGED
|
@@ -6,16 +6,16 @@ export const CONSTANTS = [
|
|
|
6
6
|
'int',
|
|
7
7
|
'float',
|
|
8
8
|
'bvec2',
|
|
9
|
-
'bvec3',
|
|
10
|
-
'bvec4',
|
|
11
9
|
'ivec2',
|
|
12
|
-
'ivec3',
|
|
13
|
-
'ivec4',
|
|
14
10
|
'uvec2',
|
|
15
|
-
'uvec3',
|
|
16
|
-
'uvec4',
|
|
17
11
|
'vec2',
|
|
12
|
+
'bvec3',
|
|
13
|
+
'ivec3',
|
|
14
|
+
'uvec3',
|
|
18
15
|
'vec3',
|
|
16
|
+
'bvec4',
|
|
17
|
+
'ivec4',
|
|
18
|
+
'uvec4',
|
|
19
19
|
'vec4',
|
|
20
20
|
'color',
|
|
21
21
|
'mat2',
|
|
@@ -24,26 +24,26 @@ export const CONSTANTS = [
|
|
|
24
24
|
] as const
|
|
25
25
|
|
|
26
26
|
export const CONVERSIONS = [
|
|
27
|
-
'toFloat',
|
|
28
|
-
'toInt',
|
|
29
|
-
'toUint',
|
|
30
27
|
'toBool',
|
|
31
|
-
'
|
|
32
|
-
'
|
|
33
|
-
'
|
|
28
|
+
'toUint',
|
|
29
|
+
'toInt',
|
|
30
|
+
'toFloat',
|
|
31
|
+
'toBvec2',
|
|
34
32
|
'toIvec2',
|
|
35
|
-
'toIvec3',
|
|
36
|
-
'toIvec4',
|
|
37
33
|
'toUvec2',
|
|
38
|
-
'
|
|
39
|
-
'toUvec4',
|
|
40
|
-
'toBvec2',
|
|
34
|
+
'toVec2',
|
|
41
35
|
'toBvec3',
|
|
36
|
+
'toIvec3',
|
|
37
|
+
'toUvec3',
|
|
38
|
+
'toVec3',
|
|
42
39
|
'toBvec4',
|
|
40
|
+
'toIvec4',
|
|
41
|
+
'toUvec4',
|
|
42
|
+
'toVec4',
|
|
43
|
+
'toColor',
|
|
43
44
|
'toMat2',
|
|
44
45
|
'toMat3',
|
|
45
46
|
'toMat4',
|
|
46
|
-
'toColor',
|
|
47
47
|
] as const
|
|
48
48
|
|
|
49
49
|
export const OPERATORS = {
|
|
@@ -226,4 +226,5 @@ export const WGSL_TO_GLSL_BUILTIN = {
|
|
|
226
226
|
sample_index: 'gl_SampleID',
|
|
227
227
|
sample_mask: 'gl_SampleMask',
|
|
228
228
|
point_coord: 'gl_PointCoord',
|
|
229
|
+
uv: 'gl_FragCoord.xy',
|
|
229
230
|
} as const
|
package/src/node/index.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { conversion as c, function_ as f,
|
|
1
|
+
import { builtin, conversion as c, function_ as f, uniform } from './node'
|
|
2
2
|
import { hex2rgb } from './utils'
|
|
3
3
|
import { is } from '../utils/helpers'
|
|
4
4
|
import type { X } from './types'
|
|
@@ -10,44 +10,25 @@ 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
|
-
|
|
23
|
-
// Default uniforms
|
|
24
|
-
export const iResolution = uniform([1280, 800], 'iResolution')
|
|
25
|
-
export const iMouse = uniform([0, 0], 'iMouse')
|
|
26
|
-
export const iTime = uniform(0, 'iTime')
|
|
27
|
-
|
|
28
13
|
// Builtin Variables
|
|
29
|
-
export const position =
|
|
30
|
-
export const vertexIndex =
|
|
31
|
-
export const instanceIndex =
|
|
32
|
-
export const frontFacing =
|
|
33
|
-
export const fragDepth =
|
|
34
|
-
export const sampleIndex =
|
|
35
|
-
export const sampleMask =
|
|
36
|
-
export const pointCoord =
|
|
14
|
+
export const position = builtin('position')
|
|
15
|
+
export const vertexIndex = builtin('vertex_index')
|
|
16
|
+
export const instanceIndex = builtin('instance_index')
|
|
17
|
+
export const frontFacing = builtin('front_facing')
|
|
18
|
+
export const fragDepth = builtin('frag_depth')
|
|
19
|
+
export const sampleIndex = builtin('sample_index')
|
|
20
|
+
export const sampleMask = builtin('sample_mask')
|
|
21
|
+
export const pointCoord = builtin('point_coord')
|
|
37
22
|
|
|
38
23
|
// TSL Compatible Builtin Variables
|
|
39
|
-
export const
|
|
40
|
-
export const
|
|
41
|
-
export const
|
|
42
|
-
export const
|
|
43
|
-
export const
|
|
44
|
-
export const
|
|
45
|
-
export const screenCoordinate =
|
|
46
|
-
export const screenUV =
|
|
47
|
-
|
|
48
|
-
// Legacy aliases for backward compatibility
|
|
49
|
-
export const fragCoord = position
|
|
50
|
-
export const vertexId = vertexIndex
|
|
24
|
+
export const normalLocal = builtin('normalLocal')
|
|
25
|
+
export const normalWorld = builtin('normalWorld')
|
|
26
|
+
export const normalView = builtin('normalView')
|
|
27
|
+
export const positionLocal = builtin('position')
|
|
28
|
+
export const positionWorld = builtin('positionWorld')
|
|
29
|
+
export const positionView = builtin('positionView')
|
|
30
|
+
export const screenCoordinate = builtin('screenCoordinate')
|
|
31
|
+
export const screenUV = builtin('screenUV')
|
|
51
32
|
|
|
52
33
|
// Type constructors
|
|
53
34
|
export const float = (x: X) => c('float', x)
|
|
@@ -74,6 +55,11 @@ export const color = (r?: X, g?: X, b?: X) => {
|
|
|
74
55
|
return vec3(r, g, b)
|
|
75
56
|
}
|
|
76
57
|
|
|
58
|
+
// Default uniforms
|
|
59
|
+
export const iResolution = uniform(vec2(1280, 800), 'iResolution')
|
|
60
|
+
export const iMouse = uniform(vec2(0, 0), 'iMouse')
|
|
61
|
+
export const iTime = uniform(float(0), 'iTime')
|
|
62
|
+
|
|
77
63
|
// Texture Functions
|
|
78
64
|
export const texture = (x: X, y: X, z?: X) => f('texture', x, y, z)
|
|
79
65
|
export const cubeTexture = (x: X, y: X, z?: X) => f('cubeTexture', x, y, z)
|
package/src/node/infer.ts
CHANGED
|
@@ -1,39 +1,21 @@
|
|
|
1
1
|
import { is } from '../utils/helpers'
|
|
2
|
-
import { isNodeProxy } from './utils'
|
|
3
2
|
import {
|
|
4
|
-
CONSTANTS,
|
|
5
|
-
SCALAR_RETURN_FUNCTIONS,
|
|
6
3
|
BOOL_RETURN_FUNCTIONS,
|
|
7
|
-
|
|
8
|
-
|
|
4
|
+
BUILTIN_TYPES,
|
|
5
|
+
COMPARISON_OPERATORS,
|
|
6
|
+
COMPONENT_COUNT_TO_TYPE,
|
|
7
|
+
CONSTANTS,
|
|
9
8
|
FIRST_ARG_TYPE_FUNCTIONS,
|
|
10
9
|
HIGHEST_TYPE_FUNCTIONS,
|
|
11
|
-
VEC4_RETURN_FUNCTIONS,
|
|
12
|
-
COMPARISON_OPERATORS,
|
|
13
10
|
LOGICAL_OPERATORS,
|
|
14
|
-
|
|
15
|
-
|
|
11
|
+
PRESERVE_TYPE_FUNCTIONS,
|
|
12
|
+
SCALAR_RETURN_FUNCTIONS,
|
|
13
|
+
VEC3_RETURN_FUNCTIONS,
|
|
14
|
+
VEC4_RETURN_FUNCTIONS,
|
|
16
15
|
} from './const'
|
|
16
|
+
import { isNodeProxy } from './utils'
|
|
17
17
|
import type { Constants, NodeConfig, NodeProxy, X } from './types'
|
|
18
18
|
|
|
19
|
-
const inferPrimitiveType = (x: any): Constants => {
|
|
20
|
-
if (is.bol(x)) return 'bool'
|
|
21
|
-
if (is.num(x)) return 'float' // Number.isInteger(x) ? 'int' : 'float' // @TODO FIX
|
|
22
|
-
if (is.arr(x)) return COMPONENT_COUNT_TO_TYPE[x.length as keyof typeof COMPONENT_COUNT_TO_TYPE] || 'float'
|
|
23
|
-
return 'float'
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
const inferBinaryOpType = (leftType: string, rightType: string, op: string): Constants => {
|
|
27
|
-
if (COMPARISON_OPERATORS.includes(op as any)) return 'bool'
|
|
28
|
-
if (LOGICAL_OPERATORS.includes(op as any)) return 'bool'
|
|
29
|
-
if (leftType === rightType) return leftType as Constants
|
|
30
|
-
if (leftType.includes('vec') && !rightType.includes('vec')) return leftType as Constants
|
|
31
|
-
if (rightType.includes('vec') && !leftType.includes('vec')) return rightType as Constants
|
|
32
|
-
const leftPriority = CONSTANTS.indexOf(leftType as any)
|
|
33
|
-
const rightPriority = CONSTANTS.indexOf(rightType as any)
|
|
34
|
-
return (leftPriority >= rightPriority ? leftType : rightType) as Constants
|
|
35
|
-
}
|
|
36
|
-
|
|
37
19
|
const getHighestPriorityType = (args: X[], c: NodeConfig) => {
|
|
38
20
|
return args.reduce((highest, current) => {
|
|
39
21
|
const currentType = infer(current, c)
|
|
@@ -43,15 +25,11 @@ const getHighestPriorityType = (args: X[], c: NodeConfig) => {
|
|
|
43
25
|
}, 'float') as Constants
|
|
44
26
|
}
|
|
45
27
|
|
|
46
|
-
const
|
|
47
|
-
return COMPONENT_COUNT_TO_TYPE[count as keyof typeof COMPONENT_COUNT_TO_TYPE]!
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
const inferBuiltinType = (id: string | undefined): Constants => {
|
|
28
|
+
const inferBuiltin = (id: string | undefined): Constants => {
|
|
51
29
|
return BUILTIN_TYPES[id as keyof typeof BUILTIN_TYPES]!
|
|
52
30
|
}
|
|
53
31
|
|
|
54
|
-
const
|
|
32
|
+
const inferFunction = (funcName: string, args: X[], c: NodeConfig): Constants => {
|
|
55
33
|
const firstArgType = args.length > 0 ? infer(args[0], c) : 'float'
|
|
56
34
|
if (FIRST_ARG_TYPE_FUNCTIONS.includes(funcName as any)) return firstArgType
|
|
57
35
|
if (SCALAR_RETURN_FUNCTIONS.includes(funcName as any)) return 'float'
|
|
@@ -63,29 +41,47 @@ const inferMathType = (funcName: string, args: X[], c: NodeConfig): Constants =>
|
|
|
63
41
|
return firstArgType
|
|
64
42
|
}
|
|
65
43
|
|
|
44
|
+
const inferOperator = (leftType: string, rightType: string, op: string): Constants => {
|
|
45
|
+
if (COMPARISON_OPERATORS.includes(op as any)) return 'bool'
|
|
46
|
+
if (LOGICAL_OPERATORS.includes(op as any)) return 'bool'
|
|
47
|
+
if (leftType === rightType) return leftType as Constants
|
|
48
|
+
if (leftType.includes('vec') && !rightType.includes('vec')) return leftType as Constants
|
|
49
|
+
if (rightType.includes('vec') && !leftType.includes('vec')) return rightType as Constants
|
|
50
|
+
const leftPriority = CONSTANTS.indexOf(leftType as any)
|
|
51
|
+
const rightPriority = CONSTANTS.indexOf(rightType as any)
|
|
52
|
+
return (leftPriority >= rightPriority ? leftType : rightType) as Constants
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const inferPrimitiveType = (x: any): Constants => {
|
|
56
|
+
if (is.bol(x)) return 'bool'
|
|
57
|
+
if (is.num(x)) return 'float' // Number.isInteger(x) ? 'int' : 'float' // @TODO FIX
|
|
58
|
+
if (is.arr(x)) return COMPONENT_COUNT_TO_TYPE[x.length as keyof typeof COMPONENT_COUNT_TO_TYPE] || 'float'
|
|
59
|
+
return 'float'
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const inferSwizzle = (count: number): Constants => {
|
|
63
|
+
return COMPONENT_COUNT_TO_TYPE[count as keyof typeof COMPONENT_COUNT_TO_TYPE]!
|
|
64
|
+
}
|
|
65
|
+
|
|
66
66
|
export const inferImpl = (target: NodeProxy, c: NodeConfig): Constants => {
|
|
67
67
|
const { type, props } = target
|
|
68
|
-
const { id, children = [],
|
|
68
|
+
const { id, children = [], inferFrom } = props
|
|
69
69
|
const [x, y, z] = children
|
|
70
|
-
if (
|
|
71
|
-
type === 'uniform' ||
|
|
72
|
-
type === 'variable' ||
|
|
73
|
-
type === 'constant' ||
|
|
74
|
-
type === 'attribute' ||
|
|
75
|
-
type === 'varying'
|
|
76
|
-
)
|
|
77
|
-
return inferPrimitiveType(value)
|
|
70
|
+
if (inferFrom) return infer(inferFrom, c)
|
|
78
71
|
if (type === 'conversion') return x as Constants
|
|
79
|
-
if (type === 'operator') return
|
|
80
|
-
if (type === 'function') return
|
|
81
|
-
if (type === 'swizzle') return
|
|
82
|
-
if (type === 'ternary') return
|
|
83
|
-
if (type === '
|
|
84
|
-
if (type === '
|
|
85
|
-
|
|
72
|
+
if (type === 'operator') return inferOperator(infer(y, c), infer(z, c), x as string)
|
|
73
|
+
if (type === 'function') return inferFunction(x as string, children.slice(1), c)
|
|
74
|
+
if (type === 'swizzle') return inferSwizzle((x as string).length)
|
|
75
|
+
if (type === 'ternary') return inferOperator(infer(y, c), infer(z, c), 'add')
|
|
76
|
+
if (type === 'builtin') return inferBuiltin(id)
|
|
77
|
+
if (type === 'define') {
|
|
78
|
+
if (props.layout?.type && props.layout?.type !== 'auto') return props.layout.type as Constants
|
|
79
|
+
return y ? infer(y, c) : 'void'
|
|
80
|
+
}
|
|
81
|
+
return infer(x, c)
|
|
86
82
|
}
|
|
87
83
|
|
|
88
|
-
export const infer = (target: X, c
|
|
84
|
+
export const infer = (target: X, c?: NodeConfig | null): Constants => {
|
|
89
85
|
if (!c) c = {}
|
|
90
86
|
if (!isNodeProxy(target)) return inferPrimitiveType(target)
|
|
91
87
|
if (!c.infers) c.infers = new WeakMap<NodeProxy, Constants>()
|
package/src/node/node.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { code } from './code'
|
|
2
2
|
import { assign, toVar } from './scope'
|
|
3
|
-
import {
|
|
3
|
+
import { conversionToConstant, isConversion, isFunction, isOperator, isSwizzle } from './utils'
|
|
4
4
|
import type { Functions, NodeProps, NodeProxy, NodeTypes, Operators, Swizzles, X } from './types'
|
|
5
5
|
|
|
6
6
|
const toPrimitive = (x: X, hint: string) => {
|
|
@@ -21,11 +21,11 @@ export const node = (type: NodeTypes, props?: NodeProps | null, ...args: X[]) =>
|
|
|
21
21
|
if (isSwizzle(key)) return swizzle(key, x)
|
|
22
22
|
if (isOperator(key)) return (...y: X[]) => operator(key, x, ...y)
|
|
23
23
|
if (isFunction(key)) return (...y: X[]) => function_(key, x, ...y)
|
|
24
|
-
if (isConversion(key)) return conversion(key, x)
|
|
24
|
+
if (isConversion(key)) return () => conversion(conversionToConstant(key), x)
|
|
25
25
|
}
|
|
26
|
-
const set = (_: unknown, key: string,
|
|
26
|
+
const set = (_: unknown, key: string, y: X) => {
|
|
27
27
|
if (isSwizzle(key)) {
|
|
28
|
-
swizzle(key, x).assign(
|
|
28
|
+
swizzle(key, x).assign(y)
|
|
29
29
|
return true
|
|
30
30
|
}
|
|
31
31
|
return false
|
|
@@ -34,9 +34,19 @@ export const node = (type: NodeTypes, props?: NodeProps | null, ...args: X[]) =>
|
|
|
34
34
|
return x
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
+
// headers
|
|
38
|
+
export const attribute = (x: X, id?: string) => node('varying', { id }, x)
|
|
39
|
+
export const uniform = (x: X, id?: string) => node('uniform', { id }, x)
|
|
40
|
+
export const varying = (x: X, id?: string) => node('varying', { id }, x)
|
|
41
|
+
export const constant = (x: X, id?: string) => node('constant', { id }, x)
|
|
42
|
+
export const variable = (id: string) => node('variable', { id })
|
|
43
|
+
export const builtin = (id: string) => node('builtin', { id })
|
|
44
|
+
|
|
37
45
|
// Node shorthands
|
|
38
|
-
export const variable = (...args: X[]) => node('variable', { id: getId() }, ...args)
|
|
39
46
|
export const swizzle = (key: Swizzles, arg: X) => node('swizzle', null, key, arg)
|
|
40
47
|
export const operator = (key: Operators, ...args: X[]) => node('operator', null, key, ...args)
|
|
41
48
|
export const function_ = (key: Functions, ...args: X[]) => node('function', null, key, ...args)
|
|
42
49
|
export const conversion = (key: string, ...args: X[]) => node('conversion', null, key, ...args)
|
|
50
|
+
|
|
51
|
+
// x ? y : z
|
|
52
|
+
export const select = (x: X, y: X, z: X) => node('ternary', null, x, y, z)
|
package/src/node/scope.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { int } from '.'
|
|
2
|
+
import { conversion, node } from './node'
|
|
2
3
|
import { getId } from './utils'
|
|
3
|
-
import type { NodeProxy, X } from './types'
|
|
4
|
+
import type { FnLayout, NodeProps, NodeProxy, X } from './types'
|
|
4
5
|
|
|
5
6
|
let _scope: NodeProxy | null = null
|
|
6
7
|
|
|
@@ -19,8 +20,8 @@ const addToScope = (x: NodeProxy) => {
|
|
|
19
20
|
|
|
20
21
|
export const toVar = (x: X, id?: string) => {
|
|
21
22
|
if (!id) id = getId()
|
|
22
|
-
const y = node('variable', { id })
|
|
23
|
-
const z = node('declare', null,
|
|
23
|
+
const y = node('variable', { id, inferFrom: x })
|
|
24
|
+
const z = node('declare', null, x, y)
|
|
24
25
|
addToScope(z)
|
|
25
26
|
return y
|
|
26
27
|
}
|
|
@@ -31,48 +32,45 @@ export const assign = (x: X, y: X) => {
|
|
|
31
32
|
return x
|
|
32
33
|
}
|
|
33
34
|
|
|
34
|
-
export const If = (
|
|
35
|
-
const
|
|
36
|
-
scoped(
|
|
37
|
-
const ifNode = node('if', null,
|
|
35
|
+
export const If = (x: X, fun: () => void) => {
|
|
36
|
+
const y = node('scope')
|
|
37
|
+
scoped(y, fun)
|
|
38
|
+
const ifNode = node('if', null, x, y)
|
|
38
39
|
addToScope(ifNode)
|
|
39
|
-
const
|
|
40
|
-
ElseIf: (
|
|
41
|
-
const
|
|
42
|
-
scoped(
|
|
43
|
-
ifNode.props.children!.push(
|
|
44
|
-
return
|
|
40
|
+
const ret = () => ({
|
|
41
|
+
ElseIf: (_x: X, _fun: () => void) => {
|
|
42
|
+
const _y = node('scope')
|
|
43
|
+
scoped(_y, _fun)
|
|
44
|
+
ifNode.props.children!.push(_x, _y)
|
|
45
|
+
return ret()
|
|
45
46
|
},
|
|
46
47
|
Else: (_fun: () => void) => {
|
|
47
|
-
const
|
|
48
|
-
scoped(
|
|
49
|
-
ifNode.props.children!.push(
|
|
48
|
+
const _x = node('scope')
|
|
49
|
+
scoped(_x, _fun)
|
|
50
|
+
ifNode.props.children!.push(_x)
|
|
50
51
|
},
|
|
51
52
|
})
|
|
52
|
-
return
|
|
53
|
+
return ret()
|
|
53
54
|
}
|
|
54
55
|
|
|
55
|
-
export const Loop = (x: X, fun: (params: { i
|
|
56
|
+
export const Loop = (x: X, fun: (params: { i: NodeProxy }) => void) => {
|
|
56
57
|
const y = node('scope')
|
|
57
|
-
scoped(y, () => fun({ i: node('variable', { id: 'i' }) }))
|
|
58
|
+
scoped(y, () => fun({ i: node('variable', { id: 'i', inferFrom: int(0) }) }))
|
|
58
59
|
const ret = node('loop', null, x, y)
|
|
59
60
|
addToScope(ret)
|
|
60
61
|
return ret
|
|
61
62
|
}
|
|
62
63
|
|
|
63
|
-
export const Switch = (
|
|
64
|
-
const switchNode = node('switch', null,
|
|
64
|
+
export const Switch = (x: X) => {
|
|
65
|
+
const switchNode = node('switch', null, x)
|
|
65
66
|
addToScope(switchNode)
|
|
66
|
-
const
|
|
67
|
+
const ret = () => ({
|
|
67
68
|
Case: (...values: X[]) => {
|
|
68
69
|
return (fun: () => void) => {
|
|
69
|
-
const
|
|
70
|
-
scoped(
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
switchNode.props.children!.push(val, scope)
|
|
74
|
-
}
|
|
75
|
-
return createChain()
|
|
70
|
+
const y = node('scope')
|
|
71
|
+
scoped(y, fun)
|
|
72
|
+
for (const _x of values) switchNode.props.children!.push(_x, y)
|
|
73
|
+
return ret()
|
|
76
74
|
}
|
|
77
75
|
},
|
|
78
76
|
Default: (fun: () => void) => {
|
|
@@ -82,21 +80,32 @@ export const Switch = (value: X) => {
|
|
|
82
80
|
},
|
|
83
81
|
})
|
|
84
82
|
|
|
85
|
-
return
|
|
83
|
+
return ret()
|
|
86
84
|
}
|
|
87
85
|
|
|
88
86
|
export const Fn = (fun: (paramVars: NodeProxy[]) => NodeProxy) => {
|
|
89
|
-
|
|
90
|
-
|
|
87
|
+
let layout: FnLayout
|
|
88
|
+
const ret = (...args: X[]) => {
|
|
89
|
+
const id = layout?.name || getId()
|
|
91
90
|
const x = node('scope')
|
|
92
91
|
let y: NodeProxy | undefined
|
|
93
92
|
const paramVars: NodeProxy[] = []
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
const
|
|
97
|
-
|
|
98
|
-
|
|
93
|
+
const paramDefs: NodeProps[] = []
|
|
94
|
+
if (layout?.inputs)
|
|
95
|
+
for (const input of layout.inputs) {
|
|
96
|
+
paramDefs.push({ id: input.name, inferFrom: conversion(input.type) })
|
|
97
|
+
}
|
|
98
|
+
else
|
|
99
|
+
for (let i = 0; i < args.length; i++) {
|
|
100
|
+
paramDefs.push({ id: `p${i}`, inferFrom: args[i] })
|
|
101
|
+
}
|
|
102
|
+
for (const props of paramDefs) paramVars.push(node('variable', props))
|
|
99
103
|
scoped(x, () => (y = fun(paramVars)))
|
|
100
|
-
return node('define', { id }, x, y, ...args)
|
|
104
|
+
return node('define', { id, layout }, x, y, ...args)
|
|
101
105
|
}
|
|
106
|
+
ret.setLayout = (newLayout: FnLayout) => {
|
|
107
|
+
layout = newLayout
|
|
108
|
+
return ret
|
|
109
|
+
}
|
|
110
|
+
return ret
|
|
102
111
|
}
|