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
46 changes: 14 additions & 32 deletions src/transformation/visitors/binary-expression/assignments.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,8 +107,6 @@ function transformDestructuredAssignmentExpression(
context: TransformationContext,
expression: ts.DestructuringAssignment
) {
const rootIdentifier = context.createTempNameForNode(expression.right);

let [rightPrecedingStatements, right] = transformInPrecedingStatementScope(context, () =>
context.transformExpression(expression.right)
);
Expand All @@ -117,12 +115,15 @@ function transformDestructuredAssignmentExpression(
right = wrapInTable(right);
}

const statements = [
lua.createVariableDeclarationStatement(rootIdentifier, right),
...transformDestructuringAssignment(context, expression, rootIdentifier, rightPrecedingStatements.length > 0),
];
const rightExpr = moveToPrecedingTemp(context, right, expression.right);
const statements = transformDestructuringAssignment(
context,
expression,
rightExpr,
rightPrecedingStatements.length > 0
);

return { statements, result: rootIdentifier };
return { statements, result: rightExpr };
}

export function transformAssignmentExpression(
Expand Down Expand Up @@ -152,7 +153,6 @@ export function transformAssignmentExpression(
}

if (ts.isPropertyAccessExpression(expression.left) || ts.isElementAccessExpression(expression.left)) {
const tempVar = context.createTempNameForNode(expression.right);
const [precedingStatements, right] = transformInPrecedingStatementScope(context, () =>
context.transformExpression(expression.right)
);
Expand All @@ -163,12 +163,10 @@ export function transformAssignmentExpression(
precedingStatements.length > 0
);

context.addPrecedingStatements([
...precedingStatements,
lua.createVariableDeclarationStatement(tempVar, right, expression.right),
lua.createAssignmentStatement(left, lua.cloneIdentifier(tempVar), expression.left),
]);
return lua.cloneIdentifier(tempVar);
context.addPrecedingStatements(precedingStatements);
const rightExpr = moveToPrecedingTemp(context, right, expression.right);
context.addPrecedingStatements(lua.createAssignmentStatement(left, rightExpr, expression.left));
return rightExpr;
} else {
// Simple assignment
// ${left} = ${right}; return ${left}
Expand Down Expand Up @@ -232,24 +230,8 @@ export function transformAssignmentStatement(
return [lua.createAssignmentStatement(left, right, expression)];
}

let [rightPrecedingStatements, right] = transformInPrecedingStatementScope(context, () =>
context.transformExpression(expression.right)
);
context.addPrecedingStatements(rightPrecedingStatements);
if (isMultiReturnCall(context, expression.right)) {
right = wrapInTable(right);
}

const rootIdentifier = context.createTempNameForNode(expression.left);
return [
lua.createVariableDeclarationStatement(rootIdentifier, right),
...transformDestructuringAssignment(
context,
expression,
rootIdentifier,
rightPrecedingStatements.length > 0
),
];
const { statements } = transformDestructuredAssignmentExpression(context, expression);
return statements;
} else {
const [precedingStatements, right] = transformInPrecedingStatementScope(context, () =>
context.transformExpression(expression.right)
Expand Down
7 changes: 6 additions & 1 deletion src/transformation/visitors/expression-list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,12 @@ export function shouldMoveToTemp(context: TransformationContext, expression: lua
return (
!lua.isLiteral(expression) &&
!(lua.isIdentifier(expression) && expression.symbolId === tempSymbolId) && // Treat generated temps as consts
!(tsOriginal && (isConstIdentifier(context, tsOriginal) || isOptionalContinuation(tsOriginal)))
!(
tsOriginal &&
(isConstIdentifier(context, tsOriginal) ||
isOptionalContinuation(tsOriginal) ||
tsOriginal.kind === ts.SyntaxKind.ThisKeyword)
)
);
}

Expand Down
28 changes: 14 additions & 14 deletions src/transformation/visitors/variable-declaration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { createCallableTable, isFunctionTypeWithProperties } from "./function";
import { transformIdentifier } from "./identifier";
import { isMultiReturnCall } from "./language-extensions/multi";
import { transformPropertyName } from "./literal";
import { moveToPrecedingTemp } from "./expression-list";

export function transformArrayBindingElement(
context: TransformationContext,
Expand All @@ -38,7 +39,7 @@ export function transformArrayBindingElement(
export function transformBindingPattern(
context: TransformationContext,
pattern: ts.BindingPattern,
table: lua.Identifier,
table: lua.Expression,
propertyAccessStack: ts.PropertyName[] = []
): lua.Statement[] {
const result: lua.Statement[] = [];
Expand Down Expand Up @@ -165,21 +166,20 @@ export function transformBindingVariableDeclaration(
ts.isBindingElement(e) && (!ts.isIdentifier(e.name) || e.dotDotDotToken);

if (ts.isObjectBindingPattern(bindingPattern) || bindingPattern.elements.some(isComplexBindingElement)) {
let table: lua.Identifier;
if (initializer !== undefined && ts.isIdentifier(initializer)) {
table = transformIdentifier(context, initializer);
} else {
let table: lua.Expression;
if (initializer) {
// Contain the expression in a temporary variable
if (initializer) {
table = context.createTempNameForNode(initializer);
let expression = context.transformExpression(initializer);
if (isMultiReturnCall(context, initializer)) {
expression = wrapInTable(expression);
}
statements.push(lua.createVariableDeclarationStatement(table, expression));
} else {
table = lua.createAnonymousIdentifier();
let expression = context.transformExpression(initializer);
if (isMultiReturnCall(context, initializer)) {
expression = wrapInTable(expression);
}
const [moveStatements, movedExpr] = transformInPrecedingStatementScope(context, () =>
moveToPrecedingTemp(context, expression, initializer)
);
statements.push(...moveStatements);
table = movedExpr;
} else {
table = lua.createAnonymousIdentifier();
}
statements.push(...transformBindingPattern(context, bindingPattern, table));
return statements;
Expand Down
3 changes: 2 additions & 1 deletion test/translation/__snapshots__/transformation.spec.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,8 @@ value1 = obj.value1
value2 = obj.value2
obj2 = {value3 = 1, value4 = 2}
value3 = obj2.value3
value4 = obj2.value4
local ____obj2_0 = obj2
value4 = ____obj2_0.value4
function fun1(self)
end
fun2 = function()
Expand Down
44 changes: 44 additions & 0 deletions test/unit/destructuring.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,28 @@ test.each(testCases)("in variable declaration (%p)", ({ binding, value }) => {
`.expectToMatchJsResult();
});

test.each(testCases)("in variable declaration from const variable (%p)", ({ binding, value }) => {
util.testFunction`
let ${allBindings};
{
const v: any = ${value};
const ${binding} = v;
return { ${allBindings} };
}
`.expectToMatchJsResult();
});

test.each(testCases)("in variable declaration from this (%p)", ({ binding, value }) => {
util.testFunction`
let ${allBindings};
function test(this: any) {
const ${binding} = this;
return { ${allBindings} };
}
return test.call(${value});
`.expectToMatchJsResult();
});

test.each(testCases)("in exported variable declaration (%p)", ({ binding, value }) => {
util.testModule`
export const ${binding} = ${value};
Expand Down Expand Up @@ -101,6 +123,28 @@ test.each(assignmentTestCases)("in assignment expression (%p)", ({ binding, valu
`.expectToMatchJsResult();
});

test.each(assignmentTestCases)("in assignment expression from const variable (%p)", ({ binding, value }) => {
util.testFunction`
let ${allBindings};
const obj = { prop: false };
const v: any = ${value};
const expressionResult = (${binding} = v);
return { ${allBindings}, expressionResult };
`.expectToMatchJsResult();
});

test.each(assignmentTestCases)("in assignment expression from this (%p)", ({ binding, value }) => {
util.testFunction`
let ${allBindings};
const obj = { prop: false };
function test(this: any) {
const expressionResult = (${binding} = this);
return { ${allBindings}, obj, expressionResult };
}
return test.call(${value});
`.expectToMatchJsResult();
});

test.each(["[]", "{}"])("empty binding pattern", bindingPattern => {
util.testFunction`
let i = 1;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ end"

exports[`invalid $multi call (const [a = 0] = $multi()): diagnostics 1`] = `"main.ts(2,25): error TSTL: The $multi function must be called in a return statement."`;

exports[`invalid $multi call (const {} = $multi();): code 1`] = `"local _____24multi_result_0 = {{____(_G)}}"`;
exports[`invalid $multi call (const {} = $multi();): code 1`] = `"local ____temp_0 = {{____(_G)}}"`;

exports[`invalid $multi call (const {} = $multi();): diagnostics 1`] = `"main.ts(2,20): error TSTL: The $multi function must be called in a return statement."`;

Expand Down Expand Up @@ -219,10 +219,10 @@ local function multi(self, ...)
return ...
end
local a
local _____24multi_result_0 = {____(nil, 1)}
a = _____24multi_result_0[1]
local ____temp_0 = {____(nil, 1)}
a = ____temp_0[1]
____exports.a = a
if _____24multi_result_0 then
if ____temp_0 then
a = a + 1
____exports.a = a
end
Expand Down