@@ -4,7 +4,7 @@ import { transformBuiltinPropertyAccessExpression } from "../builtins";
44import { FunctionVisitor , TransformationContext } from "../context" ;
55import { AnnotationKind , getTypeAnnotations } from "../utils/annotations" ;
66import { createExpressionPlusOne } from "../utils/lua-ast" ;
7- import { isArrayType , isNumberType , isStringType } from "../utils/typescript" ;
7+ import { isArrayType , isNumberType , isStringType , isExpressionWithEvaluationEffect } from "../utils/typescript" ;
88import { tryGetConstEnumValue } from "./enum" ;
99import { transformLuaTablePropertyAccessExpression , validateLuaTableElementAccessExpression } from "./lua-table" ;
1010
@@ -31,20 +31,17 @@ export const transformElementAccessExpression: FunctionVisitor<ts.ElementAccessE
3131 return constEnumValue ;
3232 }
3333
34- const table = context . transformExpression ( expression . expression ) ;
35-
3634 const argumentType = context . checker . getTypeAtLocation ( expression . argumentExpression ) ;
3735 const type = context . checker . getTypeAtLocation ( expression . expression ) ;
3836 if ( isNumberType ( context , argumentType ) && isStringType ( context , type ) ) {
39- const index = context . transformExpression ( expression . argumentExpression ) ;
40- return lua . createCallExpression (
41- lua . createTableIndexExpression ( lua . createIdentifier ( "string" ) , lua . createStringLiteral ( "sub" ) ) ,
42- [ table , createExpressionPlusOne ( index ) , createExpressionPlusOne ( index ) ] ,
43- expression
44- ) ;
37+ return transformStringIndex ( context , expression ) ;
4538 }
4639
47- return lua . createTableIndexExpression ( table , transformElementAccessArgument ( context , expression ) , expression ) ;
40+ return lua . createTableIndexExpression (
41+ context . transformExpression ( expression . expression ) ,
42+ transformElementAccessArgument ( context , expression ) ,
43+ expression
44+ ) ;
4845} ;
4946
5047export const transformPropertyAccessExpression : FunctionVisitor < ts . PropertyAccessExpression > = (
@@ -94,3 +91,32 @@ export const transformQualifiedName: FunctionVisitor<ts.QualifiedName> = (node,
9491
9592 return lua . createTableIndexExpression ( left , right , node ) ;
9693} ;
94+
95+ function transformStringIndex ( context : TransformationContext , expression : ts . ElementAccessExpression ) : lua . Expression {
96+ const string = context . transformExpression ( expression . expression ) ;
97+ // Translate to string.sub(str, index, index), cache index in case it has side effects.
98+ if ( isExpressionWithEvaluationEffect ( expression . argumentExpression ) ) {
99+ const indexIdentifier = lua . createIdentifier ( "____index" ) ;
100+ // string.sub(stringExpression, ____index, ____index)
101+ const subCall = lua . createCallExpression (
102+ lua . createTableIndexExpression ( lua . createIdentifier ( "string" ) , lua . createStringLiteral ( "sub" ) ) ,
103+ [ string , lua . cloneIdentifier ( indexIdentifier ) , lua . cloneIdentifier ( indexIdentifier ) ] ,
104+ expression
105+ ) ;
106+ // function(____index) string.sub(stringExpression, ____index, ____index)
107+ const functionExpression = lua . createFunctionExpression (
108+ lua . createBlock ( [ lua . createReturnStatement ( [ subCall ] ) ] ) ,
109+ [ lua . cloneIdentifier ( indexIdentifier ) ]
110+ ) ;
111+ // (function(____index) string.sub(stringExpression, ____index, ____index) end)(index + 1)
112+ const indexPlusOne = createExpressionPlusOne ( context . transformExpression ( expression . argumentExpression ) ) ;
113+ return lua . createCallExpression ( functionExpression , [ indexPlusOne ] ) ;
114+ } else {
115+ const index = context . transformExpression ( expression . argumentExpression ) ;
116+ return lua . createCallExpression (
117+ lua . createTableIndexExpression ( lua . createIdentifier ( "string" ) , lua . createStringLiteral ( "sub" ) ) ,
118+ [ string , createExpressionPlusOne ( index ) , createExpressionPlusOne ( index ) ] ,
119+ expression
120+ ) ;
121+ }
122+ }
0 commit comments