@@ -2683,6 +2683,8 @@ export class LuaTransformer {
26832683 case ts . SyntaxKind . StringLiteral :
26842684 case ts . SyntaxKind . NoSubstitutionTemplateLiteral :
26852685 return this . transformStringLiteral ( expression as ts . StringLiteral ) ;
2686+ case ts . SyntaxKind . TaggedTemplateExpression :
2687+ return this . transformTaggedTemplateExpression ( expression as ts . TaggedTemplateExpression ) ;
26862688 case ts . SyntaxKind . TemplateExpression :
26872689 return this . transformTemplateExpression ( expression as ts . TemplateExpression ) ;
26882690 case ts . SyntaxKind . NumericLiteral :
@@ -3835,20 +3837,8 @@ export class LuaTransformer {
38353837 ! signatureDeclaration ||
38363838 tsHelper . getDeclarationContextType ( signatureDeclaration , this . checker ) !== tsHelper . ContextType . Void
38373839 ) {
3838- if (
3839- luaKeywords . has ( node . expression . name . text ) ||
3840- ! tsHelper . isValidLuaIdentifier ( node . expression . name . text )
3841- ) {
3842- return this . transformElementCall ( node ) ;
3843- } else {
3844- // table:name()
3845- return tstl . createMethodCallExpression (
3846- table ,
3847- this . transformIdentifier ( node . expression . name ) ,
3848- parameters ,
3849- node
3850- ) ;
3851- }
3840+ // table:name()
3841+ return this . transformContextualCallExpression ( node , parameters ) ;
38523842 } else {
38533843 // table.name()
38543844 const callPath = tstl . createTableIndexExpression (
@@ -3868,43 +3858,67 @@ export class LuaTransformer {
38683858 }
38693859
38703860 const signature = this . checker . getResolvedSignature ( node ) ;
3871- let parameters = this . transformArguments ( node . arguments , signature ) ;
3872-
38733861 const signatureDeclaration = signature && signature . getDeclaration ( ) ;
3862+ const parameters = this . transformArguments ( node . arguments , signature ) ;
38743863 if (
38753864 ! signatureDeclaration ||
38763865 tsHelper . getDeclarationContextType ( signatureDeclaration , this . checker ) !== tsHelper . ContextType . Void
38773866 ) {
3878- // Pass left-side as context
3867+ // A contextual parameter must be given to this call expression
3868+ return this . transformContextualCallExpression ( node , parameters ) ;
3869+ } else {
3870+ // No context
3871+ const expression = this . transformExpression ( node . expression ) ;
3872+ return tstl . createCallExpression ( expression , parameters ) ;
3873+ }
3874+ }
38793875
3880- const context = this . transformExpression ( node . expression . expression ) ;
3881- if ( tsHelper . isExpressionWithEvaluationEffect ( node . expression . expression ) ) {
3876+ public transformContextualCallExpression (
3877+ node : ts . CallExpression | ts . TaggedTemplateExpression ,
3878+ transformedArguments : tstl . Expression [ ]
3879+ ) : ExpressionVisitResult {
3880+ const left = ts . isCallExpression ( node ) ? node . expression : node . tag ;
3881+ const leftHandSideExpression = this . transformExpression ( left ) ;
3882+ if (
3883+ ts . isPropertyAccessExpression ( left ) &&
3884+ ! luaKeywords . has ( left . name . text ) &&
3885+ tsHelper . isValidLuaIdentifier ( left . name . text )
3886+ ) {
3887+ // table:name()
3888+ const table = this . transformExpression ( left . expression ) ;
3889+ return tstl . createMethodCallExpression (
3890+ table ,
3891+ this . transformIdentifier ( left . name ) ,
3892+ transformedArguments ,
3893+ node
3894+ ) ;
3895+ } else if ( ts . isElementAccessExpression ( left ) || ts . isPropertyAccessExpression ( left ) ) {
3896+ const context = this . transformExpression ( left . expression ) ;
3897+ if ( tsHelper . isExpressionWithEvaluationEffect ( left . expression ) ) {
38823898 // Inject context parameter
3883- if ( node . arguments . length > 0 ) {
3884- parameters . unshift ( tstl . createIdentifier ( "____TS_self" ) ) ;
3885- } else {
3886- parameters = [ tstl . createIdentifier ( "____TS_self" ) ] ;
3887- }
3899+ transformedArguments . unshift ( tstl . createIdentifier ( "____TS_self" ) ) ;
38883900
38893901 // Cache left-side if it has effects
38903902 //(function() local ____TS_self = context; return ____TS_self[argument](parameters); end)()
3891- const argumentExpression = ts . isElementAccessExpression ( node . expression )
3892- ? node . expression . argumentExpression
3893- : ts . createStringLiteral ( node . expression . name . text ) ;
3903+ const argumentExpression = ts . isElementAccessExpression ( left )
3904+ ? left . argumentExpression
3905+ : ts . createStringLiteral ( left . name . text ) ;
38943906 const argument = this . transformExpression ( argumentExpression ) ;
38953907 const selfIdentifier = tstl . createIdentifier ( "____TS_self" ) ;
38963908 const selfAssignment = tstl . createVariableDeclarationStatement ( selfIdentifier , context ) ;
38973909 const index = tstl . createTableIndexExpression ( selfIdentifier , argument ) ;
3898- const callExpression = tstl . createCallExpression ( index , parameters ) ;
3910+ const callExpression = tstl . createCallExpression ( index , transformedArguments ) ;
38993911 return this . createImmediatelyInvokedFunctionExpression ( [ selfAssignment ] , callExpression , node ) ;
39003912 } else {
3901- const expression = this . transformExpression ( node . expression ) ;
3902- return tstl . createCallExpression ( expression , [ context , ...parameters ] ) ;
3913+ const expression = this . transformExpression ( left ) ;
3914+ return tstl . createCallExpression ( expression , [ context , ...transformedArguments ] ) ;
39033915 }
3916+ } else if ( ts . isIdentifier ( left ) ) {
3917+ const context = this . isStrict ? tstl . createNilLiteral ( ) : tstl . createIdentifier ( "_G" ) ;
3918+ transformedArguments . unshift ( context ) ;
3919+ return tstl . createCallExpression ( leftHandSideExpression , transformedArguments , node ) ;
39043920 } else {
3905- // No context
3906- const expression = this . transformExpression ( node . expression ) ;
3907- return tstl . createCallExpression ( expression , parameters ) ;
3921+ throw TSTLErrors . UnsupportedKind ( "Left Hand Side Call Expression" , left . kind , left ) ;
39083922 }
39093923 }
39103924
@@ -4678,6 +4692,58 @@ export class LuaTransformer {
46784692 return this . createSelfIdentifier ( thisKeyword ) ;
46794693 }
46804694
4695+ public transformTaggedTemplateExpression ( expression : ts . TaggedTemplateExpression ) : ExpressionVisitResult {
4696+ const strings : string [ ] = [ ] ;
4697+ const rawStrings : string [ ] = [ ] ;
4698+ const expressions : ts . Expression [ ] = [ ] ;
4699+
4700+ if ( ts . isTemplateExpression ( expression . template ) ) {
4701+ // Expressions are in the string.
4702+ strings . push ( expression . template . head . text ) ;
4703+ rawStrings . push ( tsHelper . getRawLiteral ( expression . template . head ) ) ;
4704+ strings . push ( ...expression . template . templateSpans . map ( span => span . literal . text ) ) ;
4705+ rawStrings . push ( ...expression . template . templateSpans . map ( span => tsHelper . getRawLiteral ( span . literal ) ) ) ;
4706+ expressions . push ( ...expression . template . templateSpans . map ( span => span . expression ) ) ;
4707+ } else {
4708+ // No expressions are in the string.
4709+ strings . push ( expression . template . text ) ;
4710+ rawStrings . push ( tsHelper . getRawLiteral ( expression . template ) ) ;
4711+ }
4712+
4713+ // Construct table with strings and literal strings
4714+ const stringTableLiteral = tstl . createTableExpression (
4715+ strings . map ( partialString => tstl . createTableFieldExpression ( tstl . createStringLiteral ( partialString ) ) )
4716+ ) ;
4717+ if ( stringTableLiteral . fields ) {
4718+ const rawStringArray = tstl . createTableExpression (
4719+ rawStrings . map ( stringLiteral =>
4720+ tstl . createTableFieldExpression ( tstl . createStringLiteral ( stringLiteral ) )
4721+ )
4722+ ) ;
4723+ stringTableLiteral . fields . push (
4724+ tstl . createTableFieldExpression ( rawStringArray , tstl . createStringLiteral ( "raw" ) )
4725+ ) ;
4726+ }
4727+
4728+ // Evaluate if there is a self parameter to be used.
4729+ const signature = this . checker . getResolvedSignature ( expression ) ;
4730+ const signatureDeclaration = signature && signature . getDeclaration ( ) ;
4731+ const useSelfParameter =
4732+ signatureDeclaration &&
4733+ tsHelper . getDeclarationContextType ( signatureDeclaration , this . checker ) !== tsHelper . ContextType . Void ;
4734+
4735+ // Argument evaluation.
4736+ const callArguments = this . transformArguments ( expressions , signature ) ;
4737+ callArguments . unshift ( stringTableLiteral ) ;
4738+
4739+ if ( useSelfParameter ) {
4740+ return this . transformContextualCallExpression ( expression , callArguments ) ;
4741+ }
4742+
4743+ const leftHandSideExpression = this . transformExpression ( expression . tag ) ;
4744+ return tstl . createCallExpression ( leftHandSideExpression , callArguments ) ;
4745+ }
4746+
46814747 public transformTemplateExpression ( expression : ts . TemplateExpression ) : ExpressionVisitResult {
46824748 const parts : tstl . Expression [ ] = [ ] ;
46834749
0 commit comments