Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 15 additions & 32 deletions src/transformation/visitors/binary-expression/compound.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ export function transformCompoundAssignment(
context.transformExpression(rhs)
);

if (lua.isTableIndexExpression(left) && shouldCacheTableIndexExpressions(left, rightPrecedingStatements)) {
if (lua.isTableIndexExpression(left)) {
// Complex property/element accesses need to cache object/index expressions to avoid repeating side-effects
// local __obj, __index = ${objExpression}, ${indexExpression};
const obj = context.createTempNameForLuaExpression(left.table);
Expand Down Expand Up @@ -105,6 +105,20 @@ export function transformCompoundAssignment(
result: tmp,
};
} else {
if (isSetterSkippingCompoundAssignmentOperator(operator)) {
return {
statements: [
objAndIndexDeclaration,
...transformSetterSkippingCompoundAssignment(
accessExpression,
operator,
right,
rightPrecedingStatements
),
],
result: left,
};
}
// local ____tmp = ____obj[____index] ${replacementOperator} ${right};
// ____obj[____index] = ____tmp;
// return ____tmp
Expand Down Expand Up @@ -145,37 +159,6 @@ export function transformCompoundAssignment(
rightPrecedingStatements
);
return { statements: [tmpDeclaration, ...precedingStatements, ...assignStatements], result: tmpIdentifier };
} else if (ts.isPropertyAccessExpression(lhs) || ts.isElementAccessExpression(lhs)) {
// Simple property/element access expressions need to cache in temp to avoid double-evaluation
// local ____tmp = ${left} ${replacementOperator} ${right};
// ${left} = ____tmp;
// return ____tmp
const tmpIdentifier = context.createTempNameForLuaExpression(left);
const [precedingStatements, operatorExpression] = transformBinaryOperation(
context,
left,
right,
rightPrecedingStatements,
operator,
expression
);
const tmpDeclaration = lua.createVariableDeclarationStatement(tmpIdentifier, operatorExpression);

if (isSetterSkippingCompoundAssignmentOperator(operator)) {
const statements = [
tmpDeclaration,
...transformSetterSkippingCompoundAssignment(tmpIdentifier, operator, right, precedingStatements),
];
return { statements, result: tmpIdentifier };
}

const assignStatements = transformAssignmentWithRightPrecedingStatements(
context,
lhs,
tmpIdentifier,
precedingStatements
);
return { statements: [tmpDeclaration, ...assignStatements], result: tmpIdentifier };
} else {
if (rightPrecedingStatements.length > 0 && isSetterSkippingCompoundAssignmentOperator(operator)) {
return {
Expand Down
15 changes: 13 additions & 2 deletions test/unit/assignments.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,17 @@ test.each([
`.expectToMatchJsResult();
});

// https://github.com/TypeScriptToLua/TypeScriptToLua/issues/1277
test("Compound assignment as expression (#1277)", () => {
util.testFunction`
let foo = {
bar: false as any
}
const result = foo.bar ||= true;
return { result, foo };
`.expectToMatchJsResult();
});

test.each([
"++o.p",
"o.p++",
Expand Down Expand Up @@ -417,7 +428,7 @@ test.each([
* x.y ||= z is translated to x.y || (x.y = z).
* x.y &&= z is translated to x.y && (x.y = z).
* x.y ||= z is translated to x.y !== undefined && (x.y = z).

Test if setter in Lua is called same nr of times as in JS.
*/
util.testModule`
Expand Down Expand Up @@ -449,7 +460,7 @@ test.each([
* x.y ||= z is translated to x.y || (x.y = z).
* x.y &&= z is translated to x.y && (x.y = z).
* x.y ||= z is translated to x.y !== undefined && (x.y = z).

Test if setter in Lua is called same nr of times as in JS.
*/
util.testModule`
Expand Down