11import * as ts from "typescript" ;
22import * as lua from "../../LuaAST" ;
3+ import { assert } from "../../utils" ;
34import { FunctionVisitor , TransformationContext } from "../context" ;
45import { isVarargType } from "../utils/annotations" ;
56import { createDefaultExportStringLiteral , hasDefaultExportModifier } from "../utils/export" ;
@@ -11,8 +12,8 @@ import {
1112 createSelfIdentifier ,
1213 wrapInTable ,
1314} from "../utils/lua-ast" ;
15+ import { LuaLibFeature , transformLuaLibFunction } from "../utils/lualib" ;
1416import { peekScope , performHoisting , popScope , pushScope , Scope , ScopeType } from "../utils/scope" ;
15- import { transformGeneratorFunctionBody } from "./generator" ;
1617import { transformIdentifier } from "./identifier" ;
1718import { transformBindingPattern } from "./variable-declaration" ;
1819
@@ -157,12 +158,13 @@ export function transformParameters(
157158 return [ paramNames , dotsLiteral , restParamName ] ;
158159}
159160
160- export function transformFunctionLikeDeclaration (
161- node : ts . FunctionLikeDeclaration ,
162- context : TransformationContext
163- ) : lua . Expression {
164- const type = context . checker . getTypeAtLocation ( node ) ;
161+ export function transformFunctionToExpression (
162+ context : TransformationContext ,
163+ node : ts . FunctionLikeDeclaration
164+ ) : [ lua . Expression , Scope ] {
165+ assert ( node . body ) ;
165166
167+ const type = context . checker . getTypeAtLocation ( node ) ;
166168 let functionContext : lua . Identifier | undefined ;
167169 if ( getFunctionContextType ( context , type ) !== ContextType . Void ) {
168170 if ( ts . isArrowFunction ( node ) ) {
@@ -176,14 +178,10 @@ export function transformFunctionLikeDeclaration(
176178 }
177179 }
178180
179- // Build parameter string
180- const [ paramNames , dotsLiteral , spreadIdentifier ] = transformParameters ( context , node . parameters , functionContext ) ;
181-
182181 let flags = lua . FunctionExpressionFlags . None ;
183-
184- if ( node . body === undefined ) {
185- // This code can be reached only from object methods, which is TypeScript error
186- return lua . createNilLiteral ( ) ;
182+ if ( ! ts . isBlock ( node . body ) ) flags |= lua . FunctionExpressionFlags . Inline ;
183+ if ( ts . isFunctionDeclaration ( node ) || ts . isMethodDeclaration ( node ) ) {
184+ flags |= lua . FunctionExpressionFlags . Declaration ;
187185 }
188186
189187 let body : ts . Block ;
@@ -193,14 +191,11 @@ export function transformFunctionLikeDeclaration(
193191 const returnExpression = ts . createReturn ( node . body ) ;
194192 body = ts . createBlock ( [ returnExpression ] ) ;
195193 returnExpression . parent = body ;
196- if ( node . body ) {
197- body . parent = node . body . parent ;
198- }
199- flags |= lua . FunctionExpressionFlags . Inline ;
194+ if ( node . body ) body . parent = node . body . parent ;
200195 }
201196
202- const [ transformedBody , scope ] = transformFunctionBody ( context , node . parameters , body , spreadIdentifier ) ;
203-
197+ const [ paramNames , dotsLiteral , spreadIdentifier ] = transformParameters ( context , node . parameters , functionContext ) ;
198+ const [ transformedBody , functionScope ] = transformFunctionBody ( context , node . parameters , body , spreadIdentifier ) ;
204199 const functionExpression = lua . createFunctionExpression (
205200 lua . createBlock ( transformedBody ) ,
206201 paramNames ,
@@ -209,12 +204,31 @@ export function transformFunctionLikeDeclaration(
209204 node
210205 ) ;
211206
207+ return [
208+ node . asteriskToken
209+ ? transformLuaLibFunction ( context , LuaLibFeature . Generator , undefined , functionExpression )
210+ : functionExpression ,
211+ functionScope ,
212+ ] ;
213+ }
214+
215+ export function transformFunctionLikeDeclaration (
216+ node : ts . FunctionLikeDeclaration ,
217+ context : TransformationContext
218+ ) : lua . Expression {
219+ if ( node . body === undefined ) {
220+ // This code can be reached only from object methods, which is TypeScript error
221+ return lua . createNilLiteral ( ) ;
222+ }
223+
224+ const [ functionExpression , functionScope ] = transformFunctionToExpression ( context , node ) ;
225+
212226 // Handle named function expressions which reference themselves
213- if ( ts . isFunctionExpression ( node ) && node . name && scope . referencedSymbols ) {
227+ if ( ts . isFunctionExpression ( node ) && node . name && functionScope . referencedSymbols ) {
214228 const symbol = context . checker . getSymbolAtLocation ( node . name ) ;
215229 if ( symbol ) {
216230 // TODO: Not using symbol ids because of https://github.com/microsoft/TypeScript/issues/37131
217- const isReferenced = [ ...scope . referencedSymbols ] . some ( ( [ , nodes ] ) =>
231+ const isReferenced = [ ...functionScope . referencedSymbols ] . some ( ( [ , nodes ] ) =>
218232 nodes . some ( n => context . checker . getSymbolAtLocation ( n ) ?. valueDeclaration === symbol . valueDeclaration )
219233 ) ;
220234
@@ -234,34 +248,19 @@ export function transformFunctionLikeDeclaration(
234248
235249export const transformFunctionDeclaration : FunctionVisitor < ts . FunctionDeclaration > = ( node , context ) => {
236250 // Don't transform functions without body (overload declarations)
237- if ( ! node . body ) {
251+ if ( node . body === undefined ) {
238252 return undefined ;
239253 }
240254
241- const type = context . checker . getTypeAtLocation ( node ) ;
242- const functionContext =
243- getFunctionContextType ( context , type ) !== ContextType . Void ? createSelfIdentifier ( ) : undefined ;
244- const [ params , dotsLiteral , restParamName ] = transformParameters ( context , node . parameters , functionContext ) ;
245-
246- const [ body , functionScope ] = node . asteriskToken
247- ? transformGeneratorFunctionBody ( context , node . parameters , node . body , restParamName )
248- : transformFunctionBody ( context , node . parameters , node . body , restParamName ) ;
249-
250- const block = lua . createBlock ( body ) ;
251- const functionExpression = lua . createFunctionExpression (
252- block ,
253- params ,
254- dotsLiteral ,
255- lua . FunctionExpressionFlags . Declaration
256- ) ;
257-
258255 if ( hasDefaultExportModifier ( node ) ) {
259256 return lua . createAssignmentStatement (
260257 lua . createTableIndexExpression ( createExportsIdentifier ( ) , createDefaultExportStringLiteral ( node ) ) ,
261258 transformFunctionLikeDeclaration ( node , context )
262259 ) ;
263260 }
264261
262+ const [ functionExpression , functionScope ] = transformFunctionToExpression ( context , node ) ;
263+
265264 // Name being undefined without default export is a TypeScript error
266265 const name = node . name ? transformIdentifier ( context , node . name ) : lua . createAnonymousIdentifier ( ) ;
267266
@@ -278,3 +277,10 @@ export const transformFunctionDeclaration: FunctionVisitor<ts.FunctionDeclaratio
278277
279278 return createLocalOrExportedOrGlobalDeclaration ( context , name , functionExpression , node ) ;
280279} ;
280+
281+ export const transformYieldExpression : FunctionVisitor < ts . YieldExpression > = ( expression , context ) =>
282+ lua . createCallExpression (
283+ lua . createTableIndexExpression ( lua . createIdentifier ( "coroutine" ) , lua . createStringLiteral ( "yield" ) ) ,
284+ expression . expression ? [ context . transformExpression ( expression . expression ) ] : [ ] ,
285+ expression
286+ ) ;
0 commit comments