@@ -213,25 +213,37 @@ export class LuaPrinter {
213213
214214 private printDoStatement ( statement : tstl . DoStatement ) : SourceNode {
215215 const chunks : SourceChunk [ ] = [ ] ;
216- chunks . push ( this . indent ( "do\n" ) ) ;
217- this . pushIndent ( ) ;
218- chunks . push ( ...this . ignoreDeadStatements ( statement . statements ) . map ( s => this . printStatement ( s ) ) ) ;
219- this . popIndent ( ) ;
220- chunks . push ( this . indent ( "end\n" ) ) ;
216+
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+ }
221224
222225 return this . concatNodes ( ...chunks ) ;
223226 }
224227
225228 private printVariableDeclarationStatement ( statement : tstl . VariableDeclarationStatement ) : SourceNode {
226229 const chunks : SourceChunk [ ] = [ ] ;
230+
227231 chunks . push ( this . indent ( "local " ) ) ;
228- chunks . push ( ...this . joinChunks ( ", " , statement . left . map ( e => this . printExpression ( e ) ) ) ) ;
229232
230- if ( statement . right ) {
231- chunks . push ( " = " ) ;
232- chunks . push ( ...this . joinChunks ( ", " , statement . right . map ( e => this . printExpression ( e ) ) ) ) ;
233+ if ( tstl . isFunctionDefinition ( statement ) ) {
234+ // Print all local functions as `local function foo()` instead of `local foo = function` to allow recursion
235+ chunks . push ( this . printFunctionDefinition ( statement ) ) ;
236+ chunks . push ( "\n" ) ;
237+
238+ } else {
239+ chunks . push ( ...this . joinChunks ( ", " , statement . left . map ( e => this . printExpression ( e ) ) ) ) ;
240+
241+ if ( statement . right ) {
242+ chunks . push ( " = " ) ;
243+ chunks . push ( ...this . joinChunks ( ", " , statement . right . map ( e => this . printExpression ( e ) ) ) ) ;
244+ }
245+ chunks . push ( ";\n" ) ;
233246 }
234- chunks . push ( ";\n" ) ;
235247
236248 return this . concatNodes ( ...chunks ) ;
237249 }
@@ -240,6 +252,19 @@ export class LuaPrinter {
240252 const chunks : SourceChunk [ ] = [ ] ;
241253
242254 chunks . push ( this . indent ( ) ) ;
255+
256+ if ( tstl . isFunctionDefinition ( statement )
257+ && ( statement . right [ 0 ] . flags & tstl . FunctionExpressionFlags . Declaration ) !== 0 )
258+ {
259+ // Use `function foo()` instead of `foo = function()`
260+ const name = this . printExpression ( statement . left [ 0 ] ) ;
261+ if ( tsHelper . isValidLuaFunctionDeclarationName ( name . toString ( ) ) ) {
262+ chunks . push ( this . printFunctionDefinition ( statement ) ) ;
263+ chunks . push ( "\n" ) ;
264+ return this . createSourceNode ( statement , chunks ) ;
265+ }
266+ }
267+
243268 chunks . push ( ...this . joinChunks ( ", " , statement . left . map ( e => this . printExpression ( e ) ) ) ) ;
244269 chunks . push ( " = " ) ;
245270 chunks . push ( ...this . joinChunks ( ", " , statement . right . map ( e => this . printExpression ( e ) ) ) ) ;
@@ -359,7 +384,6 @@ export class LuaPrinter {
359384 const chunks : SourceChunk [ ] = [ ] ;
360385
361386 chunks . push ( ...this . joinChunks ( ", " , statement . expressions . map ( e => this . printExpression ( e ) ) ) ) ;
362-
363387 chunks . push ( ";\n" ) ;
364388
365389 return this . createSourceNode ( statement , [ this . indent ( ) , "return " , ...chunks ] ) ;
@@ -436,7 +460,7 @@ export class LuaPrinter {
436460 }
437461 }
438462
439- private printFunctionExpression ( expression : tstl . FunctionExpression ) : SourceNode {
463+ private printFunctionParameters ( expression : tstl . FunctionExpression ) : SourceChunk [ ] {
440464 const parameterChunks : SourceNode [ ] = expression . params
441465 ? expression . params . map ( i => this . printIdentifier ( i ) )
442466 : [ ] ;
@@ -445,10 +469,46 @@ export class LuaPrinter {
445469 parameterChunks . push ( this . printDotsLiteral ( expression . dots ) ) ;
446470 }
447471
472+ return this . joinChunks ( ", " , parameterChunks ) ;
473+ }
474+
475+ private printFunctionExpression ( expression : tstl . FunctionExpression ) : SourceNode {
448476 const chunks : SourceChunk [ ] = [ ] ;
449477
450478 chunks . push ( "function(" ) ;
451- chunks . push ( ...this . joinChunks ( ", " , parameterChunks ) ) ;
479+ chunks . push ( ...this . printFunctionParameters ( expression ) ) ;
480+ chunks . push ( ")" ) ;
481+
482+ if ( tstl . isInlineFunctionExpression ( expression ) ) {
483+ const returnStatement = expression . body . statements [ 0 ] ;
484+ chunks . push ( " " ) ;
485+ const returnNode : SourceChunk [ ] = [
486+ "return " ,
487+ ...this . joinChunks ( ", " , returnStatement . expressions . map ( e => this . printExpression ( e ) ) ) ,
488+ ";" ,
489+ ] ;
490+ chunks . push ( this . createSourceNode ( returnStatement , returnNode ) ) ;
491+ chunks . push ( " end" ) ;
492+
493+ } else {
494+ chunks . push ( "\n" ) ;
495+ this . pushIndent ( ) ;
496+ chunks . push ( this . printBlock ( expression . body ) ) ;
497+ this . popIndent ( ) ;
498+ chunks . push ( this . indent ( "end" ) ) ;
499+ }
500+
501+ return this . createSourceNode ( expression , chunks ) ;
502+ }
503+
504+ private printFunctionDefinition ( statement : tstl . FunctionDefinition ) : SourceNode {
505+ const expression = statement . right [ 0 ] ;
506+ const chunks : SourceChunk [ ] = [ ] ;
507+
508+ chunks . push ( "function " ) ;
509+ chunks . push ( this . printExpression ( statement . left [ 0 ] ) ) ;
510+ chunks . push ( "(" ) ;
511+ chunks . push ( ...this . printFunctionParameters ( expression ) ) ;
452512 chunks . push ( ")\n" ) ;
453513
454514 this . pushIndent ( ) ;
@@ -482,14 +542,18 @@ export class LuaPrinter {
482542
483543 chunks . push ( "{" ) ;
484544
485- if ( expression . fields ) {
486- expression . fields . forEach ( ( f , i ) => {
487- if ( i < expression . fields . length - 1 ) {
488- chunks . push ( this . printTableFieldExpression ( f ) , ", " ) ;
489- } else {
490- chunks . push ( this . printTableFieldExpression ( f ) ) ;
491- }
492- } ) ;
545+ if ( expression . fields && expression . fields . length > 0 ) {
546+ if ( expression . fields . length === 1 ) {
547+ // Inline tables with only one entry
548+ chunks . push ( this . printTableFieldExpression ( expression . fields [ 0 ] ) ) ;
549+
550+ } else {
551+ chunks . push ( "\n" ) ;
552+ this . pushIndent ( ) ;
553+ expression . fields . forEach ( f => chunks . push ( this . indent ( ) , this . printTableFieldExpression ( f ) , ",\n" ) ) ;
554+ this . popIndent ( ) ;
555+ chunks . push ( this . indent ( ) ) ;
556+ }
493557 }
494558
495559 chunks . push ( "}" ) ;
@@ -501,41 +565,21 @@ export class LuaPrinter {
501565 const chunks : SourceChunk [ ] = [ ] ;
502566
503567 chunks . push ( this . printOperator ( expression . operator ) ) ;
504-
505- if ( this . needsParentheses ( expression . operand ) ) {
506- chunks . push ( "(" , this . printExpression ( expression . operand ) , ")" ) ;
507- } else {
508- chunks . push ( this . printExpression ( expression . operand ) ) ;
509- }
568+ chunks . push ( this . printExpression ( expression . operand ) ) ;
510569
511570 return this . createSourceNode ( expression , chunks ) ;
512571 }
513572
514573 private printBinaryExpression ( expression : tstl . BinaryExpression ) : SourceNode {
515574 const chunks : SourceChunk [ ] = [ ] ;
516575
517- if ( this . needsParentheses ( expression . left ) ) {
518- chunks . push ( "(" , this . printExpression ( expression . left ) , ")" ) ;
519- } else {
520- chunks . push ( this . printExpression ( expression . left ) ) ;
521- }
522-
576+ chunks . push ( this . printExpression ( expression . left ) ) ;
523577 chunks . push ( " " , this . printOperator ( expression . operator ) , " " ) ;
524-
525- if ( this . needsParentheses ( expression . right ) ) {
526- chunks . push ( "(" , this . printExpression ( expression . right ) , ")" ) ;
527- } else {
528- chunks . push ( this . printExpression ( expression . right ) ) ;
529- }
578+ chunks . push ( this . printExpression ( expression . right ) ) ;
530579
531580 return this . createSourceNode ( expression , chunks ) ;
532581 }
533582
534- private needsParentheses ( expression : tstl . Expression ) : boolean {
535- return tstl . isBinaryExpression ( expression ) || tstl . isUnaryExpression ( expression )
536- || tstl . isFunctionExpression ( expression ) ;
537- }
538-
539583 private printParenthesizedExpression ( expression : tstl . ParenthesizedExpression ) : SourceNode {
540584 return this . createSourceNode ( expression , [ "(" , this . printExpression ( expression . innerEpxression ) , ")" ] ) ;
541585 }
@@ -544,11 +588,7 @@ export class LuaPrinter {
544588 const chunks = [ ] ;
545589 const parameterChunks = this . joinChunks ( ", " , expression . params . map ( e => this . printExpression ( e ) ) ) ;
546590
547- if ( this . needsParentheses ( expression . expression ) ) {
548- chunks . push ( "(" , this . printExpression ( expression . expression ) , ")(" , ...parameterChunks , ")" ) ;
549- } else {
550- chunks . push ( this . printExpression ( expression . expression ) , "(" , ...parameterChunks , ")" ) ;
551- }
591+ chunks . push ( this . printExpression ( expression . expression ) , "(" , ...parameterChunks , ")" ) ;
552592
553593 return this . concatNodes ( ...chunks ) ;
554594 }
0 commit comments