@@ -172,10 +172,48 @@ export class LuaPrinter {
172172 }
173173
174174 private printBlock ( block : tstl . Block ) : SourceNode {
175- return this . createSourceNode (
176- block ,
177- this . ignoreDeadStatements ( block . statements ) . map ( s => this . printStatement ( s ) )
175+ return this . createSourceNode ( block , this . printStatementArray ( block . statements ) ) ;
176+ }
177+
178+ private statementMayRequireSemiColon ( statement : tstl . Statement ) : boolean {
179+ // Types of statements that could create ambiguous syntax if followed by parenthesis
180+ return tstl . isVariableDeclarationStatement ( statement )
181+ || tstl . isAssignmentStatement ( statement )
182+ || tstl . isExpressionStatement ( statement ) ;
183+ }
184+
185+ private nodeStartsWithParenthesis ( sourceNode : SourceNode ) : boolean {
186+ let result : boolean | undefined ;
187+ sourceNode . walk ( chunk => {
188+ if ( result === undefined ) {
189+ chunk = chunk . trimLeft ( ) ; // Ignore leading whitespace
190+
191+ if ( chunk . length > 0 ) {
192+ result = chunk . startsWith ( "(" ) ;
193+ }
194+ }
195+ } ) ;
196+ return result || false ;
197+ }
198+
199+ private printStatementArray ( statements : tstl . Statement [ ] ) : SourceChunk [ ] {
200+ const statementNodes : SourceNode [ ] = [ ] ;
201+ statements = this . removeDeadAndEmptyStatements ( statements ) ;
202+ statements . forEach (
203+ ( s , i ) => {
204+ const node = this . printStatement ( s ) ;
205+
206+ if ( i > 0
207+ && this . statementMayRequireSemiColon ( statements [ i - 1 ] )
208+ && this . nodeStartsWithParenthesis ( node ) )
209+ {
210+ statementNodes [ i - 1 ] . add ( ";" ) ;
211+ }
212+
213+ statementNodes . push ( node ) ;
214+ }
178215 ) ;
216+ return statementNodes . length > 0 ? [ ...this . joinChunks ( "\n" , statementNodes ) , "\n" ] : [ ] ;
179217 }
180218
181219 private printStatement ( statement : tstl . Statement ) : SourceNode {
@@ -214,13 +252,11 @@ export class LuaPrinter {
214252 private printDoStatement ( statement : tstl . DoStatement ) : SourceNode {
215253 const chunks : SourceChunk [ ] = [ ] ;
216254
217- if ( statement . statements && statement . statements . length > 0 ) {
218- chunks . push ( this . indent ( "do\n" ) ) ;
219- this . pushIndent ( ) ;
220- chunks . push ( ...this . ignoreDeadStatements ( statement . statements ) . map ( s => this . printStatement ( s ) ) ) ;
221- this . popIndent ( ) ;
222- chunks . push ( this . indent ( "end\n" ) ) ;
223- }
255+ chunks . push ( this . indent ( "do\n" ) ) ;
256+ this . pushIndent ( ) ;
257+ chunks . push ( ...this . printStatementArray ( statement . statements ) ) ;
258+ this . popIndent ( ) ;
259+ chunks . push ( this . indent ( "end" ) ) ;
224260
225261 return this . concatNodes ( ...chunks ) ;
226262 }
@@ -233,7 +269,6 @@ export class LuaPrinter {
233269 if ( tstl . isFunctionDefinition ( statement ) ) {
234270 // Print all local functions as `local function foo()` instead of `local foo = function` to allow recursion
235271 chunks . push ( this . printFunctionDefinition ( statement ) ) ;
236- chunks . push ( "\n" ) ;
237272
238273 } else {
239274 chunks . push ( ...this . joinChunks ( ", " , statement . left . map ( e => this . printExpression ( e ) ) ) ) ;
@@ -242,7 +277,6 @@ export class LuaPrinter {
242277 chunks . push ( " = " ) ;
243278 chunks . push ( ...this . joinChunks ( ", " , statement . right . map ( e => this . printExpression ( e ) ) ) ) ;
244279 }
245- chunks . push ( ";\n" ) ;
246280 }
247281
248282 return this . concatNodes ( ...chunks ) ;
@@ -260,15 +294,13 @@ export class LuaPrinter {
260294 const name = this . printExpression ( statement . left [ 0 ] ) ;
261295 if ( tsHelper . isValidLuaFunctionDeclarationName ( name . toString ( ) ) ) {
262296 chunks . push ( this . printFunctionDefinition ( statement ) ) ;
263- chunks . push ( "\n" ) ;
264297 return this . createSourceNode ( statement , chunks ) ;
265298 }
266299 }
267300
268301 chunks . push ( ...this . joinChunks ( ", " , statement . left . map ( e => this . printExpression ( e ) ) ) ) ;
269302 chunks . push ( " = " ) ;
270303 chunks . push ( ...this . joinChunks ( ", " , statement . right . map ( e => this . printExpression ( e ) ) ) ) ;
271- chunks . push ( ";\n" ) ;
272304
273305 return this . createSourceNode ( statement , chunks ) ;
274306 }
@@ -292,10 +324,10 @@ export class LuaPrinter {
292324 this . pushIndent ( ) ;
293325 chunks . push ( this . printBlock ( statement . elseBlock ) ) ;
294326 this . popIndent ( ) ;
295- chunks . push ( this . indent ( "end\n " ) ) ;
327+ chunks . push ( this . indent ( "end" ) ) ;
296328 }
297329 } else {
298- chunks . push ( this . indent ( "end\n " ) ) ;
330+ chunks . push ( this . indent ( "end" ) ) ;
299331 }
300332
301333 return this . concatNodes ( ...chunks ) ;
@@ -310,7 +342,7 @@ export class LuaPrinter {
310342 chunks . push ( this . printBlock ( statement . body ) ) ;
311343 this . popIndent ( ) ;
312344
313- chunks . push ( this . indent ( "end\n " ) ) ;
345+ chunks . push ( this . indent ( "end" ) ) ;
314346
315347 return this . concatNodes ( ...chunks ) ;
316348 }
@@ -324,7 +356,7 @@ export class LuaPrinter {
324356 chunks . push ( this . printBlock ( statement . body ) ) ;
325357 this . popIndent ( ) ;
326358
327- chunks . push ( this . indent ( "until " ) , this . printExpression ( statement . condtion ) , ";\n" ) ;
359+ chunks . push ( this . indent ( "until " ) , this . printExpression ( statement . condtion ) ) ;
328360
329361 return this . concatNodes ( ...chunks ) ;
330362 }
@@ -347,7 +379,7 @@ export class LuaPrinter {
347379 chunks . push ( this . printBlock ( statement . body ) ) ;
348380 this . popIndent ( ) ;
349381
350- chunks . push ( this . indent ( "end\n " ) ) ;
382+ chunks . push ( this . indent ( "end" ) ) ;
351383
352384 return this . concatNodes ( ...chunks ) ;
353385 }
@@ -363,38 +395,37 @@ export class LuaPrinter {
363395 this . pushIndent ( ) ;
364396 chunks . push ( this . printBlock ( statement . body ) ) ;
365397 this . popIndent ( ) ;
366- chunks . push ( this . indent ( "end\n " ) ) ;
398+ chunks . push ( this . indent ( "end" ) ) ;
367399
368400 return this . createSourceNode ( statement , chunks ) ;
369401 }
370402
371403 private printGotoStatement ( statement : tstl . GotoStatement ) : SourceNode {
372- return this . createSourceNode ( statement , [ this . indent ( "goto " ) , statement . label , ";\n" ] ) ;
404+ return this . createSourceNode ( statement , [ this . indent ( "goto " ) , statement . label ] ) ;
373405 }
374406
375407 private printLabelStatement ( statement : tstl . LabelStatement ) : SourceNode {
376- return this . createSourceNode ( statement , [ this . indent ( "::" ) , statement . name , "::\n " ] ) ;
408+ return this . createSourceNode ( statement , [ this . indent ( "::" ) , statement . name , "::" ] ) ;
377409 }
378410
379411 private printReturnStatement ( statement : tstl . ReturnStatement ) : SourceNode {
380412 if ( ! statement . expressions || statement . expressions . length === 0 ) {
381- return this . createSourceNode ( statement , this . indent ( "return;\n " ) ) ;
413+ return this . createSourceNode ( statement , this . indent ( "return" ) ) ;
382414 }
383415
384416 const chunks : SourceChunk [ ] = [ ] ;
385417
386418 chunks . push ( ...this . joinChunks ( ", " , statement . expressions . map ( e => this . printExpression ( e ) ) ) ) ;
387- chunks . push ( ";\n" ) ;
388419
389420 return this . createSourceNode ( statement , [ this . indent ( ) , "return " , ...chunks ] ) ;
390421 }
391422
392423 private printBreakStatement ( statement : tstl . BreakStatement ) : SourceNode {
393- return this . createSourceNode ( statement , this . indent ( "break;\n " ) ) ;
424+ return this . createSourceNode ( statement , this . indent ( "break" ) ) ;
394425 }
395426
396427 private printExpressionStatement ( statement : tstl . ExpressionStatement ) : SourceNode {
397- return this . concatNodes ( this . indent ( ) , this . printExpression ( statement . expression ) , ";\n" ) ;
428+ return this . concatNodes ( this . indent ( ) , this . printExpression ( statement . expression ) ) ;
398429 }
399430
400431 // Expressions
@@ -485,7 +516,6 @@ export class LuaPrinter {
485516 const returnNode : SourceChunk [ ] = [
486517 "return " ,
487518 ...this . joinChunks ( ", " , returnStatement . expressions . map ( e => this . printExpression ( e ) ) ) ,
488- ";" ,
489519 ] ;
490520 chunks . push ( this . createSourceNode ( returnStatement , returnNode ) ) ;
491521 chunks . push ( " end" ) ;
@@ -621,10 +651,16 @@ export class LuaPrinter {
621651 return LuaPrinter . operatorMap [ kind ] ;
622652 }
623653
624- private ignoreDeadStatements ( statements : tstl . Statement [ ] ) : tstl . Statement [ ] {
654+ private isEmptyStatement ( statement : tstl . Statement ) : boolean {
655+ return tstl . isDoStatement ( statement ) && ( ! statement . statements || statement . statements . length === 0 ) ;
656+ }
657+
658+ private removeDeadAndEmptyStatements ( statements : tstl . Statement [ ] ) : tstl . Statement [ ] {
625659 const aliveStatements = [ ] ;
626660 for ( const statement of statements ) {
627- aliveStatements . push ( statement ) ;
661+ if ( ! this . isEmptyStatement ( statement ) ) {
662+ aliveStatements . push ( statement ) ;
663+ }
628664 if ( tstl . isReturnStatement ( statement ) ) {
629665 break ;
630666 }
0 commit comments