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
4 changes: 2 additions & 2 deletions src/transformation/utils/preceding-statements.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ export interface WithPrecedingStatements<

export function transformInPrecedingStatementScope<
TReturn extends lua.Statement | lua.Statement[] | lua.Expression | lua.Expression[]
>(context: TransformationContext, transformer: () => TReturn): [lua.Statement[], TReturn] {
>(context: TransformationContext, transformer: () => TReturn): WithPrecedingStatements<TReturn> {
context.pushPrecedingStatements();
const statementOrStatements = transformer();
const precedingStatements = context.popPrecedingStatements();
return [precedingStatements, statementOrStatements];
return { precedingStatements, result: statementOrStatements };
}
9 changes: 5 additions & 4 deletions src/transformation/visitors/binary-expression/assignments.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,8 +107,9 @@ function transformDestructuredAssignmentExpression(
context: TransformationContext,
expression: ts.DestructuringAssignment
) {
let [rightPrecedingStatements, right] = transformInPrecedingStatementScope(context, () =>
context.transformExpression(expression.right)
let { precedingStatements: rightPrecedingStatements, result: right } = transformInPrecedingStatementScope(
context,
() => context.transformExpression(expression.right)
);
context.addPrecedingStatements(rightPrecedingStatements);
if (isMultiReturnCall(context, expression.right)) {
Expand Down Expand Up @@ -153,7 +154,7 @@ export function transformAssignmentExpression(
}

if (ts.isPropertyAccessExpression(expression.left) || ts.isElementAccessExpression(expression.left)) {
const [precedingStatements, right] = transformInPrecedingStatementScope(context, () =>
const { precedingStatements, result: right } = transformInPrecedingStatementScope(context, () =>
context.transformExpression(expression.right)
);

Expand Down Expand Up @@ -233,7 +234,7 @@ export function transformAssignmentStatement(
const { statements } = transformDestructuredAssignmentExpression(context, expression);
return statements;
} else {
const [precedingStatements, right] = transformInPrecedingStatementScope(context, () =>
const { precedingStatements, result: right } = transformInPrecedingStatementScope(context, () =>
context.transformExpression(expression.right)
);
return transformAssignmentWithRightPrecedingStatements(context, expression.left, right, precedingStatements);
Expand Down
35 changes: 18 additions & 17 deletions src/transformation/visitors/binary-expression/compound.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,9 @@ function transformCompoundAssignment(
}

const left = cast(context.transformExpression(lhs), lua.isAssignmentLeftHandSideExpression);
const [rightPrecedingStatements, right] = transformInPrecedingStatementScope(context, () =>
context.transformExpression(rhs)
const { precedingStatements: rightPrecedingStatements, result: right } = transformInPrecedingStatementScope(
context,
() => context.transformExpression(rhs)
);

if (lua.isTableIndexExpression(left)) {
Expand All @@ -105,7 +106,7 @@ function transformCompoundAssignment(
// ____obj[____index] = ____tmp ${replacementOperator} ${right};
// return ____tmp
const tmpDeclaration = lua.createVariableDeclarationStatement(tmp, accessExpression);
const [precedingStatements, operatorExpression] = transformBinaryOperation(
const { precedingStatements, result: operatorExpression } = transformBinaryOperation(
context,
tmp,
right,
Expand Down Expand Up @@ -136,7 +137,7 @@ function transformCompoundAssignment(
// local ____tmp = ____obj[____index] ${replacementOperator} ${right};
// ____obj[____index] = ____tmp;
// return ____tmp
const [precedingStatements, operatorExpression] = transformBinaryOperation(
const { precedingStatements, result: operatorExpression } = transformBinaryOperation(
context,
accessExpression,
right,
Expand All @@ -158,7 +159,7 @@ function transformCompoundAssignment(
// return ____tmp
const tmpIdentifier = context.createTempNameForLuaExpression(left);
const tmpDeclaration = lua.createVariableDeclarationStatement(tmpIdentifier, left);
const [precedingStatements, operatorExpression] = transformBinaryOperation(
const { precedingStatements, result: operatorExpression } = transformBinaryOperation(
context,
tmpIdentifier,
right,
Expand Down Expand Up @@ -191,7 +192,7 @@ function transformCompoundAssignment(

// Simple expressions
// ${left} = ${left} ${operator} ${right}
const [precedingStatements, operatorExpression] = transformBinaryOperation(
const { precedingStatements, result: operatorExpression } = transformBinaryOperation(
context,
left,
right,
Expand Down Expand Up @@ -250,8 +251,9 @@ export function transformCompoundAssignmentStatement(
}

const left = cast(context.transformExpression(lhs), lua.isAssignmentLeftHandSideExpression);
let [rightPrecedingStatements, right] = transformInPrecedingStatementScope(context, () =>
context.transformExpression(rhs)
const { precedingStatements: rightPrecedingStatements, result: right } = transformInPrecedingStatementScope(
context,
() => context.transformExpression(rhs)
);

if (lua.isTableIndexExpression(left) && shouldCacheTableIndexExpressions(left, rightPrecedingStatements)) {
Expand All @@ -277,8 +279,7 @@ export function transformCompoundAssignmentStatement(
];
}

let operatorExpression: lua.Expression;
[rightPrecedingStatements, operatorExpression] = transformBinaryOperation(
const { precedingStatements: rightPrecedingStatements2, result: operatorExpression } = transformBinaryOperation(
context,
accessExpression,
right,
Expand All @@ -287,16 +288,15 @@ export function transformCompoundAssignmentStatement(
node
);
const assignStatement = lua.createAssignmentStatement(accessExpression, operatorExpression);
return [objAndIndexDeclaration, ...rightPrecedingStatements, assignStatement];
return [objAndIndexDeclaration, ...rightPrecedingStatements2, assignStatement];
} else {
if (isSetterSkippingCompoundAssignmentOperator(operator)) {
return transformSetterSkippingCompoundAssignment(left, operator, right, rightPrecedingStatements, node);
}

// Simple statements
// ${left} = ${left} ${replacementOperator} ${right}
let operatorExpression: lua.Expression;
[rightPrecedingStatements, operatorExpression] = transformBinaryOperation(
const { precedingStatements: rightPrecedingStatements2, result: operatorExpression } = transformBinaryOperation(
context,
left,
right,
Expand All @@ -308,7 +308,7 @@ export function transformCompoundAssignmentStatement(
context,
lhs,
operatorExpression,
rightPrecedingStatements
rightPrecedingStatements2
);
}
}
Expand Down Expand Up @@ -368,12 +368,13 @@ function transformCompoundLengthSetter(
rhs: ts.Expression,
operator: CompoundAssignmentToken
): WithPrecedingStatements<lua.ExpressionStatement> {
const [rightPrecedingStatements, right] = transformInPrecedingStatementScope(context, () =>
context.transformExpression(rhs)
const { precedingStatements: rightPrecedingStatements, result: right } = transformInPrecedingStatementScope(
context,
() => context.transformExpression(rhs)
);
const table = context.transformExpression(lhs.expression);
const lengthExpression = lua.createUnaryExpression(table, lua.SyntaxKind.LengthOperator, lhs);
const [precedingStatements, operatorExpression] = transformBinaryOperation(
const { precedingStatements, result: operatorExpression } = transformBinaryOperation(
context,
lengthExpression,
right,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,15 +97,14 @@ function transformArrayLiteralAssignmentPattern(
lua.SyntaxKind.EqualityOperator
);

const [defaultPrecedingStatements, defaultAssignmentStatements] = transformInPrecedingStatementScope(
context,
() =>
const { precedingStatements: defaultPrecedingStatements, result: defaultAssignmentStatements } =
transformInPrecedingStatementScope(context, () =>
transformAssignment(
context,
(element as ts.BinaryExpression).left,
context.transformExpression((element as ts.BinaryExpression).right)
)
);
);

// Keep preceding statements inside if block
defaultAssignmentStatements.unshift(...defaultPrecedingStatements);
Expand All @@ -126,7 +125,7 @@ function transformArrayLiteralAssignmentPattern(
case ts.SyntaxKind.Identifier:
case ts.SyntaxKind.PropertyAccessExpression:
case ts.SyntaxKind.ElementAccessExpression:
const [precedingStatements, statements] = transformInPrecedingStatementScope(context, () =>
const { precedingStatements, result: statements } = transformInPrecedingStatementScope(context, () =>
transformAssignment(context, element, indexedRoot, rightHasPrecedingStatements)
);
return [...precedingStatements, ...statements]; // Keep preceding statements in order
Expand All @@ -144,14 +143,15 @@ function transformArrayLiteralAssignmentPattern(
lua.createNumericLiteral(index)
);

const [spreadPrecedingStatements, spreadStatements] = transformInPrecedingStatementScope(context, () =>
transformAssignment(
context,
(element as ts.SpreadElement).expression,
restElements,
rightHasPrecedingStatements
)
);
const { precedingStatements: spreadPrecedingStatements, result: spreadStatements } =
transformInPrecedingStatementScope(context, () =>
transformAssignment(
context,
(element as ts.SpreadElement).expression,
restElements,
rightHasPrecedingStatements
)
);
return [...spreadPrecedingStatements, ...spreadStatements]; // Keep preceding statements in order
case ts.SyntaxKind.OmittedExpression:
return [];
Expand Down Expand Up @@ -279,9 +279,8 @@ function transformPropertyAssignment(
const left = cast(context.transformExpression(node.initializer.left), lua.isTableIndexExpression);

const rightExpression = node.initializer.right;
const [defaultPrecedingStatements, defaultExpression] = transformInPrecedingStatementScope(context, () =>
context.transformExpression(rightExpression)
);
const { precedingStatements: defaultPrecedingStatements, result: defaultExpression } =
transformInPrecedingStatementScope(context, () => context.transformExpression(rightExpression));

const tableTemp = context.createTempNameForLuaExpression(left.table);
const indexTemp = context.createTempNameForLuaExpression(left.index);
Expand All @@ -292,7 +291,7 @@ function transformPropertyAssignment(
);

// obj[index] = extractingExpression ?? defaultExpression
const [rightPrecedingStatements, rhs] = transformBinaryOperation(
const { precedingStatements: rightPrecedingStatements, result: rhs } = transformBinaryOperation(
context,
extractingExpression,
defaultExpression,
Expand Down
44 changes: 27 additions & 17 deletions src/transformation/visitors/binary-expression/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import {
} from "./compound";
import { assert } from "../../../utils";
import { transformOrderedExpressions } from "../expression-list";
import { transformInPrecedingStatementScope } from "../../utils/preceding-statements";
import { transformInPrecedingStatementScope, WithPrecedingStatements } from "../../utils/preceding-statements";

type ShortCircuitOperator =
| ts.SyntaxKind.AmpersandAmpersandToken
Expand Down Expand Up @@ -100,7 +100,7 @@ export function createShortCircuitBinaryExpressionPrecedingStatements(
rightPrecedingStatements: lua.Statement[],
operator: ShortCircuitOperator,
node?: ts.BinaryExpression
): [lua.Statement[], lua.Expression] {
): WithPrecedingStatements<lua.Expression> {
const conditionIdentifier = context.createTempNameForLuaExpression(lhs);
const assignmentStatement = lua.createVariableDeclarationStatement(conditionIdentifier, lhs, node?.left);

Expand Down Expand Up @@ -132,19 +132,19 @@ export function createShortCircuitBinaryExpressionPrecedingStatements(
undefined,
node?.left
);
return [[assignmentStatement, ifStatement], conditionIdentifier];
return { precedingStatements: [assignmentStatement, ifStatement], result: conditionIdentifier };
}

function transformShortCircuitBinaryExpression(
context: TransformationContext,
node: ts.BinaryExpression,
operator: ShortCircuitOperator
): [lua.Statement[], lua.Expression] {
): WithPrecedingStatements<lua.Expression> {
const lhs = context.transformExpression(node.left);
const [rightPrecedingStatements, rhs] = transformInPrecedingStatementScope(context, () =>
const { precedingStatements, result } = transformInPrecedingStatementScope(context, () =>
context.transformExpression(node.right)
);
return transformBinaryOperation(context, lhs, rhs, rightPrecedingStatements, operator, node);
return transformBinaryOperation(context, lhs, result, precedingStatements, operator, node);
}

export function transformBinaryOperation(
Expand All @@ -154,7 +154,7 @@ export function transformBinaryOperation(
rightPrecedingStatements: lua.Statement[],
operator: BitOperator | SimpleOperator | ts.SyntaxKind.QuestionQuestionToken,
node: ts.Node
): [lua.Statement[], lua.Expression] {
): WithPrecedingStatements<lua.Expression> {
if (rightPrecedingStatements.length > 0 && isShortCircuitOperator(operator)) {
assert(ts.isBinaryExpression(node));
return createShortCircuitBinaryExpressionPrecedingStatements(
Expand All @@ -167,10 +167,10 @@ export function transformBinaryOperation(
);
}

return [
rightPrecedingStatements,
transformBinaryOperationWithNoPrecedingStatements(context, left, right, operator, node),
];
return {
precedingStatements: rightPrecedingStatements,
result: transformBinaryOperationWithNoPrecedingStatements(context, left, right, operator, node),
};
}

export const transformBinaryExpression: FunctionVisitor<ts.BinaryExpression> = (node, context) => {
Expand Down Expand Up @@ -216,7 +216,7 @@ export const transformBinaryExpression: FunctionVisitor<ts.BinaryExpression> = (

case ts.SyntaxKind.CommaToken: {
const statements = context.transformStatements(ts.factory.createExpressionStatement(node.left));
const [precedingStatements, result] = transformInPrecedingStatementScope(context, () =>
const { precedingStatements, result } = transformInPrecedingStatementScope(context, () =>
context.transformExpression(node.right)
);
statements.push(...precedingStatements);
Expand All @@ -227,17 +227,27 @@ export const transformBinaryExpression: FunctionVisitor<ts.BinaryExpression> = (
case ts.SyntaxKind.QuestionQuestionToken:
case ts.SyntaxKind.AmpersandAmpersandToken:
case ts.SyntaxKind.BarBarToken: {
const [precedingStatements, result] = transformShortCircuitBinaryExpression(context, node, operator);
const { precedingStatements, result } = transformShortCircuitBinaryExpression(context, node, operator);
context.addPrecedingStatements(precedingStatements);
return result;
}
}

let [precedingStatements, [lhs, rhs]] = transformInPrecedingStatementScope(context, () =>
const {
precedingStatements: orderedExpressionPrecedingStatements,
result: [lhs, rhs],
} = transformInPrecedingStatementScope(context, () =>
transformOrderedExpressions(context, [node.left, node.right])
);
let result: lua.Expression;
[precedingStatements, result] = transformBinaryOperation(context, lhs, rhs, precedingStatements, operator, node);

const { precedingStatements, result } = transformBinaryOperation(
context,
lhs,
rhs,
orderedExpressionPrecedingStatements,
operator,
node
);
context.addPrecedingStatements(precedingStatements);
return result;
};
Expand Down Expand Up @@ -277,7 +287,7 @@ function transformNullishCoalescingOperationNoPrecedingStatements(
// Check if we can take a shortcut to 'lhs or rhs' if the left-hand side cannot be 'false'.
if (canBeFalsyWhenNotNull(context, lhsType)) {
// reuse logic from case with preceding statements
const [precedingStatements, result] = createShortCircuitBinaryExpressionPrecedingStatements(
const { precedingStatements, result } = createShortCircuitBinaryExpressionPrecedingStatements(
context,
transformedLeft,
transformedRight,
Expand Down
10 changes: 4 additions & 6 deletions src/transformation/visitors/call.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,9 +80,8 @@ export function transformCallAndArguments(
signature?: ts.Signature,
callContext?: ts.Expression
): [lua.Expression, lua.Expression[]] {
const [argPrecedingStatements, transformedArguments] = transformInPrecedingStatementScope(context, () =>
transformArguments(context, params, signature, callContext)
);
const { precedingStatements: argPrecedingStatements, result: transformedArguments } =
transformInPrecedingStatementScope(context, () => transformArguments(context, params, signature, callContext));
return transformCallWithArguments(context, callExpression, transformedArguments, argPrecedingStatements);
}

Expand Down Expand Up @@ -125,9 +124,8 @@ export function transformContextualCallExpression(
}
const left = ts.isCallExpression(node) ? getCalledExpression(node) : node.tag;

let [argPrecedingStatements, transformedArguments] = transformInPrecedingStatementScope(context, () =>
transformArguments(context, args, signature)
);
let { precedingStatements: argPrecedingStatements, result: transformedArguments } =
transformInPrecedingStatementScope(context, () => transformArguments(context, args, signature));

if (
ts.isPropertyAccessExpression(left) &&
Expand Down
2 changes: 1 addition & 1 deletion src/transformation/visitors/class/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ export const transformClassDeclaration: FunctionVisitor<ts.ClassLikeDeclaration>
// If declaration is a default export, transform to export variable assignment instead
if (hasDefaultExportModifier(declaration)) {
// Class declaration including assignment to ____exports.default are in preceding statements
const [precedingStatements] = transformInPrecedingStatementScope(context, () => {
const { precedingStatements } = transformInPrecedingStatementScope(context, () => {
transformClassAsExpression(declaration, context);
return [];
});
Expand Down
2 changes: 1 addition & 1 deletion src/transformation/visitors/class/members/fields.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ export function transformClassInstanceFields(
const statements: lua.Statement[] = [];

for (const f of instanceFields) {
const [precedingStatements, statement] = transformInPrecedingStatementScope(context, () => {
const { precedingStatements, result: statement } = transformInPrecedingStatementScope(context, () => {
// Get identifier
const fieldName = transformPropertyName(context, f.name);

Expand Down
Loading