Skip to content

Commit d82ec0d

Browse files
authored
Merge pull request #8754 from LalitNarayanYadav/refactor/strands-extract-copying-helpers
Refactor: Extract shared addCopyingAndReturn helper for control flow transformations
2 parents bbbcedd + 0de66f7 commit d82ec0d

1 file changed

Lines changed: 74 additions & 130 deletions

File tree

src/strands/strands_transpiler.js

Lines changed: 74 additions & 130 deletions
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,79 @@ function transformBinaryOrLogical(node, state, ancestors) {
288288
node.arguments = [node.right];
289289
}
290290

291+
// Shared helper used by both IfStatement and ForStatement handlers.
292+
// Adds temp variable copies, replaces references, and appends a return
293+
// statement to a branch/loop function body.
294+
// sourcePrefix: the root identifier to read from ('vars' for loops,
295+
// null for if-branches where we read directly from the outer variable).
296+
function addCopyingAndReturn(functionBody, varsToReturn, sourcePrefix = null) {
297+
if (functionBody.type !== 'BlockStatement') return;
298+
299+
const tempVarMap = new Map();
300+
const copyStatements = [];
301+
302+
for (const varPath of varsToReturn) {
303+
const parts = varPath.split('.');
304+
const tempName = `__copy_${parts.join('_')}_${blockVarCounter++}`;
305+
tempVarMap.set(varPath, tempName);
306+
307+
// If sourcePrefix is set (loop case), read from vars.x.y
308+
// Otherwise (if-branch case), read directly from x.y
309+
let sourceExpr = sourcePrefix
310+
? { type: 'Identifier', name: sourcePrefix }
311+
: { type: 'Identifier', name: parts[0] };
312+
313+
const pathParts = sourcePrefix ? parts : parts.slice(1);
314+
for (const part of pathParts) {
315+
sourceExpr = {
316+
type: 'MemberExpression',
317+
object: sourceExpr,
318+
property: { type: 'Identifier', name: part },
319+
computed: false
320+
};
321+
}
322+
323+
copyStatements.push({
324+
type: 'VariableDeclaration',
325+
declarations: [{
326+
type: 'VariableDeclarator',
327+
id: { type: 'Identifier', name: tempName },
328+
init: {
329+
type: 'CallExpression',
330+
callee: {
331+
type: 'MemberExpression',
332+
object: sourceExpr,
333+
property: { type: 'Identifier', name: 'copy' },
334+
computed: false
335+
},
336+
arguments: []
337+
}
338+
}],
339+
kind: 'let'
340+
});
341+
}
342+
343+
functionBody.body.forEach(node => replaceReferences(node, tempVarMap));
344+
functionBody.body.unshift(...copyStatements);
345+
346+
const returnObj = {
347+
type: 'ObjectExpression',
348+
properties: Array.from(varsToReturn).map(varPath => ({
349+
type: 'Property',
350+
key: { type: 'Literal', value: varPath },
351+
value: { type: 'Identifier', name: tempVarMap.get(varPath) },
352+
kind: 'init',
353+
computed: false,
354+
shorthand: false
355+
}))
356+
};
357+
358+
functionBody.body.push({
359+
type: 'ReturnStatement',
360+
argument: returnObj
361+
});
362+
}
363+
291364
const ASTCallbacks = {
292365
UnaryExpression(node, state, ancestors) {
293366
if (ancestors.some(a => nodeIsUniform(a) || nodeIsUniformCallbackFn(a, state.uniformCallbackNames))) {
@@ -689,70 +762,6 @@ const ASTCallbacks = {
689762
analyzeBranch(thenFunction.body);
690763
analyzeBranch(elseFunction.body);
691764
if (assignedVars.size > 0) {
692-
// Add copying, reference replacement, and return statements to branch functions
693-
const addCopyingAndReturn = (functionBody, varsToReturn) => {
694-
if (functionBody.type === 'BlockStatement') {
695-
// Create temporary variables and copy statements
696-
const tempVarMap = new Map(); // property path -> temp name
697-
const copyStatements = [];
698-
for (const varPath of varsToReturn) {
699-
const parts = varPath.split('.');
700-
const tempName = `__copy_${parts.join('_')}_${blockVarCounter++}`;
701-
tempVarMap.set(varPath, tempName);
702-
703-
// Build the member expression for the property path
704-
let sourceExpr = { type: 'Identifier', name: parts[0] };
705-
for (let i = 1; i < parts.length; i++) {
706-
sourceExpr = {
707-
type: 'MemberExpression',
708-
object: sourceExpr,
709-
property: { type: 'Identifier', name: parts[i] },
710-
computed: false
711-
};
712-
}
713-
714-
// let tempName = propertyPath.copy()
715-
copyStatements.push({
716-
type: 'VariableDeclaration',
717-
declarations: [{
718-
type: 'VariableDeclarator',
719-
id: { type: 'Identifier', name: tempName },
720-
init: {
721-
type: 'CallExpression',
722-
callee: {
723-
type: 'MemberExpression',
724-
object: sourceExpr,
725-
property: { type: 'Identifier', name: 'copy' },
726-
computed: false
727-
},
728-
arguments: []
729-
}
730-
}],
731-
kind: 'let'
732-
});
733-
}
734-
// Apply reference replacement to all statements
735-
functionBody.body.forEach(node => replaceReferences(node, tempVarMap));
736-
// Insert copy statements at the beginning
737-
functionBody.body.unshift(...copyStatements);
738-
// Add return statement with flat object using property paths as keys
739-
const returnObj = {
740-
type: 'ObjectExpression',
741-
properties: Array.from(varsToReturn).map(varPath => ({
742-
type: 'Property',
743-
key: { type: 'Literal', value: varPath },
744-
value: { type: 'Identifier', name: tempVarMap.get(varPath) },
745-
kind: 'init',
746-
computed: false,
747-
shorthand: false
748-
}))
749-
};
750-
functionBody.body.push({
751-
type: 'ReturnStatement',
752-
argument: returnObj
753-
});
754-
}
755-
};
756765
addCopyingAndReturn(thenFunction.body, assignedVars);
757766
addCopyingAndReturn(elseFunction.body, assignedVars);
758767
// Create a block variable to capture the return value
@@ -1057,73 +1066,8 @@ const ASTCallbacks = {
10571066
});
10581067

10591068
if (assignedVars.size > 0) {
1060-
// Add copying, reference replacement, and return statements similar to if statements
1061-
const addCopyingAndReturn = (functionBody, varsToReturn) => {
1062-
if (functionBody.type === 'BlockStatement') {
1063-
const tempVarMap = new Map();
1064-
const copyStatements = [];
1065-
1066-
for (const varPath of varsToReturn) {
1067-
const parts = varPath.split('.');
1068-
const tempName = `__copy_${parts.join('_')}_${blockVarCounter++}`;
1069-
tempVarMap.set(varPath, tempName);
1070-
1071-
// Build the member expression for vars.propertyPath
1072-
// e.g., vars.inputs.color or vars.x
1073-
let sourceExpr = { type: 'Identifier', name: 'vars' };
1074-
for (const part of parts) {
1075-
sourceExpr = {
1076-
type: 'MemberExpression',
1077-
object: sourceExpr,
1078-
property: { type: 'Identifier', name: part },
1079-
computed: false
1080-
};
1081-
}
1082-
1083-
copyStatements.push({
1084-
type: 'VariableDeclaration',
1085-
declarations: [{
1086-
type: 'VariableDeclarator',
1087-
id: { type: 'Identifier', name: tempName },
1088-
init: {
1089-
type: 'CallExpression',
1090-
callee: {
1091-
type: 'MemberExpression',
1092-
object: sourceExpr,
1093-
property: { type: 'Identifier', name: 'copy' },
1094-
computed: false
1095-
},
1096-
arguments: []
1097-
}
1098-
}],
1099-
kind: 'let'
1100-
});
1101-
}
1102-
1103-
functionBody.body.forEach(node => replaceReferences(node, tempVarMap));
1104-
functionBody.body.unshift(...copyStatements);
1105-
1106-
// Add return statement with flat object using property paths as keys
1107-
const returnObj = {
1108-
type: 'ObjectExpression',
1109-
properties: Array.from(varsToReturn).map(varPath => ({
1110-
type: 'Property',
1111-
key: { type: 'Literal', value: varPath },
1112-
value: { type: 'Identifier', name: tempVarMap.get(varPath) },
1113-
kind: 'init',
1114-
computed: false,
1115-
shorthand: false
1116-
}))
1117-
};
1118-
1119-
functionBody.body.push({
1120-
type: 'ReturnStatement',
1121-
argument: returnObj
1122-
});
1123-
}
1124-
};
11251069

1126-
addCopyingAndReturn(bodyFunction.body, assignedVars);
1070+
addCopyingAndReturn(bodyFunction.body, assignedVars, 'vars');
11271071

11281072
// Create block variable and assignments similar to if statements
11291073
const blockVar = `__block_${blockVarCounter++}`;

0 commit comments

Comments
 (0)