@@ -10,7 +10,6 @@ import {TSTLErrors} from "./TSTLErrors";
1010
1111export type StatementVisitResult = tstl . Statement | tstl . Statement [ ] | undefined ;
1212export type ExpressionVisitResult = tstl . Expression | undefined ;
13-
1413export enum ScopeType {
1514 File = 0x1 ,
1615 Function = 0x2 ,
@@ -1031,6 +1030,144 @@ export class LuaTransformer {
10311030 } ) ;
10321031 }
10331032
1033+ private transformGeneratorFunction (
1034+ parameters : ts . NodeArray < ts . ParameterDeclaration > ,
1035+ body : ts . Block ,
1036+ transformedParameters : tstl . Identifier [ ] ,
1037+ dotsLiteral : tstl . DotsLiteral ,
1038+ spreadIdentifier ?: tstl . Identifier
1039+ ) : [ tstl . Statement [ ] , Scope ]
1040+ {
1041+ this . importLuaLibFeature ( LuaLibFeature . Symbol ) ;
1042+ const [ functionBody , functionScope ] = this . transformFunctionBody (
1043+ parameters ,
1044+ body ,
1045+ spreadIdentifier
1046+ ) ;
1047+
1048+ const coroutineIdentifier = tstl . createIdentifier ( "____co" ) ;
1049+ const valueIdentifier = tstl . createIdentifier ( "____value" ) ;
1050+ const errIdentifier = tstl . createIdentifier ( "____err" ) ;
1051+ const itIdentifier = tstl . createIdentifier ( "____it" ) ;
1052+
1053+ //local ____co = coroutine.create(originalFunction)
1054+ const coroutine =
1055+ tstl . createVariableDeclarationStatement ( coroutineIdentifier ,
1056+ tstl . createCallExpression (
1057+ tstl . createTableIndexExpression ( tstl . createIdentifier ( "coroutine" ) ,
1058+ tstl . createStringLiteral ( "create" )
1059+ ) ,
1060+ [ tstl . createFunctionExpression (
1061+ tstl . createBlock ( functionBody ) ,
1062+ transformedParameters ,
1063+ dotsLiteral ,
1064+ spreadIdentifier ) ,
1065+ ]
1066+ )
1067+ ) ;
1068+
1069+ const nextBody = [ ] ;
1070+ // coroutine.resume(__co, ...)
1071+ const resumeCall = tstl . createCallExpression (
1072+ tstl . createTableIndexExpression (
1073+ tstl . createIdentifier ( "coroutine" ) ,
1074+ tstl . createStringLiteral ( "resume" )
1075+ ) ,
1076+ [ coroutineIdentifier , tstl . createDotsLiteral ( ) ]
1077+ ) ;
1078+
1079+ // ____err, ____value = coroutine.resume(____co, ...)
1080+ nextBody . push ( tstl . createVariableDeclarationStatement (
1081+ [ errIdentifier , valueIdentifier ] ,
1082+ resumeCall )
1083+ ) ;
1084+
1085+ //coroutine.status(____co) ~= "dead";
1086+ const coStatus = tstl . createCallExpression (
1087+ tstl . createTableIndexExpression (
1088+ tstl . createIdentifier ( "coroutine" ) ,
1089+ tstl . createStringLiteral ( "status" )
1090+ ) ,
1091+ [ coroutineIdentifier ]
1092+ ) ;
1093+ const status = tstl . createBinaryExpression (
1094+ coStatus ,
1095+ tstl . createStringLiteral ( "dead" ) ,
1096+ tstl . SyntaxKind . EqualityOperator
1097+ ) ;
1098+ nextBody . push ( status ) ;
1099+ //if(not ____err){error(____value)}
1100+ const errorCheck = tstl . createIfStatement (
1101+ tstl . createUnaryExpression (
1102+ errIdentifier ,
1103+ tstl . SyntaxKind . NotOperator
1104+ ) ,
1105+ tstl . createBlock ( [
1106+ tstl . createExpressionStatement (
1107+ tstl . createCallExpression (
1108+ tstl . createIdentifier ( "error" ) ,
1109+ [ valueIdentifier ]
1110+ )
1111+ ) ,
1112+ ] )
1113+ ) ;
1114+ nextBody . push ( errorCheck ) ;
1115+ //{done = coroutine.status(____co) ~= "dead"; value = ____value}
1116+ const iteratorResult = tstl . createTableExpression ( [
1117+ tstl . createTableFieldExpression (
1118+ status ,
1119+ tstl . createStringLiteral ( "done" )
1120+ ) ,
1121+ tstl . createTableFieldExpression (
1122+ valueIdentifier ,
1123+ tstl . createStringLiteral ( "value" )
1124+ ) ,
1125+ ] ) ;
1126+ nextBody . push ( tstl . createReturnStatement ( [ iteratorResult ] ) ) ;
1127+
1128+ //function(____, ...)
1129+ const nextFunctionDeclaration = tstl . createFunctionExpression (
1130+ tstl . createBlock ( nextBody ) ,
1131+ [ tstl . createAnnonymousIdentifier ( ) ] ,
1132+ tstl . createDotsLiteral ( ) ) ;
1133+
1134+ //____it = {next = function(____, ...)}
1135+ const iterator = tstl . createVariableDeclarationStatement (
1136+ itIdentifier ,
1137+ tstl . createTableExpression ( [
1138+ tstl . createTableFieldExpression (
1139+ nextFunctionDeclaration ,
1140+ tstl . createStringLiteral ( "next" )
1141+ ) ,
1142+ ] )
1143+ ) ;
1144+
1145+ const symbolIterator = tstl . createTableIndexExpression (
1146+ tstl . createIdentifier ( "Symbol" ) ,
1147+ tstl . createStringLiteral ( "iterator" )
1148+ ) ;
1149+
1150+ const block = [
1151+ coroutine ,
1152+ iterator ,
1153+ //____it[Symbol.iterator] = {return ____it}
1154+ tstl . createAssignmentStatement (
1155+ tstl . createTableIndexExpression (
1156+ itIdentifier ,
1157+ symbolIterator
1158+ ) ,
1159+ tstl . createFunctionExpression (
1160+ tstl . createBlock (
1161+ [ tstl . createReturnStatement ( [ itIdentifier ] ) ]
1162+ )
1163+ )
1164+ ) ,
1165+ //return ____it
1166+ tstl . createReturnStatement ( [ itIdentifier ] ) ,
1167+ ] ;
1168+ return [ block , functionScope ] ;
1169+ }
1170+
10341171 public transformFunctionDeclaration ( functionDeclaration : ts . FunctionDeclaration ) : StatementVisitResult {
10351172 // Don't transform functions without body (overload declarations)
10361173 if ( ! functionDeclaration . body ) {
@@ -1044,22 +1181,28 @@ export class LuaTransformer {
10441181 const [ params , dotsLiteral , restParamName ] = this . transformParameters ( functionDeclaration . parameters , context ) ;
10451182
10461183 const name = this . transformIdentifier ( functionDeclaration . name ) ;
1047- const [ body , functionScope ] = this . transformFunctionBody (
1048- functionDeclaration . parameters ,
1049- functionDeclaration . body ,
1050- restParamName
1051- ) ;
1184+ const [ body , functionScope ] = functionDeclaration . asteriskToken
1185+ ? this . transformGeneratorFunction (
1186+ functionDeclaration . parameters ,
1187+ functionDeclaration . body ,
1188+ params ,
1189+ dotsLiteral ,
1190+ restParamName
1191+ )
1192+ : this . transformFunctionBody (
1193+ functionDeclaration . parameters ,
1194+ functionDeclaration . body ,
1195+ restParamName
1196+ ) ;
10521197 const block = tstl . createBlock ( body ) ;
10531198 const functionExpression = tstl . createFunctionExpression ( block , params , dotsLiteral , restParamName ) ;
1054-
10551199 // Remember symbols referenced in this function for hoisting later
10561200 if ( ! this . options . noHoisting && name . symbolId !== undefined ) {
10571201 const scope = this . peekScope ( ) ;
10581202 if ( ! scope . functionDefinitions ) { scope . functionDefinitions = new Map ( ) ; }
10591203 const functionInfo = { referencedSymbols : functionScope . referencedSymbols || new Set ( ) } ;
10601204 scope . functionDefinitions . set ( name . symbolId , functionInfo ) ;
10611205 }
1062-
10631206 return this . createLocalOrExportedOrGlobalDeclaration ( name , functionExpression , functionDeclaration ) ;
10641207 }
10651208
@@ -1219,6 +1362,12 @@ export class LuaTransformer {
12191362 return tstl . createExpressionStatement ( this . transformExpression ( expression ) ) ;
12201363 }
12211364
1365+ public transformYield ( expression : ts . YieldExpression ) : tstl . Expression {
1366+ return tstl . createCallExpression (
1367+ tstl . createTableIndexExpression ( tstl . createIdentifier ( "coroutine" ) , tstl . createStringLiteral ( "yield" ) ) ,
1368+ expression . expression ?[ this . transformExpression ( expression . expression ) ] :[ ] , expression ) ;
1369+ }
1370+
12221371 public transformReturn ( statement : ts . ReturnStatement ) : tstl . Statement {
12231372 if ( statement . expression ) {
12241373 const returnType = tsHelper . getContainingFunctionReturnType ( statement , this . checker ) ;
@@ -1731,6 +1880,8 @@ export class LuaTransformer {
17311880 return this . transformSpreadElement ( expression as ts . SpreadElement ) ;
17321881 case ts . SyntaxKind . NonNullExpression :
17331882 return this . transformExpression ( ( expression as ts . NonNullExpression ) . expression ) ;
1883+ case ts . SyntaxKind . YieldExpression :
1884+ return this . transformYield ( expression as ts . YieldExpression ) ;
17341885 case ts . SyntaxKind . EmptyStatement :
17351886 return undefined ;
17361887 case ts . SyntaxKind . NotEmittedStatement :
@@ -1871,7 +2022,6 @@ export class LuaTransformer {
18712022 throw TSTLErrors . UnsupportedUnionAccessor ( lhs ) ;
18722023 }
18732024 }
1874-
18752025 return tstl . createAssignmentStatement (
18762026 this . transformExpression ( lhs ) as tstl . IdentifierOrTableIndexExpression ,
18772027 right ,
0 commit comments