/* Ċ Ġ* ĠCopyright Ġ 2 0 1 8 ĠA aron ĠGal uzz i Ċ Ġ* Ċ Ġ* ĠLicensed Ġunder Ġthe ĠApache ĠLicense , ĠVersion Ġ 2 . 0 Ġ( the Ġ" License "); Ċ Ġ* Ġyou Ġmay Ġnot Ġuse Ġthis Ġfile Ġexcept Ġin Ġcompliance Ġwith Ġthe ĠLicense . Ċ Ġ* ĠYou Ġmay Ġobtain Ġa Ġcopy Ġof Ġthe ĠLicense Ġat Ċ Ġ* Ċ Ġ* ĠĠĠĠ Ġhttp :// www . apache . org / licenses / LICENSE - 2 . 0 Ċ Ġ* Ċ Ġ* ĠUnless Ġrequired Ġby Ġapplicable Ġlaw Ġor Ġagreed Ġto Ġin Ġwriting , Ġsoftware Ċ Ġ* Ġdistributed Ġunder Ġthe ĠLicense Ġis Ġdistributed Ġon Ġan Ġ" AS ĠIS " ĠBASIS , Ċ Ġ* ĠWITHOUT ĠWARRANTIES ĠOR ĠCONDITIONS ĠOF ĠANY ĠKIND , Ġeither Ġexpress Ġor Ġimplied . Ċ Ġ* ĠSee Ġthe ĠLicense Ġfor Ġthe Ġspecific Ġlanguage Ġgoverning Ġpermissions Ġand Ċ Ġ* Ġlimitations Ġunder Ġthe ĠLicense . Ċ Ġ*/ Ċ Ċ package Ġgal uzz i . kode gen Ċ Ċ import Ġjava . io . Writer Ċ import Ġjava . lang . Integer . max Ċ Ċ /** Ċ Ġ* ĠA Ġlanguage - agnostic Ġoutput Ġmechanism Ġfor Ġgenerating Ġcode . Ċ Ġ* Ċ Ġ* ĠThis Ġclass Ġallows Ġfor Ġrecursively Ġwriting Ġa Ġtree - like Ġstructure Ġof Ġcode Ġelements , Ċ Ġ* Ġas Ġwell Ġas Ġhelping Ġout Ġwith Ġindentation Ġand Ġnew lines . Ċ Ġ*/ Ċ class ĠCode Writer ( private Ġval Ġoutput : ĠWriter ) Ġ: ĠAuto Closeable Ċ { ĊĠĠĠ Ġprivate Ġvar Ġindent Ġ= Ġ 0 ĊĠĠĠ Ġprivate Ġvar Ġtrailing New lines Ġ= Ġ 0 ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠIn crements Ġthe Ġcurrent Ġindentation Ġlevel . ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġfun Ġindent () ĊĠĠĠ Ġ{ ĊĠĠĠĠĠĠĠ Ġindent ++ ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠDec re ments Ġthe Ġcurrent Ġindentation Ġlevel . ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġfun Ġout dent () ĊĠĠĠ Ġ{ ĊĠĠĠĠĠĠĠ Ġindent Ġ= Ġmax ( 0 , Ġindent Ġ- Ġ 1 ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠEns ures Ġthat Ġthe Ġnext Ġ[ non - newline ] Ġcharacter Ġwritten Ġwill Ġbe Ġat Ġthe Ġbeginning Ġof Ġa Ġnew Ġline . ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġfun Ġnewline () ĊĠĠĠ Ġ{ ĊĠĠĠĠĠĠĠ Ġif Ġ( trailing New lines Ġ== Ġ 0 ) ĊĠĠĠĠĠĠĠ Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġwrite ('\ n ') ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠEns ures Ġthat Ġthe Ġnext Ġ[ non - newline ] Ġcharacter Ġwritten Ġwill Ġbe Ġat Ġthe Ġbeginning Ġof Ġa Ġnew Ġline , ĊĠĠĠĠ Ġ* Ġand Ġalso Ġprece ded Ġby Ġa Ġblank Ġline . ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġfun Ġpad () ĊĠĠĠ Ġ{ ĊĠĠĠĠĠĠĠ Ġwhile Ġ( trailing New lines Ġ< Ġ 2 ) ĊĠĠĠĠĠĠĠ Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġwrite ('\ n ') ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠWrites Ġa Ġsingle Ġcharacter . ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġfun Ġwrite ( c : ĠChar ) ĊĠĠĠ Ġ{ ĊĠĠĠĠĠĠĠ Ġif Ġ( c Ġ== Ġ'\ n ') ĊĠĠĠĠĠĠĠ Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġoutput . append ('\ n ') ĊĠĠĠĠĠĠĠĠĠĠĠ Ġtrailing New lines ++ ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġelse ĊĠĠĠĠĠĠĠ Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( trailing New lines Ġ> Ġ 0 ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġfor Ġ( i Ġin Ġ 0 Ġuntil Ġindent ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġoutput . append (" ĠĠĠ Ġ") ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġoutput . append ( c ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġtrailing New lines Ġ= Ġ 0 ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠWrites Ġa Ġsingle Ġcharacter . Ġ( for ĠDSL ) ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġoperator Ġfun ĠChar . unary Plus () ĊĠĠĠ Ġ{ ĊĠĠĠĠĠĠĠ Ġwrite ( this ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠWrites Ġa ĠString . ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġfun Ġwrite ( str : ĠString ) ĊĠĠĠ Ġ{ ĊĠĠĠĠĠĠĠ Ġstr . forEach (:: write ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠWrites Ġa ĠString . Ġ( for ĠDSL ) ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġoperator Ġfun ĠString . unary Plus () ĊĠĠĠ Ġ{ ĊĠĠĠĠĠĠĠ Ġwrite ( this ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠWrites Ġa Ġnumber , Ġby Ġcalling Ġits ĠtoString (). ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġfun Ġwrite ( num : ĠNumber ) ĊĠĠĠ Ġ{ ĊĠĠĠĠĠĠĠ Ġwrite ( num . toString ()) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠWrites Ġa Ġnumber , Ġby Ġcalling Ġits ĠtoString (). Ġ( for ĠDSL ) ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġoperator Ġfun ĠNumber . unary Plus () ĊĠĠĠ Ġ{ ĊĠĠĠĠĠĠĠ Ġwrite ( this ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠWrites Ġa Ġpiece Ġof Ġ[ CodeGen ]. ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġfun Ġwrite ( code : ĠCode Gen ) ĊĠĠĠ Ġ{ ĊĠĠĠĠĠĠĠ Ġcode . invoke ( this ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠWrites Ġa Ġpiece Ġof Ġ[ CodeGen ]. Ġ( for ĠDSL ) ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġoperator Ġfun ĠCode Gen . unary Plus () ĊĠĠĠ Ġ{ ĊĠĠĠĠĠĠĠ Ġwrite ( this ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠWrites Ġa Ġcode Ġelement , Ġby Ġcalling Ġits Ġ[ Code Element . build ] Ġfunction . ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġfun Ġwrite ( element : ĠCode Element ) ĊĠĠĠ Ġ{ ĊĠĠĠĠĠĠĠ Ġwrite ( element . build ()) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠWrites Ġa Ġcode Ġelement , Ġby Ġcalling Ġits Ġ[ Code Element . build ] Ġfunction . Ġ( for ĠDSL ) ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġoperator Ġfun ĠCode Element . unary Plus () ĊĠĠĠ Ġ{ ĊĠĠĠĠĠĠĠ Ġwrite ( this ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠWrites Ġa Ġcollection Ġof Ġcode Ġelements , Ġby Ġcalling Ġtheir Ġ[ Code Element . build ] Ġfunctions . ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġfun Ġwrite ( elements : ĠIterable < Code Element >) ĊĠĠĠ Ġ{ ĊĠĠĠĠĠĠĠ Ġelements . forEach ( this :: write ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠWrites Ġa Ġcollection Ġof Ġcode Ġelements , Ġby Ġcalling Ġtheir Ġ[ Code Element . build ] Ġfunctions . Ġ( for ĠDSL ) ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġoperator Ġfun ĠIterable < Code Element >. unary Plus () ĊĠĠĠ Ġ{ ĊĠĠĠĠĠĠĠ Ġwrite ( this ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠWrites Ġa Ġcode Ġembed d able , Ġby Ġcalling Ġits Ġ[ Code Embed d able . toString ] Ġfunction . ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġfun Ġwrite ( embed d able : ĠCode Embed d able ) ĊĠĠĠ Ġ{ ĊĠĠĠĠĠĠĠ Ġwrite ( embed d able . toString ()) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ/** ĊĠĠĠĠ Ġ* ĠWrites Ġa Ġcode Ġfragment , Ġby Ġcalling Ġits Ġ[ Code Embed d able . toString ] Ġfunction . Ġ( for ĠDSL ) ĊĠĠĠĠ Ġ*/ ĊĠĠĠ Ġoperator Ġfun ĠCode Embed d able . unary Plus () ĊĠĠĠ Ġ{ ĊĠĠĠĠĠĠĠ Ġwrite ( this ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġfun Ġclose () ĊĠĠĠ Ġ{ ĊĠĠĠĠĠĠĠ Ġoutput . flush () ĊĠĠĠĠĠĠĠ Ġoutput . close () ĊĠĠĠ Ġ} Ċ } Ċ Ċ /** Ċ Ġ* ĠA Ġcode Ġgeneration Ġfunction , Ġwhich Ġis Ġinvoked Ġwith Ġa Ġ[ Code Writer ] Ġreceiver Ġto Ġprovide Ġa Ġfluent Ġsyntax . Ċ Ġ*/ Ċ type alias ĠCode Gen Ġ= ĠCode Writer . () Ġ-> ĠUnit ĊĊĊ