(p5, fn, strandsContext)
| 156 | // User nodes |
| 157 | ////////////////////////////////////////////// |
| 158 | export function initGlobalStrandsAPI(p5, fn, strandsContext) { |
| 159 | // We augment the strands node with operations programatically |
| 160 | // this means methods like .add, .sub, etc can be chained |
| 161 | for (const { name, arity, opCode } of OperatorTable) { |
| 162 | if (arity === 'binary') { |
| 163 | StrandsNode.prototype[name] = function (...right) { |
| 164 | const { id, dimension } = build.binaryOpNode(strandsContext, this, right, opCode); |
| 165 | return createStrandsNode(id, dimension, strandsContext); |
| 166 | }; |
| 167 | } |
| 168 | if (arity === 'unary') { |
| 169 | p5[name] = function (nodeOrValue) { |
| 170 | const { id, dimension } = build.unaryOpNode(strandsContext, nodeOrValue, opCode); |
| 171 | return createStrandsNode(id, dimension, strandsContext); |
| 172 | } |
| 173 | } |
| 174 | } |
| 175 | ////////////////////////////////////////////// |
| 176 | // Unique Functions |
| 177 | ////////////////////////////////////////////// |
| 178 | augmentFn(fn, p5, 'discard', function() { |
| 179 | build.statementNode(strandsContext, StatementType.DISCARD); |
| 180 | }); |
| 181 | augmentFn(fn, p5, 'break', function() { |
| 182 | build.statementNode(strandsContext, StatementType.BREAK); |
| 183 | }); |
| 184 | p5.break = fn.break; |
| 185 | augmentFn(fn, p5, 'instanceID', function() { |
| 186 | const node = build.variableNode(strandsContext, { baseType: BaseType.INT, dimension: 1 }, strandsContext.backend.instanceIdReference()); |
| 187 | return createStrandsNode(node.id, node.dimension, strandsContext); |
| 188 | }); |
| 189 | // Internal methods use p5 static methods; user-facing methods use fn. |
| 190 | // Some methods need to be used by both. |
| 191 | p5.strandsIf = function(conditionNode, ifBody) { |
| 192 | return new StrandsConditional(strandsContext, conditionNode, ifBody); |
| 193 | } |
| 194 | augmentFn(fn, p5, 'strandsIf', p5.strandsIf); |
| 195 | p5.strandsFor = function(initialCb, conditionCb, updateCb, bodyCb, initialVars) { |
| 196 | return new StrandsFor(strandsContext, initialCb, conditionCb, updateCb, bodyCb, initialVars).build(); |
| 197 | }; |
| 198 | augmentFn(fn, p5, 'strandsFor', p5.strandsFor); |
| 199 | p5.strandsTernary = function(condition, ifTrue, ifFalse) { |
| 200 | return buildTernary(strandsContext, condition, ifTrue, ifFalse); |
| 201 | }; |
| 202 | augmentFn(fn, p5, 'strandsTernary', p5.strandsTernary); |
| 203 | p5.strandsEarlyReturn = function(value) { |
| 204 | const { dag, cfg } = strandsContext; |
| 205 | |
| 206 | // Ensure we're inside a hook |
| 207 | if (!strandsContext.activeHook) { |
| 208 | throw new Error('strandsEarlyReturn can only be used inside a hook callback'); |
| 209 | } |
| 210 | |
| 211 | // Convert value to a StrandsNode if it isn't already |
| 212 | const valueNode = value?.isStrandsNode ? value : p5.strandsNode(value); |
| 213 | |
| 214 | // Create a new CFG block for the early return |
| 215 | const earlyReturnBlockID = CFG.createBasicBlock(cfg, BlockType.DEFAULT); |
no test coverage detected