/* Ċ Ġ* ĠCopyright Ġ 2 0 1 0 - 2 0 1 9 ĠJetBrains Ġs . r . o . Ġand ĠKotlin ĠProgramming ĠLanguage Ġcontributors . Ċ Ġ* ĠUse Ġof Ġthis Ġsource Ġcode Ġis Ġgoverned Ġby Ġthe ĠApache Ġ 2 . 0 Ġlicense Ġthat Ġcan Ġbe Ġfound Ġin Ġthe Ġlicense / LICENSE . txt Ġfile . Ċ Ġ*/ Ċ Ċ package Ġorg . jetbrains . kotlin . backend . jvm . lower Ċ Ċ import Ġorg . jetbrains . kotlin . backend . common . File Lower ing Pass Ċ import Ġorg . jetbrains . kotlin . backend . common . Ir Element Transformer Void WithContext Ċ import Ġorg . jetbrains . kotlin . backend . common . ir . all Parameters Ċ import Ġorg . jetbrains . kotlin . backend . common . lower . create Ir Builder Ċ import Ġorg . jetbrains . kotlin . backend . common . lower . ir Block Ċ import Ġorg . jetbrains . kotlin . backend . common . ph aser . make Ir File Phase Ċ import Ġorg . jetbrains . kotlin . backend . jvm . Jvm Backend Context Ċ import Ġorg . jetbrains . kotlin . backend . jvm . ir . Ir Inline Reference Locator Ċ import Ġorg . jetbrains . kotlin . backend . jvm . ir . create Jvm Ir Builder Ċ import Ġorg . jetbrains . kotlin . backend . jvm . ir . ir Array Ċ import Ġorg . jetbrains . kotlin . backend . jvm . ir . is Lambda Ċ import Ġorg . jetbrains . kotlin . codegen . Asm Util . BOUND _ REFERENCE _ RECE IVER Ċ import Ġorg . jetbrains . kotlin . descriptors . Vis ibilities Ċ import Ġorg . jetbrains . kotlin . ir . builders .* Ċ import Ġorg . jetbrains . kotlin . ir . builders . declarations . add Value Parameter Ċ import Ġorg . jetbrains . kotlin . ir . builders . declarations . build Fun Ċ import Ġorg . jetbrains . kotlin . ir . declarations .* Ċ import Ġorg . jetbrains . kotlin . ir . expressions .* Ċ import Ġorg . jetbrains . kotlin . ir . expressions . impl . Ir Function Reference Impl Ċ import Ġorg . jetbrains . kotlin . ir . types . Ir Simple Type Ċ import Ġorg . jetbrains . kotlin . ir . util .* Ċ import Ġorg . jetbrains . kotlin . ir . visitor s . transform Children Void Ċ import Ġorg . jetbrains . kotlin . name . Name Ċ Ċ internal Ġval Ġinline Callable Reference To Lambda Phase Ġ= Ġmake Ir File Phase ( ĊĠĠĠ Ġ:: Inline Callable Reference To Lambda Phase , ĊĠĠĠ Ġname Ġ= Ġ" Inline Callable Reference To Lambda Phase ", ĊĠĠĠ Ġdescription Ġ= Ġ" Transform Ġcallable Ġreference Ġto Ġinline Ġlambda " Ċ ) Ċ Ċ // ĠThis Ġlower ing Ġtransforms ĠCR Ġpassed Ġto Ġinline Ġfunction Ġto Ġlambda Ġwhich Ġwould Ġbe Ġin lined Ċ // Ċ // ĠĠĠĠĠ Ġinline Ġfun Ġfoo ( inline Parameter : Ġ( A ) Ġ-> ĠB ): ĠB Ġ{ Ċ // ĠĠĠĠĠĠĠĠĠ Ġreturn Ġinline Parameter () Ċ // ĠĠĠĠĠ Ġ} Ċ // Ċ // ĠĠĠĠĠ Ġfoo (:: sm th ) Ġ-> Ġfoo Ġ{ Ġa Ġ-> Ġsm th ( a ) Ġ} Ċ // Ċ internal Ġclass ĠInline Callable Reference To Lambda Phase ( val Ġcontext : ĠJ vm Backend Context ) Ġ: ĠFile Lower ing Pass , ĊĠĠĠ ĠIr Element Transformer Void WithContext () Ġ{ ĊĊĠĠĠ Ġprivate Ġvar Ġin lin able References Ġ= Ġmutable Set Of < Ir Callable Reference >() ĊĊĠĠĠ Ġoverride Ġfun Ġlower ( ir File : ĠIr File ) Ġ{ ĊĠĠĠĠĠĠĠ Ġin lin able References . addAll ( Ir Inline Reference Locator . scan ( context , Ġir File )) ĊĠĠĠĠĠĠĠ Ġir File . transform Children Void ( this ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġfun Ġvisit Function Reference ( expression : ĠIr Function Reference ): ĠIr Expression Ġ{ ĊĠĠĠĠĠĠĠ Ġexpression . transform Children Void ( this ) ĊĠĠĠĠĠĠĠ Ġif Ġ( expression Ġ! in Ġin lin able References Ġ|| Ġexpression . origin . is Lambda ) Ġreturn Ġexpression ĊĠĠĠĠĠĠĠ Ġreturn Ġexpand Inline Function Reference To Lambda ( expression , Ġexpression . symbol . owner ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġfun Ġvisit Property Reference ( expression : ĠIr Property Reference ): ĠIr Expression Ġ{ ĊĠĠĠĠĠĠĠ Ġexpression . transform Children Void ( this ) ĊĠĠĠĠĠĠĠ Ġif Ġ( expression Ġ! in Ġin lin able References ) Ġreturn Ġexpression ĊĊĠĠĠĠĠĠĠ Ġreturn Ġif Ġ( expression . field ?. owner Ġ== Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠUse Ġgetter Ġif Ġfield Ġis Ġabsent Ġ... ĊĠĠĠĠĠĠĠĠĠĠĠ Ġexpand Inline Function Reference To Lambda ( expression , Ġexpression . getter !!. owner ) ĊĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġ... Ġelse Ġuse Ġfield Ġitself ĊĠĠĠĠĠĠĠĠĠĠĠ Ġexpand Inline Field Reference To Lambda ( expression , Ġexpression . field !!. owner ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġexpand Inline Field Reference To Lambda ( expression : ĠIr Property Reference , Ġfield : ĠIr Field ): ĠIr Expression Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġir Builder Ġ= Ġcontext . create Jvm Ir Builder ( current Scope !!. scope . scope Owner Symbol , Ġexpression . start Offset , Ġexpression . end Offset ) ĊĠĠĠĠĠĠĠ Ġreturn Ġir Builder . ir Block ( expression , ĠIr Statement Origin . L AMBDA ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġfunction Ġ= Ġbuild Fun Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġset Source Range ( expression ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġorigin Ġ= ĠIr Declaration Origin . LOCAL _ FUNCTION _ FOR _ L AMBDA ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġname Ġ= ĠName . identifier (" stub _ for _ inline ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġvisibility Ġ= ĠVis ibilities . LOCAL ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠreturnType Ġ= Ġfield . type ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġis Suspend Ġ= Ġfalse ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ}. apply Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġparent Ġ= Ġcurrent Declaration Parent ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġbound Receiver Ġ= Ġexpression . dispatch Receiver Ġ?: Ġexpression . extension Receiver ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġreceiver Ġ= ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġwhen Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġfield . is Static Ġ-> Ġnull ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġbound Receiver Ġ!= Ġnull Ġ-> Ġir Get ( ir Temporary ( bound Receiver , ĠBO UND _ REFERENCE _ RECE IVER )) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġ-> Ġir Get ( add Value Parameter (" receiver ", Ġfield . parent As Class . default Type )) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġbody Ġ= Ġthis @ Inline Callable Reference To Lambda Phase . context . create Ir Builder ( symbol ). run Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġir Expr Body ( ir GetField ( receiver , Ġfield )) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġ+ function ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ+ Ir Function Reference Impl ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġexpression . start Offset , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġexpression . end Offset , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġfield . type , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġfunction . symbol , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtype Arguments Count Ġ= Ġ 0 , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreflection Target Ġ= Ġnull , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġorigin Ġ= ĠIr Statement Origin . L AMBDA ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ). apply Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcopy Attributes ( expression ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġexpand Inline Function Reference To Lambda ( expression : ĠIr Callable Reference , Ġreferenced Function : ĠIr Function ): ĠIr Expression Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġir Builder Ġ= Ġcontext . create Jvm Ir Builder ( current Scope !!. scope . scope Owner Symbol , Ġexpression . start Offset , Ġexpression . end Offset ) ĊĠĠĠĠĠĠĠ Ġreturn Ġir Builder . ir Block ( expression , ĠIr Statement Origin . L AMBDA ) Ġ{ ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// ĠWe Ġfind Ġthe Ġnumber Ġof Ġparameters Ġfor Ġconstructed Ġlambda Ġfrom Ġthe Ġtype Ġof Ġthe Ġfunction Ġreference , ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġbut Ġthe Ġactual Ġtypes Ġhave Ġto Ġbe Ġcopied Ġfrom Ġreferenced Function ; Ġfunction Ġreference Ġargument Ġtype Ġmay Ġbe Ġtoo ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ// Ġspecific Ġbecause Ġof Ġapproximation . ĠSee Ġcompiler / testData / codegen / box / callable Reference / function / argument Types . kt ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġbound Receiver : ĠPair < Ir Value Parameter , ĠIr Expression >? Ġ= Ġexpression . get Arguments With Ir (). single OrNull () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġn Params Ġ= Ġ( expression . type Ġas ĠIr Simple Type ). arguments . size Ġ- Ġ 1 ĊĠĠĠĠĠĠĠĠĠĠĠ Ġvar Ġto Drop At Start Ġ= Ġ 0 ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( bound Receiver Ġ!= Ġnull ) Ġto Drop At Start ++ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( referenced Function Ġis ĠIr Constructor ) Ġto Drop At Start ++ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġargument Types Ġ= Ġreferenced Function . all Parameters . drop ( to Drop At Start ). take ( n Params ). map Ġ{ Ġparameter Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġparameter . type . substitute ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreferenced Function . type Parameters , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreferenced Function . type Parameters . indices . map Ġ{ Ġexpression . getType Argument ( it ) !! Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġfunction Ġ= Ġbuild Fun Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġset Source Range ( expression ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġorigin Ġ= ĠIr Declaration Origin . LOCAL _ FUNCTION _ FOR _ L AMBDA ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġname Ġ= ĠName . identifier (" stub _ for _ in lining ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġvisibility Ġ= ĠVis ibilities . LOCAL ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ ĠreturnType Ġ= Ġreferenced Function . returnType ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġis Suspend Ġ= Ġreferenced Function . is Suspend ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ}. apply Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġparent Ġ= Ġcurrent Declaration Parent ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġfor Ġ(( index , Ġargument Type ) Ġin Ġargument Types . with Index ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġadd Value Parameter Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġname Ġ= ĠName . identifier (" p $ index ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtype Ġ= Ġargument Type ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġbody Ġ= Ġthis @ Inline Callable Reference To Lambda Phase . context . create Jvm Ir Builder ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġsymbol , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġexpression . start Offset , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġexpression . end Offset ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ). run Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġir Expr Body ( ir Call ( referenced Function ). apply Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġsymbol . owner . all Type Parameters . forEach Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġput Type Argument ( it . index , Ġexpression . getType Argument ( it . index )) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġvar Ġun bound Index Ġ= Ġ 0 ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġfor Ġ( parameter Ġin Ġreferenced Function . explicit Parameters ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġwhen Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġbound Receiver ?. first Ġ== Ġparameter Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġir Get ( ir Temporary ( bound Receiver . second )) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġparameter . is Var arg Ġ&& Ġun bound Index Ġ< Ġargument Types . size Ġ&& Ġparameter . type Ġ== Ġvalue Parameters [ un bound Index ]. type Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġir Get ( value Parameters [ un bound Index ++ ]) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġparameter . is Var arg Ġ&& Ġ( un bound Index Ġ< Ġargument Types . size Ġ|| Ġ! parameter . has DefaultValue ()) Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġir Array ( parameter . type ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ( un bound Index Ġuntil Ġargument Types . size ). forEach Ġ{ Ġ+ ir Get ( value Parameters [ un bound Index ++ ]) Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġun bound Index Ġ>= Ġargument Types . size Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġnull ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġir Get ( value Parameters [ un bound Index ++ ]) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ?. let Ġ{ Ġput Argument ( referenced Function , Ġparameter , Ġit ) Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ}) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġ+ function ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ+ Ir Function Reference Impl ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġexpression . start Offset , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġexpression . end Offset , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġfunction . returnType , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġfunction . symbol , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġtype Arguments Count Ġ= Ġfunction . type Parameters . size , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreflection Target Ġ= Ġnull , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġorigin Ġ= ĠIr Statement Origin . L AMBDA ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ). apply Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcopy Attributes ( expression ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} Ċ }