UNPKG

p5

Version:

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

131 lines (126 loc) 4.99 kB
import { createBasicBlock, addEdge, pushBlock, popBlock, pushBlockForModification, recordInBasicBlock } from './ir_cfg.js'; import { getOrCreateNode } from './ir_dag.js'; import { BlockType, NodeType } from './ir_types.js'; import { c as createStrandsNode } from '../ir_builders-CMXkjMoV.js'; import { createPhiNode } from './strands_phi_utils.js'; import './strands_FES.js'; import './strands_builtins.js'; class StrandsConditional { constructor(strandsContext, condition, branchCallback) { // Condition must be a node... this.branches = [{ condition, branchCallback, blockType: BlockType.IF_BODY }]; this.ctx = strandsContext; } ElseIf(condition, branchCallback) { this.branches.push({ condition, branchCallback, blockType: BlockType.IF_BODY }); return this; } Else(branchCallback = () => ({})) { this.branches.push({ condition: null, branchCallback, blockType: BlockType.IF_BODY }); const phiNodes = buildConditional(this.ctx, this); const assignments = {}; for (const [varName, phiNode] of Object.entries(phiNodes)) { assignments[varName] = createStrandsNode(phiNode.id, phiNode.dimension, this.ctx); } return assignments; } } function buildConditional(strandsContext, conditional) { const cfg = strandsContext.cfg; const branches = conditional.branches; const mergeBlock = createBasicBlock(cfg, BlockType.MERGE); const results = []; const branchEndBlocks = []; const mergedAssignments = {}; const phiBlockDependencies = {}; // Create a BRANCH block to handle phi node declarations const branchBlock = createBasicBlock(cfg, BlockType.BRANCH); addEdge(cfg, cfg.currentBlock, branchBlock); addEdge(cfg, branchBlock, mergeBlock); let previousBlock = branchBlock; for (let i = 0; i < branches.length; i++) { const { condition, branchCallback, blockType } = branches[i]; if (condition !== null) { const conditionBlock = createBasicBlock(cfg, BlockType.IF_COND); addEdge(cfg, previousBlock, conditionBlock); pushBlock(cfg, conditionBlock); cfg.blockConditions[conditionBlock] = condition.id; previousBlock = conditionBlock; popBlock(cfg); } else { const elseCondBlock = createBasicBlock(cfg, BlockType.ELSE_COND); addEdge(cfg, previousBlock, elseCondBlock); previousBlock = elseCondBlock; } const scopeStartBlock = createBasicBlock(cfg, BlockType.SCOPE_START); addEdge(cfg, previousBlock, scopeStartBlock); const branchContentBlock = createBasicBlock(cfg, blockType); addEdge(cfg, scopeStartBlock, branchContentBlock); pushBlock(cfg, branchContentBlock); const branchResults = branchCallback(); for (const key in branchResults) { branchResults[key] = strandsContext.p5.strandsNode(branchResults[key]); } for (const key in branchResults) { if (!phiBlockDependencies[key]) { phiBlockDependencies[key] = [{ value: branchResults[key], blockId: branchContentBlock }]; } else { phiBlockDependencies[key].push({ value: branchResults[key], blockId: branchContentBlock }); } } results.push(branchResults); // Create BRANCH_END block for phi assignments const branchEndBlock = createBasicBlock(cfg, BlockType.DEFAULT); addEdge(cfg, cfg.currentBlock, branchEndBlock); branchEndBlocks.push(branchEndBlock); popBlock(cfg); const scopeEndBlock = createBasicBlock(cfg, BlockType.SCOPE_END); addEdge(cfg, branchEndBlock, scopeEndBlock); addEdge(cfg, scopeEndBlock, mergeBlock); previousBlock = scopeStartBlock; } // Push the branch block for modification to avoid changing the ordering pushBlockForModification(cfg, branchBlock); for (const key in phiBlockDependencies) { mergedAssignments[key] = createPhiNode(strandsContext, phiBlockDependencies[key], key); } popBlock(cfg); for (let i = 0; i < results.length; i++) { const branchResult = results[i]; const branchEndBlockID = branchEndBlocks[i]; pushBlockForModification(cfg, branchEndBlockID); for (const key in branchResult) { if (mergedAssignments[key]) { // Create an assignment statement: phiNode = branchResult[key] const phiNodeID = mergedAssignments[key].id; const sourceNodeID = branchResult[key].id; // Create an assignment operation node // Use dependsOn[0] for phiNodeID and dependsOn[1] for sourceNodeID // This represents: dependsOn[0] = dependsOn[1] (phiNode = sourceNode) const assignmentNode = { nodeType: NodeType.ASSIGNMENT, dependsOn: [phiNodeID, sourceNodeID], phiBlocks: [] }; const assignmentID = getOrCreateNode(strandsContext.dag, assignmentNode); recordInBasicBlock(cfg, branchEndBlockID, assignmentID); } } popBlock(cfg); } pushBlock(cfg, mergeBlock); return mergedAssignments; } export { StrandsConditional };