@@ -2,9 +2,11 @@ import * as ts from "typescript";
22import * as lua from "../../../LuaAST" ;
33import { cast , assertNever } from "../../../utils" ;
44import { TransformationContext } from "../../context" ;
5- import { transformInPrecedingStatementScope } from "../../utils/preceding-statements" ;
5+ import { transformInPrecedingStatementScope , WithPrecedingStatements } from "../../utils/preceding-statements" ;
66import { transformBinaryOperation } from "./index" ;
77import { transformAssignmentWithRightPrecedingStatements } from "./assignments" ;
8+ import { isArrayLength } from "./destructuring-assignments" ;
9+ import { LuaLibFeature , transformLuaLibFunction } from "../../utils/lualib" ;
810
911function isLuaExpressionWithSideEffect ( expression : lua . Expression ) {
1012 return ! ( lua . isLiteral ( expression ) || lua . isIdentifier ( expression ) ) ;
@@ -63,14 +65,26 @@ export const isCompoundAssignmentToken = (token: ts.BinaryOperator): token is ts
6365export const unwrapCompoundAssignmentToken = ( token : ts . CompoundAssignmentOperator ) : CompoundAssignmentToken =>
6466 compoundToAssignmentTokens [ token ] ;
6567
66- export function transformCompoundAssignment (
68+ function transformCompoundAssignment (
6769 context : TransformationContext ,
6870 expression : ts . Expression ,
6971 lhs : ts . Expression ,
7072 rhs : ts . Expression ,
7173 operator : CompoundAssignmentToken ,
7274 isPostfix : boolean
73- ) {
75+ ) : WithPrecedingStatements < lua . Expression > {
76+ if ( isArrayLength ( context , lhs ) ) {
77+ const { precedingStatements, result : lengthSetterStatement } = transformCompoundLengthSetter (
78+ context ,
79+ expression ,
80+ lhs ,
81+ rhs ,
82+ operator
83+ ) ;
84+
85+ return { precedingStatements, result : lengthSetterStatement . expression } ;
86+ }
87+
7488 const left = cast ( context . transformExpression ( lhs ) , lua . isAssignmentLeftHandSideExpression ) ;
7589 const [ rightPrecedingStatements , right ] = transformInPrecedingStatementScope ( context , ( ) =>
7690 context . transformExpression ( rhs )
@@ -101,13 +115,13 @@ export function transformCompoundAssignment(
101115 ) ;
102116 const assignStatement = lua . createAssignmentStatement ( accessExpression , operatorExpression ) ;
103117 return {
104- statements : [ objAndIndexDeclaration , ...precedingStatements , tmpDeclaration , assignStatement ] ,
118+ precedingStatements : [ objAndIndexDeclaration , ...precedingStatements , tmpDeclaration , assignStatement ] ,
105119 result : tmp ,
106120 } ;
107121 } else {
108122 if ( isSetterSkippingCompoundAssignmentOperator ( operator ) ) {
109123 return {
110- statements : [
124+ precedingStatements : [
111125 objAndIndexDeclaration ,
112126 ...transformSetterSkippingCompoundAssignment (
113127 accessExpression ,
@@ -133,7 +147,7 @@ export function transformCompoundAssignment(
133147 const tmpDeclaration = lua . createVariableDeclarationStatement ( tmp , operatorExpression ) ;
134148 const assignStatement = lua . createAssignmentStatement ( accessExpression , tmp ) ;
135149 return {
136- statements : [ objAndIndexDeclaration , ...precedingStatements , tmpDeclaration , assignStatement ] ,
150+ precedingStatements : [ objAndIndexDeclaration , ...precedingStatements , tmpDeclaration , assignStatement ] ,
137151 result : tmp ,
138152 } ;
139153 }
@@ -158,11 +172,19 @@ export function transformCompoundAssignment(
158172 operatorExpression ,
159173 rightPrecedingStatements
160174 ) ;
161- return { statements : [ tmpDeclaration , ...precedingStatements , ...assignStatements ] , result : tmpIdentifier } ;
175+ return {
176+ precedingStatements : [ tmpDeclaration , ...precedingStatements , ...assignStatements ] ,
177+ result : tmpIdentifier ,
178+ } ;
162179 } else {
163180 if ( rightPrecedingStatements . length > 0 && isSetterSkippingCompoundAssignmentOperator ( operator ) ) {
164181 return {
165- statements : transformSetterSkippingCompoundAssignment ( left , operator , right , rightPrecedingStatements ) ,
182+ precedingStatements : transformSetterSkippingCompoundAssignment (
183+ left ,
184+ operator ,
185+ right ,
186+ rightPrecedingStatements
187+ ) ,
166188 result : left ,
167189 } ;
168190 }
@@ -183,7 +205,7 @@ export function transformCompoundAssignment(
183205 operatorExpression ,
184206 precedingStatements
185207 ) ;
186- return { statements, result : left } ;
208+ return { precedingStatements : statements , result : left } ;
187209 }
188210}
189211
@@ -196,8 +218,15 @@ export function transformCompoundAssignmentExpression(
196218 operator : CompoundAssignmentToken ,
197219 isPostfix : boolean
198220) : lua . Expression {
199- const { statements, result } = transformCompoundAssignment ( context , expression , lhs , rhs , operator , isPostfix ) ;
200- context . addPrecedingStatements ( statements ) ;
221+ const { precedingStatements, result } = transformCompoundAssignment (
222+ context ,
223+ expression ,
224+ lhs ,
225+ rhs ,
226+ operator ,
227+ isPostfix
228+ ) ;
229+ context . addPrecedingStatements ( precedingStatements ) ;
201230 return result ;
202231}
203232
@@ -208,6 +237,18 @@ export function transformCompoundAssignmentStatement(
208237 rhs : ts . Expression ,
209238 operator : CompoundAssignmentToken
210239) : lua . Statement [ ] {
240+ if ( isArrayLength ( context , lhs ) ) {
241+ const { precedingStatements, result : lengthSetterStatement } = transformCompoundLengthSetter (
242+ context ,
243+ node ,
244+ lhs ,
245+ rhs ,
246+ operator
247+ ) ;
248+
249+ return [ ...precedingStatements , lengthSetterStatement ] ;
250+ }
251+
211252 const left = cast ( context . transformExpression ( lhs ) , lua . isAssignmentLeftHandSideExpression ) ;
212253 let [ rightPrecedingStatements , right ] = transformInPrecedingStatementScope ( context , ( ) =>
213254 context . transformExpression ( rhs )
@@ -319,3 +360,31 @@ function transformSetterSkippingCompoundAssignment(
319360 ) ,
320361 ] ;
321362}
363+
364+ function transformCompoundLengthSetter (
365+ context : TransformationContext ,
366+ node : ts . Node ,
367+ lhs : ts . PropertyAccessExpression | ts . ElementAccessExpression ,
368+ rhs : ts . Expression ,
369+ operator : CompoundAssignmentToken
370+ ) : WithPrecedingStatements < lua . ExpressionStatement > {
371+ const [ rightPrecedingStatements , right ] = transformInPrecedingStatementScope ( context , ( ) =>
372+ context . transformExpression ( rhs )
373+ ) ;
374+ const table = context . transformExpression ( lhs . expression ) ;
375+ const lengthExpression = lua . createUnaryExpression ( table , lua . SyntaxKind . LengthOperator , lhs ) ;
376+ const [ precedingStatements , operatorExpression ] = transformBinaryOperation (
377+ context ,
378+ lengthExpression ,
379+ right ,
380+ rightPrecedingStatements ,
381+ operator ,
382+ node
383+ ) ;
384+
385+ const arrayLengthAssignment = lua . createExpressionStatement (
386+ transformLuaLibFunction ( context , LuaLibFeature . ArraySetLength , node , table , operatorExpression )
387+ ) ;
388+
389+ return { precedingStatements, result : arrayLengthAssignment } ;
390+ }
0 commit comments