UNPKG

p5

Version:

[![npm version](https://badge.fury.io/js/p5.svg)](https://www.npmjs.com/package/p5)

161 lines (143 loc) 4.63 kB
import { BasePriority, NodeTypeRequiredFields, NodeTypeToName, BaseType } from './ir_types.js'; import { internalError } from './strands_FES.js'; ///////////////////////////////// // Public functions for strands runtime ///////////////////////////////// function createDirectedAcyclicGraph() { const graph = { nextID: 0, cache: new Map(), nodeTypes: [], baseTypes: [], dimensions: [], opCodes: [], values: [], identifiers: [], phiBlocks: [], dependsOn: [], usedBy: [], statementTypes: [], swizzles: [], }; return graph; } function getOrCreateNode(graph, node) { // const key = getNodeKey(node); // const existing = graph.cache.get(key); // if (existing !== undefined) { // return existing; // } else { const id = createNode(graph, node); // graph.cache.set(key, id); return id; // } } function createNodeData(data = {}) { const node = { nodeType: data.nodeType ?? null, baseType: data.baseType ?? null, dimension: data.dimension ?? null, opCode: data.opCode ?? null, value: data.value ?? null, identifier: data.identifier ?? null, statementType: data.statementType ?? null, swizzle: data.swizzle ?? null, dependsOn: Array.isArray(data.dependsOn) ? data.dependsOn : [], usedBy: Array.isArray(data.usedBy) ? data.usedBy : [], phiBlocks: Array.isArray(data.phiBlocks) ? data.phiBlocks : [], }; validateNode(node); return node; } function getNodeDataFromID(graph, id) { return { id, nodeType: graph.nodeTypes[id], opCode: graph.opCodes[id], value: graph.values[id], identifier: graph.identifiers[id], dependsOn: graph.dependsOn[id], usedBy: graph.usedBy[id], phiBlocks: graph.phiBlocks[id], dimension: graph.dimensions[id], baseType: graph.baseTypes[id], statementType: graph.statementTypes[id], swizzle: graph.swizzles[id], } } function extractNodeTypeInfo(dag, nodeID) { return { baseType: dag.baseTypes[nodeID], dimension: dag.dimensions[nodeID], priority: BasePriority[dag.baseTypes[nodeID]], }; } // Propagate a known type to an ASSIGN_ON_USE node and all its ASSIGN_ON_USE dependencies function propagateTypeToAssignOnUse(dag, nodeId, baseType, dimension, visited = new Set()) { // Avoid infinite loops if (visited.has(nodeId)) { return; } visited.add(nodeId); const node = getNodeDataFromID(dag, nodeId); // Only update if this node is ASSIGN_ON_USE if (node.baseType !== BaseType.ASSIGN_ON_USE) { return; } // Update this node's type dag.baseTypes[nodeId] = baseType; dag.dimensions[nodeId] = dimension; // Recursively propagate to any ASSIGN_ON_USE dependencies if (node.dependsOn && node.dependsOn.length > 0) { for (const depId of node.dependsOn) { const dep = getNodeDataFromID(dag, depId); if (dep.baseType === BaseType.ASSIGN_ON_USE) { propagateTypeToAssignOnUse(dag, depId, baseType, dimension, visited); } } } } ///////////////////////////////// // Private functions ///////////////////////////////// function createNode(graph, node) { const id = graph.nextID++; graph.nodeTypes[id] = node.nodeType; graph.opCodes[id] = node.opCode; graph.values[id] = node.value; graph.identifiers[id] = node.identifier; graph.dependsOn[id] = node.dependsOn.slice(); graph.usedBy[id] = node.usedBy; graph.phiBlocks[id] = node.phiBlocks.slice(); graph.baseTypes[id] = node.baseType; graph.dimensions[id] = node.dimension; graph.statementTypes[id] = node.statementType; graph.swizzles[id] = node.swizzle; for (const dep of node.dependsOn) { if (!Array.isArray(graph.usedBy[dep])) { graph.usedBy[dep] = []; } graph.usedBy[dep].push(id); } return id; } function validateNode(node){ const nodeType = node.nodeType; const requiredFields = NodeTypeRequiredFields[nodeType]; if (requiredFields.length === 2) { internalError(`Required fields for node type '${NodeTypeToName[nodeType]}' not defined. Please add them to the utils.js file in p5.strands!`); } const missingFields = []; for (const field of requiredFields) { if (node[field] === null) { missingFields.push(field); } } if (node.dependsOn?.some(v => v === undefined)) { throw new Error('Undefined dependency!'); } if (missingFields.length > 0) { internalError(`Missing fields ${missingFields.join(', ')} for a node type '${NodeTypeToName[nodeType]}'.`); } } export { createDirectedAcyclicGraph, createNodeData, extractNodeTypeInfo, getNodeDataFromID, getOrCreateNode, propagateTypeToAssignOnUse };