@@ -2,9 +2,11 @@ import * as ts from "typescript";
2
2
import * as lua from "../../../LuaAST" ;
3
3
import { cast , assertNever } from "../../../utils" ;
4
4
import { TransformationContext } from "../../context" ;
5
- import { transformInPrecedingStatementScope } from "../../utils/preceding-statements" ;
5
+ import { transformInPrecedingStatementScope , WithPrecedingStatements } from "../../utils/preceding-statements" ;
6
6
import { transformBinaryOperation } from "./index" ;
7
7
import { transformAssignmentWithRightPrecedingStatements } from "./assignments" ;
8
+ import { isArrayLength } from "./destructuring-assignments" ;
9
+ import { LuaLibFeature , transformLuaLibFunction } from "../../utils/lualib" ;
8
10
9
11
function isLuaExpressionWithSideEffect ( expression : lua . Expression ) {
10
12
return ! ( lua . isLiteral ( expression ) || lua . isIdentifier ( expression ) ) ;
@@ -63,14 +65,26 @@ export const isCompoundAssignmentToken = (token: ts.BinaryOperator): token is ts
63
65
export const unwrapCompoundAssignmentToken = ( token : ts . CompoundAssignmentOperator ) : CompoundAssignmentToken =>
64
66
compoundToAssignmentTokens [ token ] ;
65
67
66
- export function transformCompoundAssignment (
68
+ function transformCompoundAssignment (
67
69
context : TransformationContext ,
68
70
expression : ts . Expression ,
69
71
lhs : ts . Expression ,
70
72
rhs : ts . Expression ,
71
73
operator : CompoundAssignmentToken ,
72
74
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
+
74
88
const left = cast ( context . transformExpression ( lhs ) , lua . isAssignmentLeftHandSideExpression ) ;
75
89
const [ rightPrecedingStatements , right ] = transformInPrecedingStatementScope ( context , ( ) =>
76
90
context . transformExpression ( rhs )
@@ -101,13 +115,13 @@ export function transformCompoundAssignment(
101
115
) ;
102
116
const assignStatement = lua . createAssignmentStatement ( accessExpression , operatorExpression ) ;
103
117
return {
104
- statements : [ objAndIndexDeclaration , ...precedingStatements , tmpDeclaration , assignStatement ] ,
118
+ precedingStatements : [ objAndIndexDeclaration , ...precedingStatements , tmpDeclaration , assignStatement ] ,
105
119
result : tmp ,
106
120
} ;
107
121
} else {
108
122
if ( isSetterSkippingCompoundAssignmentOperator ( operator ) ) {
109
123
return {
110
- statements : [
124
+ precedingStatements : [
111
125
objAndIndexDeclaration ,
112
126
...transformSetterSkippingCompoundAssignment (
113
127
accessExpression ,
@@ -133,7 +147,7 @@ export function transformCompoundAssignment(
133
147
const tmpDeclaration = lua . createVariableDeclarationStatement ( tmp , operatorExpression ) ;
134
148
const assignStatement = lua . createAssignmentStatement ( accessExpression , tmp ) ;
135
149
return {
136
- statements : [ objAndIndexDeclaration , ...precedingStatements , tmpDeclaration , assignStatement ] ,
150
+ precedingStatements : [ objAndIndexDeclaration , ...precedingStatements , tmpDeclaration , assignStatement ] ,
137
151
result : tmp ,
138
152
} ;
139
153
}
@@ -158,11 +172,19 @@ export function transformCompoundAssignment(
158
172
operatorExpression ,
159
173
rightPrecedingStatements
160
174
) ;
161
- return { statements : [ tmpDeclaration , ...precedingStatements , ...assignStatements ] , result : tmpIdentifier } ;
175
+ return {
176
+ precedingStatements : [ tmpDeclaration , ...precedingStatements , ...assignStatements ] ,
177
+ result : tmpIdentifier ,
178
+ } ;
162
179
} else {
163
180
if ( rightPrecedingStatements . length > 0 && isSetterSkippingCompoundAssignmentOperator ( operator ) ) {
164
181
return {
165
- statements : transformSetterSkippingCompoundAssignment ( left , operator , right , rightPrecedingStatements ) ,
182
+ precedingStatements : transformSetterSkippingCompoundAssignment (
183
+ left ,
184
+ operator ,
185
+ right ,
186
+ rightPrecedingStatements
187
+ ) ,
166
188
result : left ,
167
189
} ;
168
190
}
@@ -183,7 +205,7 @@ export function transformCompoundAssignment(
183
205
operatorExpression ,
184
206
precedingStatements
185
207
) ;
186
- return { statements, result : left } ;
208
+ return { precedingStatements : statements , result : left } ;
187
209
}
188
210
}
189
211
@@ -196,8 +218,15 @@ export function transformCompoundAssignmentExpression(
196
218
operator : CompoundAssignmentToken ,
197
219
isPostfix : boolean
198
220
) : 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 ) ;
201
230
return result ;
202
231
}
203
232
@@ -208,6 +237,18 @@ export function transformCompoundAssignmentStatement(
208
237
rhs : ts . Expression ,
209
238
operator : CompoundAssignmentToken
210
239
) : 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
+
211
252
const left = cast ( context . transformExpression ( lhs ) , lua . isAssignmentLeftHandSideExpression ) ;
212
253
let [ rightPrecedingStatements , right ] = transformInPrecedingStatementScope ( context , ( ) =>
213
254
context . transformExpression ( rhs )
@@ -319,3 +360,31 @@ function transformSetterSkippingCompoundAssignment(
319
360
10000
code>
) ,
320
361
] ;
321
362
}
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