package Ġl is py Ċ Ċ import Ġjavax . naming . Invalid Name Exception Ċ import Ġkotlin . reflect . K Callable Ċ Ċ // ĠPlay ing Ġfast Ġand Ġloose Ġhere Ġ-- ĠMutable Map Ġis Ġhow Ġthings Ġget Ġ" used Ġin Ġpractice ", Ġe . g ., Ġwith Ġset ! Ġand Ġdefine Ċ // Ġoperations , Ġbut Ġfor Ġtesting Ġand Ġother Ġcontexts Ġimmutable Ġmaps Ġmay Ġbe Ġuseful . Ċ // ĠAs Ġsuch , Ġ` update ` Ġdoes Ġ_ not _ Ġreturn Ġa Ġnew Ġenv Ġbut Ġinstead Ġprovides Ġa Ġmutable - like ĠAPI , Ġeven Ġwhen Ġin e leg ant . Ċ // ĠCall ers Ġcan Ġmake Ġeleg ant Ġin Ġother Ġways , Ġso Ġthat Ġthe Ġmutable Ġreality Ġis Ġnot Ġforgot ten . Ċ data Ġclass ĠEnv ( val Ġouter : ĠEnv ?, Ġval Ġmap : ĠMutable Map < String , ĠExpr >) Ġ{ ĊĠĠĠ Ġfun Ġfind ( K : ĠString ): ĠExpr ? Ġ= Ġmap . get ( K ) Ġ?: Ġouter ?. find ( K ) ĊĠĠĠ Ġfun Ġfind Env ( K : ĠString ): ĠEnv ? Ġ= Ġif Ġ( map . contains ( K )) Ġthis Ġelse Ġouter ?. find Env ( K ) ĊĠĠĠ Ġfun Ġupdate ( K : ĠString , ĠV : ĠExpr ) Ġ= Ġmap . put ( K , ĠV ) ĊĠĠĠ Ġ// Ġfun Ġpush () Ġ= ĠEnv ( this , Ġmutable Map Of ()) ĊĠĠĠ Ġ// Ġfun Ġpop () Ġ= Ġouter Ċ } Ċ Ċ // ĠDeb ating Ġwhether Ġto Ġmake Ġall ĠExpr s Ġbind Ġto Ġan ĠEnv Ġ-- ĠI Ġdon 't Ġimagine Ġre - using Ġan Ġexpr Ġin Ġa Ġnew Ġenv , Ġso Ġit Ġsimpl ifies Ċ // Ġeval Ġconsider ably Ġto Ġbind Ġat Ġcreate Ġtime . Ċ sealed Ġclass ĠExpr Ġ{ ĊĠĠĠ Ġ// Ġevaluate ĠAST Ġwithin Ġgiven ĠEnvironment , Ġreturns Ġresult ĠExpr ĊĠĠĠ Ġabstract Ġfun Ġeval ( env : ĠEnv ): ĠExpr ĊĠĠĠ Ġ// Ġconvert ĠAST ĠExpr Ġto Ġcode ĊĠĠĠ Ġabstract Ġfun Ġto Code (): ĠString ĊĊĠĠĠ Ġ// ĠAtom s ĊĠĠĠ Ġobject ĠNil Ġ: ĠExpr () Ġ{ ĊĠĠĠĠĠĠĠ Ġoverride Ġfun Ġeval ( env : ĠEnv ) Ġ= Ġthis ĊĠĠĠĠĠĠĠ Ġoverride Ġfun Ġto Code (): ĠString Ġ= Ġ" nil " ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġsealed Ġclass ĠBoolean ( val Ġbool : Ġkotlin . Boolean ) Ġ: ĠExpr () Ġ{ ĊĠĠĠĠĠĠĠ Ġobject ĠTrue Ġ: ĠExpr . Boolean ( true ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġoverride Ġfun Ġeval ( env : ĠEnv ) Ġ= Ġthis ĊĠĠĠĠĠĠĠĠĠĠĠ Ġoverride Ġfun Ġto Code (): ĠString Ġ= Ġ"# t " ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġobject ĠFalse Ġ: ĠExpr . Boolean ( false ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġoverride Ġfun Ġeval ( env : ĠEnv ) Ġ= Ġthis ĊĠĠĠĠĠĠĠĠĠĠĠ Ġoverride Ġfun Ġto Code (): ĠString Ġ= Ġ"# f " ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġdata Ġclass ĠLong Numeric ( val Ġlong : ĠLong ) Ġ: ĠExpr () Ġ{ ĊĠĠĠĠĠĠĠ Ġoverride Ġfun Ġeval ( env : ĠEnv ) Ġ= Ġthis ĊĠĠĠĠĠĠĠ Ġoverride Ġfun Ġto Code (): ĠString Ġ= Ġ"$ long " ĊĠĠĠ Ġ} ĊĠĠĠ Ġdata Ġclass ĠDouble Numeric ( val Ġdouble : ĠDouble ) Ġ: ĠExpr () Ġ{ ĊĠĠĠĠĠĠĠ Ġoverride Ġfun Ġeval ( env : ĠEnv ) Ġ= Ġthis ĊĠĠĠĠĠĠĠ Ġoverride Ġfun Ġto Code (): ĠString Ġ= Ġ"$ double " ĊĠĠĠ Ġ} ĊĠĠĠ Ġdata Ġclass ĠSymbol ( val Ġname : ĠString ) Ġ: ĠExpr () Ġ{ ĊĠĠĠĠĠĠĠ Ġoverride Ġfun Ġeval ( env : ĠEnv ): ĠExpr Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġenv . find ( name ) Ġ?: Ġthrow ĠInvalid Name Exception (" Symbol Ġnot Ġfound : Ġ$ name ") ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġoverride Ġfun Ġto Code (): ĠString Ġ= Ġ"$ name " ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġdata Ġclass ĠList ( val Ġlist : Ġkotlin . collections . List < Expr >) Ġ: ĠExpr () Ġ{ ĊĠĠĠĠĠĠĠ Ġoverride Ġfun Ġto Code (): ĠString Ġ= Ġlist . join ToString ( prefix Ġ= Ġ" (", Ġseparator Ġ= Ġ" Ġ", Ġpostfix Ġ= Ġ" )", Ġtransform Ġ= ĠExpr :: to Code ) ĊĠĠĠĠĠĠĠ Ġoverride Ġfun Ġeval ( env : ĠEnv ): ĠExpr Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( list . isEmpty ()) Ġ{ Ġthrow ĠException (" Eval Ġempty Ġlist Ġimpossible ") Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġwhen Ġ( val Ġc Ġ= Ġlist . first (). eval ( env )) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġis ĠCallable Ġ-> Ġc . callable . call ( env , Ġlist . sub List ( 1 , Ġlist . size ). map Ġ{ Ġit . eval ( env ) Ġ}. to Typed Array ()) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġis ĠLambda Ġ-> Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġnew Env Map Ġ= Ġc . params . zip ( list . drop ( 1 )). associate To ( mutable Map Of (), Ġ{ Ġit . first . name Ġto Ġit . second . eval ( env ) Ġ}) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġc . body . eval ( Env ( env , Ġnew Env Map )) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġ-> Ġthrow ĠException (" Eval Ġlist Ġhead Ġmust Ġbe Ġprocedure ") ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ// Ġcurrently Ġcallable Ġvia ĠK Callable , Ġwhich Ġlike Ġjava Ġuses ĠArray Ġfor Ġvar args . ĠFuture Ġconsideration Ġto Ġuse ĠList Ġfor ĊĠĠĠ Ġ// Ġnatural Ġiteration . ĊĠĠĠ Ġ// ĠQ : Ġshould Ġthis Ġbe Ġan ĠExpr ? ĊĠĠĠ Ġ// ĠA : Ġ( for Ġnow ) Ġyes , Ġas Ġit Ġstill Ġs its Ġn atur ally Ġin Ġthe Ġresolved Ġtree Ġstructure . ĊĠĠĠ Ġ// ĠAltern ative Ġidea : ĠList Ġgets Ġeval 'd Ġinto Ġa Ġbound Ġprocedure . ĠHow Ġdoes Ġcur ry ' ing Ġfit Ġinto Ġthat ? ĊĠĠĠ Ġdata Ġclass ĠCallable ( val Ġcallable : ĠK Callable < Expr >) Ġ: ĠExpr () Ġ{ ĊĠĠĠĠĠĠĠ Ġoverride Ġfun Ġto Code (): ĠString Ġ= Ġ"< procedure >" ĊĠĠĠĠĠĠĠ Ġoverride Ġfun Ġeval ( env : ĠEnv ): ĠExpr Ġ= Ġthis Ġ// Ġthrow ĠIllegal Caller Exception (" Callable Ġcan Ġonly Ġbe Ġeval 'd Ġfrom ĠList ") ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġdata Ġclass ĠLambda ( val Ġparams : Ġkotlin . collections . List < Symbol >, Ġval Ġbody : ĠExpr ) Ġ: ĠExpr () Ġ{ ĊĠĠĠĠĠĠĠ Ġoverride Ġfun Ġto Code (): ĠString Ġ= Ġ"( lambda Ġ(" Ġ+ Ġparams . join ToString (" Ġ") Ġ+ Ġ") Ġ" Ġ+ Ġbody . to Code () ĊĠĠĠĠĠĠĠ Ġoverride Ġfun Ġeval ( env : ĠEnv ): ĠExpr Ġ= Ġthis Ġ// Ġthrow ĠIllegal Caller Exception (" TODO ĠLambda Ġcannot Ġbe Ġeval 'd ") Ġ// Ġbody . eval ( Env ( env , Ġmutable Map Of (* params . map Ġ{ Ġit Ġto Ġenv .} Ġ))) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġsealed Ġclass ĠForm Ġ: ĠExpr () Ġ{ ĊĠĠĠĠĠĠĠ Ġdata Ġclass ĠBegin ( val Ġargs : Ġkotlin . collections . List < Expr >) Ġ: ĠExpr () Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġoverride Ġfun Ġto Code (): ĠString Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġargs . join ToString ("", Ġ"( begin ", Ġ" )", Ġtransform Ġ= Ġ{ Ġ" Ġ" Ġ+ Ġit . to Code () Ġ}) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġoverride Ġfun Ġeval ( env : ĠEnv ): ĠExpr Ġ= Ġargs . fold ( Nil Ġas ĠExpr , Ġ{ Ġ_, Ġexpr Ġ-> Ġexpr . eval ( env ) Ġ}) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġdata Ġclass ĠIf ( val Ġpredicate : ĠExpr , Ġval Ġcon sequent : ĠExpr , Ġval Ġalternate : ĠExpr ?) Ġ: ĠForm () Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġoverride Ġfun Ġto Code (): ĠString Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġ"( if Ġ(${ predicate . to Code () }) Ġ(${ con sequent . to Code () })" Ġ+ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( alternate Ġ== Ġnull ) Ġ")" Ġelse Ġ" Ġ(${ alternate . to Code ()} )) " ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġoverride Ġfun Ġeval ( env : ĠEnv ): ĠExpr Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġif Ġ( predicate . eval ( env ) Ġ!= ĠExpr . Boolean . False ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġcon sequent . eval ( env ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} Ġelse Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġalternate ?. eval ( env ) Ġ?: ĠNil ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġdata Ġclass ĠDefine ( val Ġsymbol : ĠSymbol , Ġval Ġvalue : ĠExpr ) Ġ: ĠForm () Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġoverride Ġfun Ġto Code (): ĠString Ġ= Ġ"( define Ġ${ symbol . name } Ġ$ value )" ĊĠĠĠĠĠĠĠĠĠĠĠ Ġoverride Ġfun Ġeval ( env : ĠEnv ): ĠExpr Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġenv . update ( symbol . name , Ġvalue . eval ( env )) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreturn ĠNil ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġdata Ġclass ĠSet ( val Ġsymbol : ĠSymbol , Ġval Ġvalue : ĠExpr ) Ġ: ĠForm () Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġoverride Ġfun Ġto Code (): ĠString Ġ= Ġ"( set ! Ġ${ symbol . name } Ġ$ value )" ĊĠĠĠĠĠĠĠĠĠĠĠ Ġoverride Ġfun Ġeval ( env : ĠEnv ): ĠExpr Ġ= ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġenv . find Env ( symbol . name )?. update ( symbol . name , Ġvalue ) Ġ?: Ġthrow ĠIllegalStateException (" symbol Ġnot Ġfound ") ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġdata Ġclass ĠQuote ( val Ġexpr : ĠExpr ) Ġ: ĠExpr () Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġoverride Ġfun Ġto Code (): ĠString Ġ= Ġ"( quote Ġ${ expr . to Code () }" ĊĠĠĠĠĠĠĠĠĠĠĠ Ġoverride Ġfun Ġeval ( env : ĠEnv ): ĠExpr Ġ= Ġexpr ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} Ċ } Ċ Ċ fun ĠBoolean . to Expr (): ĠExpr . Boolean Ġ= Ġif Ġ( this ) ĠExpr . Boolean . True Ġelse ĠExpr . Boolean . False Ċ fun ĠInt . to Expr (): ĠExpr . Long Numeric Ġ= ĠExpr . Long Numeric ( this . to Long ()) Ċ fun ĠLong . to Expr (): ĠExpr . Long Numeric Ġ= ĠExpr . Long Numeric ( this ) Ċ fun ĠFloat . to Expr (): ĠExpr . Double Numeric Ġ= ĠExpr . Double Numeric ( this . toDouble ()) Ċ fun ĠDouble . to Expr (): ĠExpr . Double Numeric Ġ= ĠExpr . Double Numeric ( this ) Ċ