@womp/spark-agent 7.0.0 → 8.0.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/CHANGELOG.md +36 -0
- package/dist/capabilities/geometry.d.ts +17 -5
- package/dist/capabilities/geometry.js +11 -12
- package/dist/generated/geometry-declarations.d.ts +1 -1
- package/dist/generated/geometry-declarations.js +1 -1
- package/dist/geometry/backendRegistry.d.ts +1 -0
- package/dist/geometry/common.d.ts +5 -2
- package/dist/geometry/common.js +18 -3
- package/dist/geometry/compiler.js +2 -2
- package/dist/geometry/diagnostics.d.ts +2 -7
- package/dist/geometry/diagnostics.js +3 -51
- package/dist/geometry/graph.d.ts +1 -1
- package/dist/geometry/graph.js +1 -0
- package/dist/geometry/index.d.ts +0 -1
- package/dist/geometry/index.js +0 -3
- package/dist/geometry/lift.js +105 -113
- package/dist/geometry/lower.js +29 -49
- package/dist/geometry/schemas/flowir-dialect.json +117 -117
- package/dist/geometry/writeParamData.js +4 -4
- package/dist/geometry.d.ts +2 -5
- package/dist/geometry.js +7 -11
- package/dist/intent-bench.js +1 -1
- package/dist/sdk-geometry-host.d.ts +1 -1
- package/dist/sdk-geometry-host.js +253 -251
- package/dist/womp-scene-api.d.ts +9 -1
- package/dist/womp-scene-api.js +41 -32
- package/package.json +2 -2
package/dist/geometry/lift.js
CHANGED
|
@@ -1,11 +1,42 @@
|
|
|
1
|
-
import { VALUE_BACKEND_NAMES,
|
|
2
|
-
const
|
|
3
|
-
function
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
import { VALUE_BACKEND_NAMES, backendTypeId, isArrayPortType, paramName, storedSymbol, buildIncomingMap, defaultScalar, } from "./common.js";
|
|
2
|
+
const NO_SOURCE_POSITION = { line: 0, column: 0 };
|
|
3
|
+
function uniqueSymbol(prefix, start, taken) {
|
|
4
|
+
let index = start;
|
|
5
|
+
while (taken.has(`${prefix}${index}`))
|
|
6
|
+
index += 1;
|
|
7
|
+
taken.add(`${prefix}${index}`);
|
|
8
|
+
return `${prefix}${index}`;
|
|
9
|
+
}
|
|
10
|
+
function resolveNames(valueNodes, paramInputBid, dialectBids, graphExt) {
|
|
11
|
+
const names = new Map();
|
|
12
|
+
const taken = new Set();
|
|
13
|
+
const keep = (bid, name) => {
|
|
14
|
+
if (name === undefined)
|
|
15
|
+
return;
|
|
16
|
+
names.set(bid, name);
|
|
17
|
+
taken.add(name);
|
|
18
|
+
};
|
|
19
|
+
for (const vNode of valueNodes) {
|
|
20
|
+
const inputBid = paramInputBid(vNode);
|
|
21
|
+
keep(vNode.bid, inputBid
|
|
22
|
+
? paramName(graphExt, vNode.bid, inputBid)
|
|
23
|
+
: storedSymbol(graphExt, vNode.bid));
|
|
24
|
+
}
|
|
25
|
+
for (const bid of dialectBids)
|
|
26
|
+
keep(bid, storedSymbol(graphExt, bid));
|
|
27
|
+
let paramIndex = 0;
|
|
28
|
+
let constIndex = 0;
|
|
29
|
+
for (const vNode of valueNodes) {
|
|
30
|
+
const isParam = paramInputBid(vNode) !== undefined;
|
|
31
|
+
const index = isParam ? paramIndex++ : constIndex++;
|
|
32
|
+
if (!names.has(vNode.bid))
|
|
33
|
+
names.set(vNode.bid, uniqueSymbol(isParam ? "p" : "c", index, taken));
|
|
34
|
+
}
|
|
35
|
+
dialectBids.forEach((bid, index) => {
|
|
36
|
+
if (!names.has(bid))
|
|
37
|
+
names.set(bid, uniqueSymbol("n", index, taken));
|
|
7
38
|
});
|
|
8
|
-
return
|
|
39
|
+
return names;
|
|
9
40
|
}
|
|
10
41
|
function isVec3Object(v) {
|
|
11
42
|
if (!v || typeof v !== "object")
|
|
@@ -105,70 +136,47 @@ function decodeScalarValue(raw, typeName) {
|
|
|
105
136
|
return {
|
|
106
137
|
kind: "vec3",
|
|
107
138
|
value: [vec.x, vec.y, vec.z],
|
|
108
|
-
|
|
109
|
-
pos: POS,
|
|
139
|
+
...NO_SOURCE_POSITION,
|
|
110
140
|
};
|
|
111
141
|
}
|
|
112
|
-
if (typeName === "Bool" && typeof raw === "boolean") {
|
|
113
|
-
return { kind: "bool", value: raw, pos: POS };
|
|
114
|
-
}
|
|
115
142
|
if (typeName === "Int" && typeof raw === "number") {
|
|
116
143
|
const v = Math.trunc(raw);
|
|
117
|
-
return { kind: "int", value: v,
|
|
144
|
+
return { kind: "int", value: v, ...NO_SOURCE_POSITION };
|
|
118
145
|
}
|
|
119
146
|
const num = typeof raw === "number" ? raw : 0;
|
|
120
|
-
return { kind: "float", value: num,
|
|
147
|
+
return { kind: "float", value: num, ...NO_SOURCE_POSITION };
|
|
121
148
|
}
|
|
122
149
|
function decodeBackendValue(raw, backendPort, dialectPort, flowirRegistry) {
|
|
123
|
-
if (dialectPort.
|
|
124
|
-
const
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
}
|
|
129
|
-
if (backendPort.enumValues?.length && typeof raw === "number") {
|
|
130
|
-
const name = backendPort.enumValues[raw];
|
|
131
|
-
if (name)
|
|
132
|
-
return { kind: "ident", name, pos: POS };
|
|
150
|
+
if (flowirRegistry.isEnum(dialectPort.type)) {
|
|
151
|
+
const name = typeof raw === "number"
|
|
152
|
+
? flowirRegistry.getEnumValues(dialectPort.type)[raw]
|
|
153
|
+
: undefined;
|
|
154
|
+
return name ? { kind: "ident", name, ...NO_SOURCE_POSITION } : null;
|
|
133
155
|
}
|
|
134
156
|
const unwrapped = isArrayPortType(backendPort.type) && Array.isArray(raw) && raw.length === 1
|
|
135
157
|
? raw[0]
|
|
136
158
|
: raw;
|
|
137
|
-
if (isVec3Object(unwrapped))
|
|
138
|
-
return
|
|
139
|
-
kind: "vec3",
|
|
140
|
-
value: [unwrapped.x, unwrapped.y, unwrapped.z],
|
|
141
|
-
raw: `Vec3(${decimal(unwrapped.x)}, ${decimal(unwrapped.y)}, ${decimal(unwrapped.z)})`,
|
|
142
|
-
pos: POS,
|
|
143
|
-
};
|
|
144
|
-
}
|
|
159
|
+
if (isVec3Object(unwrapped))
|
|
160
|
+
return decodeScalarValue(unwrapped, "Vec3");
|
|
145
161
|
if (typeof unwrapped === "boolean") {
|
|
146
|
-
return { kind: "bool", value: unwrapped,
|
|
162
|
+
return { kind: "bool", value: unwrapped, ...NO_SOURCE_POSITION };
|
|
147
163
|
}
|
|
148
164
|
if (typeof unwrapped === "number") {
|
|
149
165
|
if (dialectPort.type === "Int" || dialectPort.type === "Int[]") {
|
|
150
166
|
const v = Math.trunc(unwrapped);
|
|
151
|
-
return { kind: "int", value: v,
|
|
167
|
+
return { kind: "int", value: v, ...NO_SOURCE_POSITION };
|
|
152
168
|
}
|
|
153
|
-
return {
|
|
154
|
-
kind: "float",
|
|
155
|
-
value: unwrapped,
|
|
156
|
-
raw: decimal(unwrapped),
|
|
157
|
-
pos: POS,
|
|
158
|
-
};
|
|
169
|
+
return { kind: "float", value: unwrapped, ...NO_SOURCE_POSITION };
|
|
159
170
|
}
|
|
160
171
|
return null;
|
|
161
172
|
}
|
|
162
|
-
function liftParam(vNode, gipBid,
|
|
173
|
+
function liftParam(vNode, gipBid, name, ctx) {
|
|
163
174
|
const typeName = vNode.valueTypeName ?? "Float";
|
|
164
|
-
const extName = ctx.graphExt.nodes?.[gipBid]?.name;
|
|
165
|
-
const name = extName ? titleToAstName(extName) : `p${paramCounter}`;
|
|
166
175
|
const rawDefault = getData(ctx.graph, vNode.bid, "0");
|
|
167
|
-
const paramTypeName = typeName === "Bool" ? "Float" : typeName;
|
|
168
176
|
return {
|
|
169
177
|
kind: "param",
|
|
170
178
|
name,
|
|
171
|
-
typeName
|
|
179
|
+
typeName,
|
|
172
180
|
value: rawDefault != null
|
|
173
181
|
? decodeScalarValue(rawDefault, typeName)
|
|
174
182
|
: decodeScalarValue(typeName === "Vec3" ? { x: 0, y: 0, z: 0 } : 0, typeName),
|
|
@@ -177,53 +185,50 @@ function liftParam(vNode, gipBid, paramCounter, ctx) {
|
|
|
177
185
|
max: getDataAsNumber(ctx.graph, gipBid, "1"),
|
|
178
186
|
step: getDataAsNumber(ctx.graph, gipBid, "2"),
|
|
179
187
|
},
|
|
180
|
-
|
|
188
|
+
...NO_SOURCE_POSITION,
|
|
181
189
|
};
|
|
182
190
|
}
|
|
183
|
-
function liftConst(vNode,
|
|
191
|
+
function liftConst(vNode, name, ctx) {
|
|
184
192
|
const typeName = vNode.valueTypeName ?? "Float";
|
|
185
193
|
const rawDefault = getData(ctx.graph, vNode.bid, "0");
|
|
186
194
|
return {
|
|
187
195
|
kind: "const",
|
|
188
|
-
name
|
|
189
|
-
typeName
|
|
196
|
+
name,
|
|
197
|
+
typeName,
|
|
190
198
|
value: rawDefault != null
|
|
191
199
|
? decodeScalarValue(rawDefault, typeName)
|
|
192
200
|
: decodeScalarValue(typeName === "Vec3" ? { x: 0, y: 0, z: 0 } : 0, typeName),
|
|
193
|
-
|
|
201
|
+
...NO_SOURCE_POSITION,
|
|
194
202
|
};
|
|
195
203
|
}
|
|
196
204
|
function resolveInputBinding(bid, idx, dialectPort, backendPort, ctx) {
|
|
197
205
|
const connEdge = ctx.incoming.get(bid)?.find((e) => e.toPort === idx);
|
|
198
206
|
if (connEdge) {
|
|
199
207
|
const sourceNode = ctx.classMap.get(connEdge.fromBid);
|
|
200
|
-
|
|
208
|
+
const sourceName = ctx.names.get(connEdge.fromBid);
|
|
209
|
+
if (!sourceNode || !sourceName)
|
|
201
210
|
return null;
|
|
202
|
-
|
|
203
|
-
if (paramName) {
|
|
211
|
+
if (sourceNode.cls === "value") {
|
|
204
212
|
return {
|
|
205
213
|
name: dialectPort.name,
|
|
206
|
-
value: { kind: "ident", name:
|
|
207
|
-
|
|
214
|
+
value: { kind: "ident", name: sourceName, ...NO_SOURCE_POSITION },
|
|
215
|
+
...NO_SOURCE_POSITION,
|
|
208
216
|
};
|
|
209
217
|
}
|
|
210
218
|
if (sourceNode.cls === "dialect" && sourceNode.dialectName) {
|
|
211
219
|
const sourceDialect = ctx.flowirRegistry.getNode(sourceNode.dialectName);
|
|
212
|
-
const
|
|
213
|
-
if (
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
pos: POS,
|
|
225
|
-
};
|
|
226
|
-
}
|
|
220
|
+
const outputPort = sourceDialect?.outputs[connEdge.fromPort];
|
|
221
|
+
if (outputPort) {
|
|
222
|
+
return {
|
|
223
|
+
name: dialectPort.name,
|
|
224
|
+
value: {
|
|
225
|
+
kind: "ref",
|
|
226
|
+
nodeId: sourceName,
|
|
227
|
+
port: outputPort.name,
|
|
228
|
+
...NO_SOURCE_POSITION,
|
|
229
|
+
},
|
|
230
|
+
...NO_SOURCE_POSITION,
|
|
231
|
+
};
|
|
227
232
|
}
|
|
228
233
|
}
|
|
229
234
|
return null;
|
|
@@ -234,11 +239,11 @@ function resolveInputBinding(bid, idx, dialectPort, backendPort, ctx) {
|
|
|
234
239
|
const decoded = decodeBackendValue(rawData, backendPort, dialectPort, ctx.flowirRegistry);
|
|
235
240
|
if (!decoded)
|
|
236
241
|
return null;
|
|
237
|
-
return { name: dialectPort.name, value: decoded,
|
|
242
|
+
return { name: dialectPort.name, value: decoded, ...NO_SOURCE_POSITION };
|
|
238
243
|
}
|
|
239
244
|
function liftNodeStmt(bid, cNode, ctx) {
|
|
240
245
|
const dialectName = cNode.dialectName;
|
|
241
|
-
const stmtId = ctx.
|
|
246
|
+
const stmtId = ctx.names.get(bid);
|
|
242
247
|
const dialectNode = ctx.flowirRegistry.getNode(dialectName);
|
|
243
248
|
if (!dialectNode)
|
|
244
249
|
return null;
|
|
@@ -254,7 +259,13 @@ function liftNodeStmt(bid, cNode, ctx) {
|
|
|
254
259
|
if (binding)
|
|
255
260
|
inputs.push(binding);
|
|
256
261
|
}
|
|
257
|
-
return {
|
|
262
|
+
return {
|
|
263
|
+
kind: "node",
|
|
264
|
+
id: stmtId,
|
|
265
|
+
nodeType: dialectName,
|
|
266
|
+
inputs,
|
|
267
|
+
...NO_SOURCE_POSITION,
|
|
268
|
+
};
|
|
258
269
|
}
|
|
259
270
|
function liftOutStmt(oNode, ctx) {
|
|
260
271
|
const geoEdge = ctx.incoming.get(oNode.bid)?.find((e) => e.toPort === 1);
|
|
@@ -264,7 +275,7 @@ function liftOutStmt(oNode, ctx) {
|
|
|
264
275
|
if (!sourceNode || sourceNode.cls !== "dialect" || !sourceNode.dialectName)
|
|
265
276
|
return null;
|
|
266
277
|
const sourceDialect = ctx.flowirRegistry.getNode(sourceNode.dialectName);
|
|
267
|
-
const sourceStmtId = ctx.
|
|
278
|
+
const sourceStmtId = ctx.names.get(geoEdge.fromBid);
|
|
268
279
|
if (!sourceDialect || !sourceStmtId)
|
|
269
280
|
return null;
|
|
270
281
|
const outputPort = sourceDialect.outputs[geoEdge.fromPort];
|
|
@@ -277,20 +288,16 @@ function liftOutStmt(oNode, ctx) {
|
|
|
277
288
|
kind: "ref",
|
|
278
289
|
nodeId: sourceStmtId,
|
|
279
290
|
port: outputPort.name,
|
|
280
|
-
|
|
291
|
+
...NO_SOURCE_POSITION,
|
|
281
292
|
},
|
|
282
|
-
|
|
293
|
+
...NO_SOURCE_POSITION,
|
|
283
294
|
};
|
|
284
295
|
}
|
|
285
296
|
export function lift(graph, graphExt, flowirRegistry, backendRegistry) {
|
|
286
297
|
const reverseMap = new Map();
|
|
287
298
|
for (const name of flowirRegistry.listNodeNames()) {
|
|
288
|
-
const id = flowirRegistry
|
|
289
|
-
if (id == null)
|
|
290
|
-
continue;
|
|
299
|
+
const id = backendTypeId(flowirRegistry, name);
|
|
291
300
|
const outputs = backendRegistry.getSchema(id)?.outputs;
|
|
292
|
-
// Dialect aliases can share a backend ID. Lift the native output type,
|
|
293
|
-
// so vector math is not accidentally narrowed to its scalar alias.
|
|
294
301
|
const matches = flowirRegistry
|
|
295
302
|
.getNode(name)
|
|
296
303
|
?.outputs.every((port, index) => port.type ===
|
|
@@ -313,52 +320,37 @@ export function lift(graph, graphExt, flowirRegistry, backendRegistry) {
|
|
|
313
320
|
const classMap = new Map();
|
|
314
321
|
for (const node of classified)
|
|
315
322
|
classMap.set(node.bid, node);
|
|
323
|
+
const valueNodes = classified.filter((n) => n.cls === "value");
|
|
324
|
+
const paramInputBid = (vNode) => incoming
|
|
325
|
+
.get(vNode.bid)
|
|
326
|
+
?.find((e) => classMap.get(e.fromBid)?.cls === "gip" && e.toPort === 0)
|
|
327
|
+
?.fromBid;
|
|
328
|
+
const dialectBids = toposort(classified.filter((n) => n.cls === "dialect").map((n) => n.bid), incoming);
|
|
316
329
|
const ctx = {
|
|
317
330
|
graph,
|
|
318
|
-
graphExt,
|
|
319
331
|
flowirRegistry,
|
|
320
332
|
backendRegistry,
|
|
321
333
|
incoming,
|
|
322
334
|
classMap,
|
|
323
|
-
|
|
324
|
-
dialectStmtIds: new Map(),
|
|
335
|
+
names: resolveNames(valueNodes, paramInputBid, dialectBids, graphExt),
|
|
325
336
|
};
|
|
326
337
|
const statements = [];
|
|
327
338
|
const nodeIds = {};
|
|
328
|
-
let paramCounter = 0;
|
|
329
|
-
let constCounter = 0;
|
|
330
|
-
const valueNodes = classified.filter((n) => n.cls === "value");
|
|
331
339
|
for (const vNode of valueNodes) {
|
|
332
|
-
const
|
|
333
|
-
const
|
|
334
|
-
if (
|
|
335
|
-
statements.push(liftParam(vNode,
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
nodeIds[`param:${stmt.name}`] = vNode.bid;
|
|
339
|
-
nodeIds[`param-input:${stmt.name}`] = gipEdge.fromBid;
|
|
340
|
-
paramCounter++;
|
|
340
|
+
const name = ctx.names.get(vNode.bid);
|
|
341
|
+
const inputBid = paramInputBid(vNode);
|
|
342
|
+
if (inputBid) {
|
|
343
|
+
statements.push(liftParam(vNode, inputBid, name, ctx));
|
|
344
|
+
nodeIds[`param:${name}`] = vNode.bid;
|
|
345
|
+
nodeIds[`param-input:${name}`] = inputBid;
|
|
341
346
|
}
|
|
342
347
|
else {
|
|
343
|
-
statements.push(liftConst(vNode,
|
|
344
|
-
const
|
|
345
|
-
ctx.paramBids.set(vNode.bid, stmt.name);
|
|
346
|
-
nodeIds[`const:${stmt.name}`] = vNode.bid;
|
|
347
|
-
constCounter++;
|
|
348
|
+
statements.push(liftConst(vNode, name, ctx));
|
|
349
|
+
nodeIds[`const:${name}`] = vNode.bid;
|
|
348
350
|
}
|
|
349
351
|
}
|
|
350
|
-
const dialectBids
|
|
351
|
-
|
|
352
|
-
.map((n) => n.bid);
|
|
353
|
-
const sortedBids = toposort(dialectBids, incoming);
|
|
354
|
-
let nodeCounter = 0;
|
|
355
|
-
for (const bid of sortedBids) {
|
|
356
|
-
ctx.dialectStmtIds.set(bid, `n${nodeCounter}`);
|
|
357
|
-
nodeCounter++;
|
|
358
|
-
}
|
|
359
|
-
for (const bid of sortedBids) {
|
|
360
|
-
const cNode = classMap.get(bid);
|
|
361
|
-
const stmt = liftNodeStmt(bid, cNode, ctx);
|
|
352
|
+
for (const bid of dialectBids) {
|
|
353
|
+
const stmt = liftNodeStmt(bid, classMap.get(bid), ctx);
|
|
362
354
|
if (stmt) {
|
|
363
355
|
statements.push(stmt);
|
|
364
356
|
nodeIds[`node:${stmt.id}`] = bid;
|
package/dist/geometry/lower.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { astNameToTitle, defaultScalar, valueBackendName, isArrayPortType, } from "./common.js";
|
|
1
|
+
import { astNameToTitle, backendTypeId, defaultScalar, valueBackendName, isArrayPortType, } from "./common.js";
|
|
2
2
|
class GraphBuilder {
|
|
3
3
|
nextId = 0;
|
|
4
4
|
nodes = {};
|
|
@@ -28,10 +28,7 @@ class GraphBuilder {
|
|
|
28
28
|
}
|
|
29
29
|
}
|
|
30
30
|
function resolveBackendSchema(nodeType, flowirRegistry, backendRegistry) {
|
|
31
|
-
|
|
32
|
-
if (typeId === null)
|
|
33
|
-
return null;
|
|
34
|
-
return backendRegistry.getSchema(typeId);
|
|
31
|
+
return backendRegistry.getSchema(backendTypeId(flowirRegistry, nodeType));
|
|
35
32
|
}
|
|
36
33
|
function toLiteral(value) {
|
|
37
34
|
if (value.kind === "int")
|
|
@@ -45,10 +42,7 @@ function toLiteral(value) {
|
|
|
45
42
|
return null;
|
|
46
43
|
}
|
|
47
44
|
function isVecPortType(type) {
|
|
48
|
-
return
|
|
49
|
-
type === "Vec" ||
|
|
50
|
-
type === "Vec3[]" ||
|
|
51
|
-
type === "VecArray");
|
|
45
|
+
return type === "Vec" || type === "VecArray";
|
|
52
46
|
}
|
|
53
47
|
function isZeroVec(v) {
|
|
54
48
|
if (!v || typeof v !== "object")
|
|
@@ -56,11 +50,9 @@ function isZeroVec(v) {
|
|
|
56
50
|
const vec = v;
|
|
57
51
|
return vec.x === 0 && vec.y === 0 && vec.z === 0;
|
|
58
52
|
}
|
|
59
|
-
function isDefaultValue(value, port
|
|
53
|
+
function isDefaultValue(value, port) {
|
|
60
54
|
if (port.enumValues?.length)
|
|
61
55
|
return false;
|
|
62
|
-
if (dialectPort?.enum)
|
|
63
|
-
return false;
|
|
64
56
|
if (defaultScalar(port) === null)
|
|
65
57
|
return false;
|
|
66
58
|
if (value === 0)
|
|
@@ -91,9 +83,9 @@ function encodeLiteralForPort(literal, port) {
|
|
|
91
83
|
}
|
|
92
84
|
return isArray ? [scalar] : scalar;
|
|
93
85
|
}
|
|
94
|
-
function trySetInput(bid, portIndex, literal, port,
|
|
86
|
+
function trySetInput(bid, portIndex, literal, port, graph) {
|
|
95
87
|
const encoded = encodeLiteralForPort(literal, port);
|
|
96
|
-
if (!isDefaultValue(encoded, port
|
|
88
|
+
if (!isDefaultValue(encoded, port)) {
|
|
97
89
|
graph.setInput(bid, portIndex, encoded);
|
|
98
90
|
}
|
|
99
91
|
}
|
|
@@ -101,27 +93,19 @@ function encodeValue(value, port, dialectPort, flowirRegistry) {
|
|
|
101
93
|
const literal = toLiteral(value);
|
|
102
94
|
if (literal)
|
|
103
95
|
return encodeLiteralForPort(literal, port);
|
|
104
|
-
if (value.kind
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
return idx;
|
|
111
|
-
}
|
|
112
|
-
if (port.enumValues?.length) {
|
|
113
|
-
const idx = port.enumValues.indexOf(value.name);
|
|
114
|
-
if (idx >= 0)
|
|
115
|
-
return idx;
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
return null;
|
|
96
|
+
if (value.kind !== "ident" || !flowirRegistry.isEnum(dialectPort.type))
|
|
97
|
+
return null;
|
|
98
|
+
const index = flowirRegistry
|
|
99
|
+
.getEnumValues(dialectPort.type)
|
|
100
|
+
.indexOf(value.name);
|
|
101
|
+
return index >= 0 ? index : null;
|
|
119
102
|
}
|
|
120
103
|
function valueNodeSchema(typeName, backendRegistry) {
|
|
121
104
|
const backendName = valueBackendName(typeName);
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
105
|
+
const schema = backendName ? backendRegistry.getSchemaByName(backendName) : null;
|
|
106
|
+
if (!schema)
|
|
107
|
+
throw new Error(`Geometry has no value node for ${typeName}.`);
|
|
108
|
+
return schema;
|
|
125
109
|
}
|
|
126
110
|
function lowerFloatExpr(expr, ctx) {
|
|
127
111
|
if (expr.kind === "float_lit")
|
|
@@ -157,7 +141,7 @@ function lowerFloatExpr(expr, ctx) {
|
|
|
157
141
|
if (left.kind === "literal") {
|
|
158
142
|
const port = mathFloat.inputs[1];
|
|
159
143
|
if (port)
|
|
160
|
-
trySetInput(bid, 1, { kind: "float", value: left.value }, port,
|
|
144
|
+
trySetInput(bid, 1, { kind: "float", value: left.value }, port, ctx.graph);
|
|
161
145
|
}
|
|
162
146
|
else {
|
|
163
147
|
ctx.graph.connect(left.backendNodeId, left.portIndex, bid, 1);
|
|
@@ -165,7 +149,7 @@ function lowerFloatExpr(expr, ctx) {
|
|
|
165
149
|
if (right.kind === "literal") {
|
|
166
150
|
const port = mathFloat.inputs[2];
|
|
167
151
|
if (port)
|
|
168
|
-
trySetInput(bid, 2, { kind: "float", value: right.value }, port,
|
|
152
|
+
trySetInput(bid, 2, { kind: "float", value: right.value }, port, ctx.graph);
|
|
169
153
|
}
|
|
170
154
|
else {
|
|
171
155
|
ctx.graph.connect(right.backendNodeId, right.portIndex, bid, 2);
|
|
@@ -187,7 +171,7 @@ function lowerVec3Ctor(ctor, targetBid, targetPortIndex, targetPort, ctx) {
|
|
|
187
171
|
if (result.kind === "literal") {
|
|
188
172
|
const port = combineXyz.inputs[idx];
|
|
189
173
|
if (port)
|
|
190
|
-
trySetInput(combineBid, idx, { kind: "float", value: result.value }, port,
|
|
174
|
+
trySetInput(combineBid, idx, { kind: "float", value: result.value }, port, ctx.graph);
|
|
191
175
|
}
|
|
192
176
|
else {
|
|
193
177
|
ctx.graph.connect(result.backendNodeId, result.portIndex, combineBid, idx);
|
|
@@ -198,22 +182,19 @@ function lowerVec3Ctor(ctor, targetBid, targetPortIndex, targetPort, ctx) {
|
|
|
198
182
|
}
|
|
199
183
|
function lowerConst(stmt, ctx) {
|
|
200
184
|
const schema = valueNodeSchema(stmt.typeName, ctx.backendRegistry);
|
|
201
|
-
if (!schema)
|
|
202
|
-
return;
|
|
203
185
|
const lit = toLiteral(stmt.value);
|
|
204
186
|
if (!lit)
|
|
205
187
|
return;
|
|
206
188
|
const bid = ctx.graph.addNode(schema.typeId);
|
|
207
189
|
const backendPort = schema.inputs[0];
|
|
208
190
|
if (backendPort)
|
|
209
|
-
trySetInput(bid, 0, lit, backendPort,
|
|
191
|
+
trySetInput(bid, 0, lit, backendPort, ctx.graph);
|
|
210
192
|
ctx.paramNodes.set(stmt.name, bid);
|
|
211
193
|
ctx.nodeIds[`const:${stmt.name}`] = bid;
|
|
194
|
+
ctx.graphExt.nodes[bid] = { flowirSymbol: stmt.name };
|
|
212
195
|
}
|
|
213
196
|
function lowerParam(stmt, ctx) {
|
|
214
197
|
const schema = valueNodeSchema(stmt.typeName, ctx.backendRegistry);
|
|
215
|
-
if (!schema)
|
|
216
|
-
return;
|
|
217
198
|
const lit = toLiteral(stmt.value);
|
|
218
199
|
if (!lit)
|
|
219
200
|
return;
|
|
@@ -222,17 +203,18 @@ function lowerParam(stmt, ctx) {
|
|
|
222
203
|
return;
|
|
223
204
|
const gipBid = ctx.graph.addNode(gipSchema.typeId);
|
|
224
205
|
ctx.nodeIds[`param-input:${stmt.name}`] = gipBid;
|
|
225
|
-
ctx.
|
|
206
|
+
ctx.graphExt.nodes[gipBid] = { name: astNameToTitle(stmt.name) };
|
|
226
207
|
ctx.graph.setInput(gipBid, 0, stmt.range.min);
|
|
227
208
|
ctx.graph.setInput(gipBid, 1, stmt.range.max);
|
|
228
209
|
ctx.graph.setInput(gipBid, 2, stmt.range.step);
|
|
229
210
|
const bid = ctx.graph.addNode(schema.typeId);
|
|
230
211
|
const backendPort = schema.inputs[0];
|
|
231
212
|
if (backendPort)
|
|
232
|
-
trySetInput(bid, 0, lit, backendPort,
|
|
213
|
+
trySetInput(bid, 0, lit, backendPort, ctx.graph);
|
|
233
214
|
ctx.graph.connect(gipBid, 0, bid, 0);
|
|
234
215
|
ctx.paramNodes.set(stmt.name, bid);
|
|
235
216
|
ctx.nodeIds[`param:${stmt.name}`] = bid;
|
|
217
|
+
ctx.graphExt.nodes[bid] = { flowirSymbol: stmt.name };
|
|
236
218
|
}
|
|
237
219
|
function lowerNodeStmt(stmt, ctx, pending) {
|
|
238
220
|
const schema = resolveBackendSchema(stmt.nodeType, ctx.flowirRegistry, ctx.backendRegistry);
|
|
@@ -241,6 +223,7 @@ function lowerNodeStmt(stmt, ctx, pending) {
|
|
|
241
223
|
const bid = ctx.graph.addNode(schema.typeId);
|
|
242
224
|
ctx.backendIds.set(stmt.id, bid);
|
|
243
225
|
ctx.nodeIds[`node:${stmt.id}`] = bid;
|
|
226
|
+
ctx.graphExt.nodes[bid] = { flowirSymbol: stmt.id };
|
|
244
227
|
ctx.nodeTypes.set(stmt.id, stmt.nodeType);
|
|
245
228
|
ctx.nodeSchemas.set(stmt.id, schema);
|
|
246
229
|
for (const input of stmt.inputs) {
|
|
@@ -272,7 +255,7 @@ function lowerNodeStmt(stmt, ctx, pending) {
|
|
|
272
255
|
if (input.value.kind === "vec3ctor") {
|
|
273
256
|
const lowered = lowerVec3Ctor(input.value, bid, resolved.index, backendPort, ctx);
|
|
274
257
|
if (lowered !== null &&
|
|
275
|
-
!isDefaultValue(lowered, backendPort
|
|
258
|
+
!isDefaultValue(lowered, backendPort)) {
|
|
276
259
|
ctx.graph.setInput(bid, resolved.index, lowered);
|
|
277
260
|
}
|
|
278
261
|
continue;
|
|
@@ -280,7 +263,7 @@ function lowerNodeStmt(stmt, ctx, pending) {
|
|
|
280
263
|
const encoded = encodeValue(input.value, backendPort, resolved.port, ctx.flowirRegistry);
|
|
281
264
|
if (encoded === null)
|
|
282
265
|
continue;
|
|
283
|
-
if (isDefaultValue(encoded, backendPort
|
|
266
|
+
if (isDefaultValue(encoded, backendPort))
|
|
284
267
|
continue;
|
|
285
268
|
ctx.graph.setInput(bid, resolved.index, encoded);
|
|
286
269
|
}
|
|
@@ -337,7 +320,7 @@ export function lower(program, flowirRegistry, backendRegistry) {
|
|
|
337
320
|
backendIds: new Map(),
|
|
338
321
|
nodeTypes: new Map(),
|
|
339
322
|
nodeSchemas: new Map(),
|
|
340
|
-
|
|
323
|
+
graphExt: { nodes: {} },
|
|
341
324
|
nodeIds: {},
|
|
342
325
|
};
|
|
343
326
|
const pending = [];
|
|
@@ -358,8 +341,5 @@ export function lower(program, flowirRegistry, backendRegistry) {
|
|
|
358
341
|
}
|
|
359
342
|
}
|
|
360
343
|
resolvePendingConnections(pending, ctx);
|
|
361
|
-
|
|
362
|
-
nodes: Object.fromEntries([...ctx.nodeNames.entries()].map(([bid, name]) => [bid, { name }])),
|
|
363
|
-
};
|
|
364
|
-
return { graph: graph.toPayload(), graphExt, nodeIds: ctx.nodeIds };
|
|
344
|
+
return { graph: graph.toPayload(), graphExt: ctx.graphExt, nodeIds: ctx.nodeIds };
|
|
365
345
|
}
|