From db3d4f4a8673f50cdb2fbc7a8db25a60296e8bf6 Mon Sep 17 00:00:00 2001
From: Pierre Wilke <pierre.wilke@centralesupelec.fr>
Date: Mon, 2 Mar 2020 17:44:34 +0100
Subject: [PATCH] fix errors in nfa_to_dot by catching errors in e_regexp +
 other stuff

---
 .gitignore                              |   1 +
 Makefile                                |   2 +-
 Sujet.pdf                               | Bin 498194 -> 497584 bytes
 src/Makefile                            |  15 +++----
 src/cfg.ml                              |  42 ++++++++++++++++++++
 src/cfg_dead_assign.ml                  |  50 +-----------------------
 src/cfg_liveness.ml                     |  50 ++++++++++++++++++++++++
 src/cfg_loops.ml                        |  11 ++++++
 src/cfg_run.ml                          |   3 +-
 src/e_regexp.ml                         |   7 +++-
 src/main.ml                             |  26 +++++++++---
 src/options.ml                          |   1 +
 src/utils.ml                            |   9 +++++
 tests/basic/loop.e                      |  15 +++++++
 tests/basic/loop.e.expect_14_12_3_8_12  |   1 +
 tests/basic/loop.e.expect_1_2_3         |   1 +
 tests/basic/loop2.e                     |  12 ++++++
 tests/basic/loop2.e.expect_14_12_3_8_12 |   1 +
 tests/basic/loop2.e.expect_1_2_3        |   1 +
 tests/basic/loop3.e                     |  14 +++++++
 tests/basic/loop3.e.expect_14_12_3_8_12 |   1 +
 tests/basic/loop3.e.expect_1_2_3        |   1 +
 tests/basic/loop4.e                     |  20 ++++++++++
 tests/basic/loop4.e.expect_14_12_3_8_12 |   1 +
 tests/basic/loop4.e.expect_1_2_3        |   1 +
 tests/test.py                           |   1 +
 26 files changed, 223 insertions(+), 64 deletions(-)
 create mode 100644 src/cfg_liveness.ml
 create mode 100644 src/cfg_loops.ml
 create mode 100644 tests/basic/loop.e
 create mode 100644 tests/basic/loop.e.expect_14_12_3_8_12
 create mode 100644 tests/basic/loop.e.expect_1_2_3
 create mode 100644 tests/basic/loop2.e
 create mode 100644 tests/basic/loop2.e.expect_14_12_3_8_12
 create mode 100644 tests/basic/loop2.e.expect_1_2_3
 create mode 100644 tests/basic/loop3.e
 create mode 100644 tests/basic/loop3.e.expect_14_12_3_8_12
 create mode 100644 tests/basic/loop3.e.expect_1_2_3
 create mode 100644 tests/basic/loop4.e
 create mode 100644 tests/basic/loop4.e.expect_14_12_3_8_12
 create mode 100644 tests/basic/loop4.e.expect_1_2_3

diff --git a/.gitignore b/.gitignore
index 18688d3..8102f28 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,6 +3,7 @@ tests/**/*.cfg
 tests/**/*.cfg0
 tests/**/*.cfg1
 tests/**/*.cfg2
+tests/**/*.cfg3
 tests/**/*.e.dump
 tests/**/*.e.html
 tests/**/*.exe
diff --git a/Makefile b/Makefile
index 5cbca0c..1cac380 100644
--- a/Makefile
+++ b/Makefile
@@ -9,7 +9,7 @@ main.native:
 			-t grammar.html
 	./configure
 	make -C src
-	cp src/main.native main.native
+	ln -sf src/main.native main.native
 
 
 clean:
diff --git a/Sujet.pdf b/Sujet.pdf
index 91b343c098fa8b5ffdb6a8055a32342e9d93248b..6cd99d9db240f72fa9761f1fbbec548db85b35dd 100644
GIT binary patch
delta 18082
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
B`bPi&

delta 18688
zcmV)GK)%1QuO5=L9<Yul1354^laVK51_XD1yVzZm`X@er(B*Q}=f7?)UcKQ(#waOh
z!LplA88?au!7`&Pp%$9f*@ygcySb~Ia#wHL#nKun@|&wyi=_}EU+ueo-}~$D+E0rm
z%eU9n$~Umri=S`)eevzhh($w*)f)O2#4?RseE6AWYk2nWj1p1U>@P>T$)q;KFay_3
zb`6q5j2zd0!eJz&=E!yI6q-!nnFA|~tNe%VwruM@FfWYC*L(lF3Q|@34%tkRV44)d
zWJ?a8QQUWWRW6oX7x_mj<n6wz{2lW@>uuYHmVN7g%RBfrdDVRs((D6SplL#1{jS@u
zc0*_DKsM&iHT<y;6n`$b&9?};`$W@J|MQpd6~)RbX2J5hM@3X{)e+=?<{t&6p6agb
zcD3u%=Ia;0Daa1i5u{~;C|P)EQOc8FDHwk!$h}IcIY=!LT1JwW*dxuG7iC*EfA>yK
z{6tfIu2&$1d-{<oy4}xxj{&C)tR?gYZ&kBu<RB0q$e=&wd%i`mTKv;hUFkoKYV%(e
zYX8|^uRW5U*XlF8KsQx?mOD*}7K5z2?eA6F&#@;c;Zly-Bc7Mb>X?@vId$rilo5Z%
z6MdlpqClWqVL;=O`l|`V*wFvoF2F2z<>%U46_Vd0i-c<tdAwUFmX}>W4>!moU|3J!
z#_s>v*ZyK%{fThn<wOO($qgL%ExTX3D!veyMnxdw78wtX<u5RN%6c~vVon4u04B>L
zTdz?BeA9`t+67FxC6=-&rq_SB@HKycU)lU-VNCAcsr;WA`IRP|*|Cj-AKaqH5i);$
zeG@edtyeGL-e30K1c3ykY5PyxZsQe+57*G*AMVk=IC^{vs%uxFVI6*(vPGC~%Uc}$
z;kDX>R{2iXby;^+aM}NG4mx^Pz(5fx1VEsO;ZcWNPpLjEW#LsNHOue1?QMToZZ;L(
z()`<(zS$`p8=T(i&0T{WZ7Oeh{*jXhiM#5~Ij_D7`t{x#A0ZZ1gHEjqJy+q$50~Yp
zdFgvXuQ_D~RSHf`IB7--4IT^}p2`22NI%en^sG29K7u<E9|665g95zuH>b>zag0}k
zIbLpCZ;IPy`KH<a<*n_lx6XgNU+2uMP{gXltIbKoK_pP*QzUx7uo&;pNW=;v`QRho
z4};{k?sqPDOvVq|xNkN2m2bG+qs`96VQ?u%ng__LC}cPfw%r*~uj;lcyV>69lQ6t`
z7={*n2aAF_T(<aU<q!%93?K$L>c`;7i52=GI5I+|d6K}d`@Y)XNcexH@qrx;>AP!m
z1((a8h#Q?65{ASyFMlmpu16fwmH%BiUj-N7+t9CtyBa)#_azg*hFBDN)$c+l_+(es
zO%wbnc33ahRS$lkf9V^lKs>w!<a>w?hgW(h19aTHfIP$bvI&n(d7MQlFVdUZCyIyw
zFUbT$NQ{SsA5z$YL(WzUc>}~C%<40sdz(4p3zr!yNR6=>{=sX+8WsL_w<j85RN6uT
zy5I;1$ByCGQVuPQ6D7D3SyyEjpR$X0u?xozW=#S^p&^<}WCv^lI`;pMuUDIF%9F+{
zCx5-YLqUe`1u+g%yc-GnAOMXfiVFMX2r>)aNZ79qp}^4zuKx^#kt~6brx2!eM-WCi
z9*?1*Ff|b9P`(gCK`k-be02z=DTub_9E6c9fl#CnrgTRTMme4Wp#--;6-?h5)kGHs
zm0yA)cUcV;ghJNwHDP4%Rg6BsKyeR@NPiZo0*rDF#xdP2j3~%RjxQe05~Stag`F?O
zkx9^jGG8A@0TEDv-JHQOk|j8*qY<6Z9gpZB$Q+K4YGD}({ss)E4NF5LW5CxKK7(0{
zWM|-83SvMDUmZQjU<i}y9D0##g5EG;PUA{KoI>bDd4e5sWnn&Aa1A~YdXeBA)PI9R
zv*v_zwBQ1wJ9y@=HlAUU%p`OSJ{tU$I5nOFS)>YfsE@{TLU$aTgCHY0JdW>Tma~N6
zstY4Vp~DKugaEG$oUP)NJB+RqOS7OC`~bfEMerP~3X^43;Dp!^wDJ>H704o$uP*pv
zOPG-RYF2e*V#%9c_`$%u1cLwrD1QY+63FQI0T2LBF|F<cgi#KYGx;PyxB=j$JO@Z5
zI}J!udrDwQ-=D&=jFKD!!@*QImzIr81t%7q-2)5<Pl(fK^i9e>4j75^7lZkj(!|P>
zqb86=DhJHlLjf#K?}l2A%)dPvQAr;OI8mBGm;*SFff?!4cktU-gwU!0Hh=E{h!#X(
zXtI`okv$F}0U0DOFuobkp3tY_n*}!j8IFKF0JQlKgkrJ9)p|f|bYA0H&kuLIdJ}5@
z{ZX6@Y>l{@pczCzNIt*`e#<axr)W}0lOd5d_n@gY5tzb(psaW#m|Q@(#bq2}7?Jc8
zn2{_}Jpj!23oEfkk&eiur+);dAk#sl0i~q`&m;sFW0-V-6*h6N`<4nOt>$SkF|Hud
z6X#%xWD}UKYKKwT#Z{x!btf-P5eeMS0Rr>|$505y1+Xy&fsNs^9Oq2jhlqy6w{UYY
z14gbN2?_X4jj0<q7<$wxNCH`;@*cctwu>c<wbhZ~h`g(?$cH866o06st0_=HsF6(L
z0Vajgb_^6mK3fPFboY)gY8*^h$k&e@V44(#i+GHfLY*97o-9&5V1Qkn8er3&jt3YD
zHInJz)|rK9$UIIli_~Cb5FB*|-C9M9S+~wPO#0Om4N4R^-&N-fDw0hN>iYZl3&vRf
z6IMoVtD`}dzLk3CAb-J;^&ARiODkcrqQPQNj14*@j=rjJ_sxJwBKL&K3y(`$))dg`
zhwNw9z6Ks3<Yd1AggDL>D2S*+Le{atCR$)501OHZIezFKZg3{R3u}Gb%Kcr&N5gx|
z_~Ov{GWNd8uCsU9C`BF+0s9aXrzTcB(q~#2tyn6QT28{WP=Av(Tu&8=?pf`HYz43A
zVKMnQ4NiKSYB`9s9Axq;hD^^ES`T^!&%gvsBJS7ggzEX|RY^j{Q?v?6F#)e~q}9Zo
zd8&z4hm~jaVSW`nbzRf9k}>L8Pqmkb2f8#^PGIEm0zx`gpxr{k!4*3xp(l$}ao0dx
z&_5DwN}kH*`F|eR_OdZBGDRWjiKfXVB}yCIe{i2|PRX8+adIqdLMVQMd1AJ&v6^we
zeMYj0f#ULc8a5KTqom$5oEjyESV1kd+RYxND&XN}(yVbC30A%aB{~?{NYFXzXQWGr
zqy=+|z)a$ilVJr}ioi}>T6-!bh-8t<Y4doxn^2{?41WwC_zk**$*z(TBbmkB3>H!#
zV3>hUq~*}hp?T2dax9)#>J0hwQ6__|Nn>f=GNP$?<j|C0#m3E{EU;it4b4Cnsr*9j
zVP-xVo(XMQ-U)0Uxb`ZA`G5k^6OD2TBh_g6Fon)gKOcSKt}693ZF0&8H|LZYs3y9M
z8$i+sIe#ThROvZR6^WZrt;TAls|nb`Ld@Gt+hO1_f%^ncd)is@XOyc8tQBF_Bd~(-
z$igFoq`@-mjbp9hRN*m_MXFfhz>O~Hd_5seYSNzR5ziqVhxt+=+|mw=EUIu@A}|f}
zP-85cG@nd>=7^tBjt&SgtOkO)bM|HH)RUyr_kT0$CZv@BkK)!Q2y+H=UoHKY&q6#)
z{hT6NLEPf&BQPHAoq!<VDqsZ>_Vm^XM-_>}W~^Bsn2;WYGsp9hKDmW-zX+wOkwOKQ
zY`CTm8#A-i&nVw4fJ-W$s8Olivd=k{MzV=cUtfPeY)rdc{&bXnChw%_XW;)xyTIs&
zjDHgV&5GeSYT?Y&rBN_Q-B9PiK9gAHkPs;qSQ^j^MYtR)ddUJiBu@-=P+)=dA$T6P
zQ5CLE>z0G(BF*^u2!rs!!}sQ9_#E;Bj2jR(!aVvBT82qD#nQDbVBW3xDJ=)GNagqY
z?(baXy21k$M><a4NOc@|UmlnruTaC^)_)frlhZrPu$yl=+Ro?rm39)Etsq#*=EBF_
z@qWRXdK&Iskt){HSlmp?RoGmfoHfC=!?y6S_<A^N;vVnAA)e_;m_eTSn;y4WG9_S4
z__Z2Sgk@e4PTbrq3W<9u`-h&YaW!Cfphakv@4D^Y9dW5TJlG<%jyvGt%5S_>{(q=T
zP;9r`))BF3trC+%b%1PliYdX}#;ic*H=ydgY7cu@{a4p7w)<V(1YQp3aPTfNv%zid
zyImRgxx4o&PlF7&?YhwRCqCcqx<#m~;fRM+mg?ye=14VoY(Ucd%I$!Ki}kke>#FN#
zCFcU2bQG!Vy7KSY(=nE4VGhR?W`DZU#0=2<Qug)gWIy`B{e0TDtFmckt(=al#%Fu#
zs<QcS+1<|SRk5-9&-MkQqi*MWf_W<*4GDzRZXWY7jUQ^W)@BJc!&dp#)*pGOtF{fN
zA5gsvjHdT?0ogUtGC9UD?6>am;DgD(^*;xj#Jgyd?%>79Ch^(Y9lbc%B!9LwvA0j#
zc7+RAZQ0a2cQC`ZueM!R^}gF}yDlTY_^jOf-*&qRU)cLEfSqFX7;P08@q54NRGM%0
z-Ov|0rY4?GaR*(>b`|gATH4KzxS00R-?ZC!0x@1mgmqO7Tg1Dn+qQwG`n+oPeeGS$
zrW${?k6YD;?|YXqah74&&3{<{o*+`peBo#z;rJ0)K4;1BzuI<v+-mMF*c6h{9(1q>
zr<dQVUD($?c2Eq@7<qq6^Af}kTE$y`Qp`WV=BD0u-c8ZLO~uXl<5P+5tKJskt=n#2
zwd+XVZ`+eQ<HLS_M3v>i<2$Uwp}W1mz9gO^Kp|K#f_O3j8miCm&3_&@dAuC;7Hom#
zJ}?509sp=TFJAXfMu8^|<5?+oP&l4E+IMXozZni;0X2H;*jj(2LiiJG-jMn^^Dg(h
z;l$N(<m$=MQ4_bu9kSGLTI?G@E7<#+&~$@w6AZg*!a1`au^~MCPu=|PFoi)VA>O=M
zDDBkqXXj6I0?jgH4j*nM7TTL|Oo4K+2PPFQ@E9#Nz4DaIq~{m@4|Y@%Zj%9R6SMs`
z&tC&GFff;4!2v3N+fv*}5`EWK)SDr8kyLlp1mTDV40eQPAi(4C4)7q<MWb1@)T@gF
z@7K>ssoON>)`Z)GO*={|rBazEPgZ70ip4BpGG>lh&A4DZ#vt*-VDQ6W@smu%_+j8o
zh=d8ngpq;JOhOtHQeo0DsST5YNynL#OhK76OsSYj%M_G<;Yedrai*2S1*Q`hD9sF1
zK!Y(DU<yREU=|m&WY*y(!xC7aElWrYMkkUP&K&G9iaEmrXm^QW(7<DX(P4xFOFmh{
z-~#77W;o;=&$n=kLq3V&Hnb!hqr$nunD8JW8~_MJxP+ll#<+6HfRN!3k8#Px^c)9V
z;5O;Ufq^}L81azA0<D;=WkO0BBoI`v&<Vf?OPmIFv4!Cnb<A*E;v~aQI7x;AO%4cv
zfRtna41zJ5TmaUI3E%^;r5F*$K!kHdAt4(fkpN825d_i-_W(Ta{bh=L<-kcvLIMCN
zB?tmU4S@<cIH8QA8H$X63>;KW0|3NX$1&WM3BrVbun=3cB%~>@S`&W^f<=%}#1n%V
z$hz1Dc(!&LEP{Y@1hPduCG3PjMo`!kLfaby4jAo7iDJfTx`f~-ga)v3k|F}`IGY4q
zQ>YcpB*sXvgM%zq6AB6=?1r`0kl9dV4W6bzF#}~Be6p6b8RCV7!{AFIM6kWhq7xP!
zR39pT7VWW(#%FC_l_B3`uU`inJ6+4ho@Ksa&6(6ZE$I+5ZJmBjyK6S9(>DKK=bOz3
zRf$2>VLeI9yh&+}jXRcA(^+1mt?%lG@0G*7AAHk3@&q-PI^w^uQJEHB8YpFjzs|F?
zxaYR+;_ICYNB66;pJ`av=EdM+k+LGcsMEZE&OK||v>d1Pm>uq>)2Eb*$IV_AoqM=P
z=w4KlbmE`5Vc{$VATQXN1poZyC9ZeAzW?4^w=X<?b3Lnl)AT;q^z=zr<QU_cyzk(B
zN!GA8tLPLf==3G~ZGY6PqHY<K*4NYghB&XfUJYs6+aIl>Y!2ArMeEB!hbL~3SyPyQ
z)dN_(N^?xZ?faF^)#(M%#4^#EFJ+rvQx-fLI=w)C^!{jcFd_}?{rj^GezwVuMs?$B
zcHm22kJ{?VI6~JAbL(l^&iOj2)9Dn1^{XgYB<5@&{`l2k*xg&x+02*Y{5l*Bcf2c+
z4Mj1J2+@TCMKb;R@Q8w)LBX%SF7on!-vm3@LaEg|FsrM<fnM>`iMF%A;2VS3p#O<`
z#j-8Tx9nrybZNm(+HRazY_}TUMe!8HGG@mt+Rxi_x_x^)h(3Ioc@`ZZS%PS{Dv4$d
zbBY9m=-4+^SJSGA0@cs_>c@GyQ(d#u7!xQJp|Dhyd6>BK0D5XDK((8TAJkQUH=}yn
zpN-10g7#A?ykrRKZa=twKqaB!JeXUyTl*AjVjCGaQ891^>A=o5uG)6?OBD69Kzw$U
zXH8hule5iD7*JQ^F7wa3>lPGPOxqwj=`Py-^h4cwx)4M=Y2)c4i~ig@JpQ!*uRZ@)
z`msAn%O(J%b<^%%r8WAiAbOvF&QB5@^a}TUlhyf*+@ZdtN8?SIRpY#zu;`Dx9F<MJ
zm<TX2Zm$R^$qA`-{8@{dEcyIQ^bx-OXE0|_W(~Drk|UZQs^7~THhJpNdZX_kb>rCJ
z=x^!N-wzNj?x)kd_`)`Zc}5oyvi%~RG(Bu2v(uA{ZJ|qy*_JYB2yEYf9Z3O;-XT-+
zY*bDP&ted&$%t-FBtb-$(8-pN0DU)|z4iIzs_pMYJX=5gh;DK?dfOlMCZS$Z3z{t4
z6GjA}v|IACCviZTgt}EWGvavm1;(I}=qPP)WzT=kGk<)ra~q<b@k?xapO^myld5{`
z>pp|{dGt1V7ww+*kvXS-l*?LnicT#=t0!e>`o=a1Et)5^mLVEdNR8Oz4a-`LP>Bi?
zi+zBI!x#;maw3#{Ps&4+s7K9^51Mh`b8*P{*XJ6C$AS<lbchQ&*HB>hAf*XuiJ806
zdl8Mcw|ni;sDEs968(Psj{f)g-XP&8d0V6xTd3hat+T6;I8vv7Xp*{_FMJkW)=`#^
zYri$?E<mkl(b<u<yu7U7(3Ypk&2_=5g$WJ1dZ1{r^l9lrO(@$?_E~oq)EQRiklSTQ
zmsayn|M`;<WX4dx9CGL^yP`OMK-9*AsL-J?D~TG7f{UJeS(Kqz6jgmPOEb^paLZBJ
zqTeamu#QJ>uG@oulNLQP<KIkB(2kEdhAd?~+8r_e8vllj?7iQ|CdS!$wZf|9+~SzF
zdhy}}`;&OCe4jQK@$hI;_37~9FM^x2y_-S<|9S~EB0E9JJcY@7`^aj4-QJX)dkZ4x
z_S=d`8@Dx<L^n7^TgYKlx2xfIt|yeTv~f$2OxOi-kS?ZwojjHqXYM84Wj^U@A7<%n
zX-~BtV`B8&C^kBFA#HQH4LR`8f`@Sr*^|bsagkeBHqy(0Rnzg7>=XHTpRA6t6zbJv
zMT}9npFMf$y+!<^l2_<E$t%{{&(bTKHD>GDI4RWXoLrXu%1IMy{es-NMG*&>?X&oT
zV|wc+A14ogq=4S;QzYtp=Wj^l)=Q$~rzDY#S0d5N5#y%tNBf#;n_QgGOHlQrRu$>)
z5JK9u5<=>s7f^$t^w#!af;`<<OM^b1UI8Z}q_?vRN@#~pTbSqf)>%3&!n~~Wl-g)C
z(9yWcnrNDqU0Q5abUC7zkp6P>J2wLwD-wO?;0ZQ=^cI@}jMCbdF!==&F<E^zUzUBU
z!?;J*aO^m(UP)G1d#4+Du@2+GilOO~i}*+O3hM4&L9KPKK%Zdx1wqd@3rc<0!l2M2
z()XhT{kXefD3HWCe}0l-JDpBv-DQZ)_f>Zh<`q0iXIG!|{~wk`Ui$A{4y+F8+Z0ZO
z0DRzopA!F|nJ>2lsAp_4)ZNX16mcj({Fh4ATc!GTdfuwrmcHdK#OO=oV$(ohdNsc<
z*>6^XACS@7+{tLIo|Vx?Jf6{7{*=9+)~oYvS$0uItOzB7zKX1t2{x+yaaojoA?QVD
z5*lGv(kn4KAy(2Wv9UJEYO;dcP^r~$KzREKHy&SQ{{}=*sQr@xZ4<NepZawHGLw-f
zD1WUxYjfN-lHc_!=9@>m8k%^6_t-11Bc;6OIJTvGY_0dUm>F8jTFy`*If`??{<_fs
z32-<{B3~uZfQ<&wFEkqH&da-x@7e0UzsOhjt9<qC1%to&imjN;n2{@!n=DsmwcTI*
zc#%mh6(K}T*A<3&z{@v#w)&>M_yGTeu78c6audz@$GeM{H@sM}JS*~ot?oXrxKWu9
zY-N<qatol{>M!fp?f#)|%Asx#mm6!OSl_*UdASinthdLmKlapqbNGC@Ve9s`+7f`h
zy8P?ipDwQNA`(rWS*>Ayky)mZiog6dU+tjpPpdo=g<bvRF!w8|O=g&ZcC)$#PJe=o
z7N`!B0*}ViJXGDjK9o&%xslSYUsp{@t%tHJKMAD=`YaFCcGnK|kH^aQUv9Wrx5th?
zx79HCo}oPs2~suG0dU`y`+Zq=)fIh1yQkLUCAaH#=u*T>whoX(g;E06HcVtn7M}jP
zI_$cV1o==p5zBRtWFh2u@PO*r5Pt-CV%x4f&{s8h{Sf(x`nf%9QH3CsdO&Q#=&P_w
z*|eQsXXpSS_j)ZK9y&LBjeo1mk;`;e2$RzM7AE4r?M;1uMD92**5U_(?O<UKLg87G
zF!pRwKz}ct0<ing9yURHSA^2Ms1AL#N5mf*kG89N>h!qBF9iSbSQDI<seg`60o4Kj
z4urC8_xtLwtvbiaW{H(83a!uyF&TlrM-dmsE4Cg8>d41NgLKV?0&TF;%NwDRy(Tnh
z-7R-Z{i#($GnY1?fJPVQ0GcIZ0q6R^-+x@1iJOdzfK+a`)x$6f1W9$)1i$qT!3K=)
zQ!Zo~qqN5q)sL^M?uw+yt$)t6EoNdwNrRa)h3WvC2fMHKFbH8Nt1oD0`zoXFZ%}rK
zJd{5))Yj|1-h=ajt>ycwFLgh7I>)JlLD8%pGg!Qz=-sht{1gL0ZZ54@w@uR`FF##T
z=i@P~42wiNQw5g5<(=OHH)tu<-irtA*RVDE9&Y%wF#smE^t*3~6@MohLL+oWQlRF}
zchOGV)mw7L*hK~pjmJx+)_y4L>c_f^$HGeG(A8T%QF$aFxWm5ki1#@60spvFvh&;H
zwcoD-{8v-oA6(ObY&uYrSI1#T{hx%)spV`3&<^gHm^KzcrwL!Q2Ws{0@$aScv54R-
zs6;vS*s9QnW=op_oPSovn0#_`6`A7WzNz{lrVxB`yZ0P5W#88$X_KWn(Fn;i4QnT|
z*`e%u6bjm-E}S~0$=A-O-lIklidsRaLkBGk9{l2X@IA?yqS3QC!C)7-Wb$qxgQoHL
z%?mFKnFu3?lh%%`mS5_2UoA;Q6j`1Z0dH5O#E-;e^zAKR6o13%&Tq)$i(D_*MQ(y!
z<ld(MB(ev9e#%uoI*2Qe(f)(H`4!<fL-?5v2AaL8U>u`fw=;0qV~v6eE(5!EN9utE
zsxBkgt;a@|9o1#;1qF^e5|rdQ1Yn~-MLG#hr)U|MBhtG&KU3=AStiwJr~kY>i<P5N
z?v}_=nc*fPhJP(7*JR4-*xa4sVDU_Fp7^&%I0R6-5(MCaCTyWOyECDp?;nq}1KmgC
ze-E^6^`yrIewgJMw`wkz*~zEiyc$jR;O7qq`rtoZP=sWT$9X_=ZX%)WNs<bd8DVEa
zPANhmj~HG&<q@K~{dACmyV%vk(h6{5%B-+F-6D%7QGaB`sLX#Q1j&=RSjHI-DBLeM
z4;*0E2b7z->xU)7;UX)ZXT<uv5uY=_WFp*f5Qn)9$H~XwuiJ3cYD0K2N*AEcPhf<I
z8~M0*2Nmq=c5!PdXzP)`!xBvzbde|(SFQpziOsvf@<rWH^K*IhB!MGt@ObD_P9|3`
ze83A=ihph>M;GK)@_`e&6J}G}aBO=P+l+#8CoYJ`8y~NGabe5H5Rtg>*3caLx;loK
zKAEz=A{@sNbpGr^{q%ML^MU{r#<)yta8NW6-DVJRJQe({qxVafd!*-w8X^iK;~Rrc
z*}R77MFqhO1?f@PM9c5@2}e5!w>PaPu7vIUvww?SoKRj=UmoC)=`k)^3bqy8CZ(G8
z%|>yx{vG`&`uRQmh(!k=GNDH+|2KEB4L8#83m4t-0uMf=;44``d=8ESZ|N(*`*!7!
zFWgO6!BrQ*AKYL1cf781=hZhb9FB7s&NArm|HbX?ew9u=UHEO0u|j~ChelDzGdKQ#
z7JslNx03KP!-Ba!OluLbBds4Io&t*ESpk>%jm#j%cosig!dZxcDAFK=J@<m)(E^s^
z=XY~{=2$5|8&7Q@c8MXD+e~TxRVorWY<)Zyo>oynOH`!hEX}cIECqU>)DqL+r*jj`
z?|DoqoiVgsS>&0?**T^>TEKEl{r-fh8GqKCDNpZ6?h;d+LwIVxPE(SBz2v{BseqPf
zO3ay>W6hWf^v*Q3(WpNN)8H}>qR^}T8JNm)ZJDEss{)B;5dAUeWe|HQ28T6FokPd?
zy<J^M1=n}3BBW+@0f(s85WGx4h#28$g&2k5i7s=!QZP^|0kh#N0|zGovw^o|qJPkK
zLenr6*M?0~X&8uaj4>4~H*l56Wl9Ev4{Ml>=m2&yp{z9%n+yoBK!_Nn0TbSOjgp6s
zn&J0DVk=VPO9?A7&7SF{garYC2Z3WQkDQb-D+>V$93d|9a!3IudAmuxREjsV6QXr9
z68m8lGsWNnZ*>8BF>qT!bK9Q<;(ysDP+8zXl(x`-ZD&<Z+L96tK*LDE!5;<)YD-yg
zIUw^9h|1DnUAidZv2gS&jV%cfJV%&@k-!%kjf6{A;il8DAAkTA;ThZo9BB)a85qgX
zqGCb}7`@3=LWc!SDQ2Ug7D5kUk+P9d3j+l#Fbd?i+YFQ7Ss{SqU?J+cCx3wiia^C+
zH`00WMY{=D0g0YB{`{T4C+G+jpZocEP52vOB$I(o#w*tQxBqc_;(BL`&0VkOdNZ+|
z8XyNDE2*OGxIYWzpoBu%X)klQ0xGU`<Q*_hR=G{w1)^zLFqyau#MB~JJRS`404q_G
zL*g99GKSU=IWEq@bLHTvB7Z~y3&Wl%qUi*XXQZA{1BeFp1W%~}TwR!$7y-eQmFQ?j
zenHsUSXF$5@8aMR8JhX?y_bX_0bkCZc3%PO7yZ{9aemNwg3r4!ILWkzP$DvxWgu*9
zgHHyV=`;XNt>SpE8qY4!tSBM?$QV41=Eg)oP#Ip<nTUtN9k-C~rGGD21qyN#Th8Vb
zXLCBy=5)cWJF{n`H8|lZ3!4Q_H>V=`?ZyLiNj$eWl3YCZ#=&8SDm<CMM~h<FdIDBJ
zI%_?1#MF9--ih4QbPVo9jshvT<_v9Q0R-m_XGSY0%mU&XgF%TAImY!M^CCAca51vr
za)N+#L+mobKwo2oGk*fdC<slW$a7eJjF!-LthI%8;ZlgIBE%4SjkAprT1<#Sf68P^
z31BLn=OP*l9@dD6Pw+R&SS=@cJj3BY08)U_a>vs%<0WQ62L;*;T+ppJ6EJzKfb{=%
z@V&adyZ-p*_TNt;ui1ig&qbV1jL(if!7<q`Qzvx}3W~Nli+^{tJA?|6$2%Wy1)Q;&
z<CvnM#C1$zQ{=+N=xTCMV;GirvMFARF+)@r%{YdCDNQg)7rC7|RhAcUg)3z2<=~{v
zfHA2P$1U-(m3@sjW2%4yM}D0<6ZnLPKKDs?7O;NNoy`&F@sua|oJac*-ii*ZbR4}j
zZK9{9g^Q^LXMY3!KnjzAL-Of*m#MaVy{j;J?pp43u%=9+Pn{yXZ^vgi>z*4wx7|Jr
z_lX=!iA(&AGgtUc)etz;l>tn1#cR8qV}ERhatO%y{3;wtevDu7pO)UC7Za8EuFaR8
z(E*9)(W`YXmgYn?kG?|r%o1n#QYbiIekp`-Z}Kmg&VReyK={1geiB-`x{E6UP!6T0
z50JP^D9{%Z4o6H$|MbOO2(S@5%K@bPC6qtK9*<K1DrN8NV}1_D6;D!ysQni%BQmmA
z6Av@ibVlGm;$yV~^`C?hp*r9y403tao-j)Mdc-H?>VN&CIcz2htRiJ&p$Zxrw;}7y
zZ2@Gt;(wLarP85?3Qa8Lnaka-_K9@(cCXhs0w2x^1oO3BJ<tnxG?-rc5#Vx<V6^o^
zQ*X;?GC$Y2+V+K?-_^ow(^($6YLC@5dAC>$)VIx%rk2Kd$wI?Thz&~8nves9E#|Vc
zcK!ZxEQ~<>FJrO-KPlCLEfSVA+Nb8JS_wXr6n``h@%0?gd_4L|525SW^&Sng3i#{t
zB&Q`5RH{T-1Fn72L?_7vK1;7%5zMcT&7Dj0IR_QZf%zJ$vA{2x(eF1N&y0A!v;v!N
z--e+o4+R=-@D|PAFHBWETqn7wwqH`#&J_X)XU$U@2mqBUo#9x*bR@_uFCNw8h_x$d
zLVxs-OX}%!bQ}1wT;qhpVGyS@4WRifm2<FuWtSj@u0ULrdj}|yD$siS!Dm$Fe8%Zm
zwC^YjYYQr%vNkE8qMj+$ILp{UsFhDu8^e-UgILvwr*oey6S?_SxzC)PW<SMA(sFcj
zhh<-kkM8!@WIuU=1gDj82{m*?bdnac6n`DToGJjRYmfJpmo1u2D1-6I#lvnai9&3$
z9$Q4#<CBd=#`Nrvq&f*B&zTeSOy&e1kvTca0feQ4R3(ES{&%K(BSPiDyha5ARg9-b
zNn=f;b8EOsm&D03jBTgNIJex%`svz}y)IC|@V&{5cGDm0$L>;LiNn$f58>-nDSs34
zxDrcdXDR-f1h7nVO0=iBXwb`4kn}D{V9|Dgdtnwb_s_6hl`oWzq<c<h__W}W{%2{a
z0^hfOVc*JJ{Fa)9OJKhBGH8EVB3`h}DDi8gAby1u^lz$PK%`I|XW)iyRdT+)rc(-H
zl(h>7z>Zw-q1ae7dPUvt{0DG!^nW3kA_ai^NCZIOUZ+h*oj$~Y&hbFKqMm(QAN)9X
zpqIn3^QB?|!$suSLK7{ig371s&zJp$s$!}@kmD(el>lk&;JhH9rxQ4?Dd>Ieo))p3
zbF3uIEDKrAjAiI78L)D5iFK&mzH~lL(m`uIH8w6rSSl&<?BFAENX-4GD}Vp2x1p}0
z3R_f2DoU=Yy1*}WTJM0jnNUeB!#xP#uin1LsbAqF-@fwI7*mmIs8^^!rM@_u>N-J1
zTUX!deR;N6W-u>p7*)l2rkKCn4edWF6gd_&-2VByzg>TSGkv`I=K9^;o0~V+AOEEv
zy83Ychp6w}-SxN7Q6Gi~>VFah<5&D@G7k%4mlxKjA9pEsEg1dX)biaouU_AM|1oa+
z4o{K)7)f7R+*LP*MNb3I?idcj**L$_<_~j9gXk8<M3f|hQvolIj2YUT%6@6gL{b<q
z7vd?q6Gj-bB;$p}BCTu|jo^v3m*-eOh-nF{q;iWaKHbbPlayI*{Z>q`GTKuR=HL6$
zp&Jjn!+qGbhpO=fPi|xS&i|?#DksJN5krGS@TQ9U@3E^xUD1Z-dv(bec<-+E$2iY9
z>~$vdyjU~8>t7NoGYRe2cNhN$IiK_Qm+|ZY6Nh3Z0f%BH0*7KI1Gi!(1oadIG%zzY
zlaVJVf9+gta~ro2{?1>4kI8g=IJ^TLPiOoRJ8qpev79!kM;~bVEUT47m7*Ny-}l)C
z?ug?_GM&(orcEZd#Nige;@QOlSU^_JidHD^g?1jlR+yym8->#bzezYBgbGS{rSPkT
zcMiWs_=In*2o`L?iV(w0c_*R)TSQ(PBR-%`e{In~#A70T!s9fWh^WRpBOm~p3BnP(
zB@UDc^feNfPBWDtol@Y7L1@j{QE00vCz0S_POZ?Pg{a929c@AaJPGZ3Elf+i$svKB
z={5>uyq)RR3*%apRIM-`lIs>cJ~$+TFhQYqWdKQ_gc4RMe8Pjay#Q!dQ@aWYW6-YB
ze@KKl(;B?Kr9w&AU{MHY+6XwbZiP)C=!kI2p-n|#bJx6Z1`ue|0v2GcA(C^7N&z6}
z+nF{_xB%$20dxs(+63WSQXnLNl29|M@S3`BlJJ%UgOWVK6aWXyWhnvlwT;lEaWie9
z!xj)}NE@_+I9a=dv=_lEU<(LBKnc=!e}J6?B%|>nQW8*WbO-rp&><&zAb~bw3tY4f
zNRW+@iQt`nfH8hx4cd|Ac&Z^#0*$&PqJ_NLqeMVK4Mip$(@c9Kk|Eu|T$3RaK=+e{
zk!l!gN&riv3SdF7z=n|`oq_==7^eodltM{ZGE&rUbP648)l7p|!Lo>t?3ZBFe*xXs
zWVjlgRuF?ysM%24n#|ie0*&oEC^AAGKcvOTBL<L@mQ}#l+5P)7As;PImaBvF`Jw|3
zt#~2ixAXP7Tb%(Ne*Nmh`su-XzV3k9IOG0(`SQiL3O|dvQ1a0Oq5g#bX7b7MY%T8J
z7xIZt0>g@nJ%OE|XXOQ&P_6F2e<%Rfr-1-QLw*6s3S+VqK~HsG8I-I{7MNQ6;cu`1
z)h%+P&rVUD8a{oyS}qQ{wRnY|J$@qO%kINk9M13w{g*F)KJTc@N8JoioUOaF^#vf~
zW@hq5cd@)&Ejr3_IqRG5&GG!<@`HFqLb~J{Qc$$2iRlon%~z-b>^ieQe_bsv&jp+Z
zzdblRTcZ9~?BqzmEjjr6OdedmUi16&<FkLy<iq9aO}FCq)S>)ZK9i4LQUBUQk`TRq
z<+N`+tiz}#z@VH-4F)JiePfIQ*8>LTK**=dmrEfZi!aX6<3@!q38EsxWATc7Fys5f
zkN?DwY@(-8ml|?$XO|}@e}~ucM%9pe2+B7Ro^2OiuLFd1JMlW(HUas&@LH!D2h+Hb
zH?-V06GM|QT6U=y4x?#dvNi8-IebQAVKkQD8dPYn8b8%2K?URi+;seXhVc{aWc)<E
z*YOjwf@n_9ziOZ3$=U?Fz-+18##^$f&|vzqMnhV6<$!v7d~~_$f11Voe0{t;YfL?|
zew{Fwn;V+B5{&_#j~hk4ur-bM_BR%0Z=NQa-91gsTShKc2k8B7ydG*Z+U>+^TiqmO
zZf%s0roz!6ugCRh#9LYmv>zMFNYf%Y^e>hcxcv)xhII3Y2Nx9iu>3yym<LGH88q#8
z292SN{8)Z-2WSzVe}DHn!zyE&2zTnEZ7h1CY;269b*pcbHox&GR7o{h(!;Xbh8NlJ
z1yHRAhDrP1SQxB68`?vdkRTK$Rbv_lp|FW-ObEM3WA`TwwmiVV4bs?P8rllojx>97
zm+2E0W@)<6!EUs1D&C%3yWW*ycQbfAlJpuUhly{f0DfN&f13xO3-j;Ur~*4(G3|ei
zquaFY;b_0UM-NAlfjhWIpvc9pra0p5XKu{K790KBGR11T+}@LJHkdb0q-3(g3x#`h
z|AM-c+2=&6)nqA65uSaTnNoMs%+&4+#1U`5=);nof>}56_FFql?!mab;T^{@k5QPU
z_M5vI>o0X~e_BthE{~aAtxjwE5vxmg((1I@$?9$|ZdM1u#vA{7BCV#&&tV<YsZWQ!
zT8AD@eJn=dl?U?WYJPTcPBkrlh9VB+<L>?OqI>a_oT^x_F1tHsQ=c$l*1Uc2D@0yj
z-`a#ZGPzw`)y=afok)aT=E#rEjmA&x(Ad4&VF{kye>E><+#T~$H*1{EgS6X=%I$Pw
zviqHw%-x)rtlHg))Vw#u%Wf;KHHu1)Rya=MOTT@ib67Vlcd+(x>Z2a1S|WXhdCyMg
zJ-gp|&*sk4`6vID{?qB_^+tJ>6(T9rCPbrRW3XZM4weH0w<$CcqWb{(j6NI;o9$XY
z=%?HVe+vqTV9Nde#WQ-oc(-1kU;I(ZqvQ3v%h%0fc`BES`RR!~?N%qpXJ1|uH`zf#
z8ygn`BukBUb{Hs5VG^|d(<S`rr=K9+#p&^4v3%1tuTPdolF9oE%DDG-xw@A{|K&o{
zIE2X2H<m6eV5rf;nZWfa+=j@v=$<}djbr1^f8qSAc)fKHQtia+jBDs%eHUIE4R(RM
z)oZb1q{#D5yshDo@tr$T7`xuuDc^7izn6{0h6o|gkKUfIj$Vsb0|J``{UKHLDga50
zCs?Z!pZP&6-svWa5KQCg?nz^WiLf~42tGE6kFK?d$v2^J1W##?m3p5JIyG=(UV}3z
ze=1)%nWjYb)Hz;pOD&bPF`@08CI_fWy3Vn_<!AF&$_{yT8OzsNNQ$W7`ioqduc}Wg
z;%!MbW0=GArM<U}JtSRFdCfGZ>GINcY8MI%Yq`j$72BawCRgY7?QL=@=FPijOftQa
zmG9>;XVyH^7zw#dc^Lr2eW96yyQ<kHe=@Cv%&i4jhNFv8geSZ+>;{uGEJ-sbCUVr0
zEVW}TStV1S>+xE6*bZG2YFlE_Emc5gRPf3qMpP^)96SoOEFLO=cyPcZ0-1h_xhXbF
z&nB(y(8&qCd0^tJVL&o<6@o<Ru*j6OtMs$=?0@j1Mhofb0vo{_b>yLd0pke+fA1{R
zv!!|_x|03|iLZS0M+T2Gq_seo-W-`hP=tGg>XB<AB=T?;FcK^|`0`pqml6^i8JR(}
ziF6iQ<RmyvB_bvta$DRdOBdqkTX3nk91L+f(L@>IaFLypwFMC%#dXnFFKRtzx<SRV
zT{)ED3yF>9%MxV5WP#R`rDeBfe*=XyNPfenYhm`8&(mE=YB@kw*e~jcmIn>>*;*{K
z_;wHSJq-inF<{7H8+OV}lOuc0lx`OpU}+<1c$1e?F;Op#A~$U<IrL14qyA<Xlboh+
zyFR5f(_CLoo$V!vo;g&6J_&;eX~_n7%Fr|krIu_l5z2-}vg2~8rC#|&e=b|K{6j3!
z8!8@&F{dMx?+QGTI2hF2tWw!!Wf_=;mh`siZ%O6J!*BZJT#tF4KuQ|6imAt`Qaa}r
zEI8NGtyX@|dMM=vUixl%^0kgBYi08-qeLls$`rPdlh9{b6+=?@tl&FEnQ2Bj<5^Pz
zwSQ_rYglW_5N}|vz|P3le>BndfpuDHNRDykr<$B=Yzy78FcbZjG%o3aM?tg3)NSKC
zLV3WtmZ6q}MipCdjqZ(9wU*UkvisS<UegT4lxAhs3b>jo<*U(F<3H5}k1SQ(cn|s3
zlcg=)-+&L7qclz5G`9u#v^+aasrdc*-+tQv<JNzXB)^Y~&$w|7e~RZNo@JvVhiF^g
zxaQ3X{ryE=-{m=<IU=w1LUzu1-8XE1$|553sqA3eyocOm`Fcr!qNC*kbL5=7zr}Kr
z7u@v6A-oK7?0*e$)9p1i?1O1{WHs+?_^VTSuk2~^&s&q6&o$(<&!uvmX{haYqq_xT
z{2hf`K|RNHcmq$Xf2PoHH>!w`#nvkHaUfb#sT@0~qD345$~2d(zZxE2bu8-F&^k(0
zq9J~hu3InBvX=KZs;nAI%<cALcI^9d%56&Cdc+PXo(LF?qR}A`!6ApdSqj^IEB)Wb
zIitlmXGCi{Dqmroajns<>8Pbi4aL`2GzQ&kH{+1nDJ~<NfBPrnnQ57)Dmm!frnmQk
zYlUu2GtxEQ1@#K$(HM$)D|*XkBUj-yp^*bK8J$`OHO**DDd}ybhihnxZal`Wp;^mH
z>5WUdnP#zT74%PS>eJx%)Yz}9yW~_#V9H^9&mud1lA(xarjB>+#!^hna=OmX>B#$Q
z&70CN(9E&<e`bbM{_<;RsWGqN@(y;0L^+Q1@w-hN(M{ywRUd~i937+x13NkFbBUXy
zZHml~w$LptlY--@oo6;?phaI|AL&Xun#3a-%|y)`c*}g$u%g?fIhm=CVUXHw(BP1F
z<|sK>xFxQXoDTnH=Ly3K1p&$}DCFE^I1;td3YQyrfAe?is1?g4?1qcKWrT9NP;z;b
zXpyHsCmH%wXhwI6G1H83#<Qjc)S6bHZlLX-4Dkr)3hs<<O(|xkSgTw^hy%8TmPqpk
z;X)@iX6RbkAcqUF@Dx02RBKv|hN0{R*{bzCzKZ46xZX%rtKtBA4R}qd`}LF6GlKgX
zs+2Wle*}-vo*<t`lF}ULs^Gnb7DJ=%Z$PK@m~%}ZkQ|Pk;QctVSWZCl9*uWqHGAZf
zkxVyJwh3(4LvBuuPE>yVY0D1h7B#h@I?AH6i#DGbaV{@E=tRQxi!_eH5g*6z8LHGD
zfsv=?lLW3O=W*FmdyapX*f`hEXC(xz9-4Rke+G8b(LT<XXT|CI$L6!NDqYkvaEz3t
zH*geHxG{I;$Z9tEFd-|X`kFhC)0q}2u3De@0Tj1&f>;Bbp<;kXPNpw6fSQ4<;jHPX
z{;F(!Dw=7`;oz*uj9#>Z+2sCAvEA-xZ=4fpT3^h(N3z1RrnSk}<ttRDvgq1)YlOC*
zf0P6Ej7E)fO)~;hnzd8me(kY!H43g0g4C!~UhG^mNV9~~-qy6ndvcJuvEl8Sw|Tbd
zVRaRWE}=Z`E*7if^YwC-FQxo-eu^(&|Kl&u{_))(o`3UVc{)E+?Y)P~lQ&>EnIByU
zn>ioy9lCoqdT~$F-&xWzgi?n8!t!E4f0yWdN;COre*SfLeDtooQiJsEo=T|b*?N9*
zym)YSbkd1-CJ)x#>EFrq&*TrK5YRv!@8&DIq4I@%ARo!c@+<j7K9$eqU*+HAxAHsr
zLLSJ!%ekB%t>*7L`C2aIVtKMWlW$}vyZPdBji3CDYn5-0@ju?)E-zQ|NWPQDfAU10
z$}_o?%d<|N%kyq^ynG}7BmZ-`Tq8||R`Nn#bnm+}d2#$fuI2jOs_W$Xr=`4<@8yRt
zGcHe#(HC9*h<<eS>w3H&{P{1>|M}H`x4sGQKzPSQ|85B59V)z|9pO!{yWriX8}NQu
zA^r@Qf5Vs`$d^|mzF3}~&THJ?V7?teJpr2TTb^`p*EyAuz7G8f=JMw;>h@Dm|MB^c
z-#>iRqYm6IVCgTqqsx=|>KgD98+%LFUHM;!X*b}*g^j_ljJ>@E`B(#QR1N$SAV_Gf
z<mI@FzVG6H0cx8yESK@@0TYLlN(6_KN(G0LN(Q%+N(ZPs2q17_V{2h&WtTgL2ZR|o
zDIjZbVRUG7Wnmz8WpZ<AZ*CwqE;BALm*<BEG!Qp2H3~0GWo~D5Xdp8)FffymCn$ft
zTWxdGxEB7NU!jk1?-W^*C0R2&JJXi3l$N$j3x(a`gPXXmFG(C?2g?5XdyZr~@>`lh
zW@p&3t=H!~I<HEXM}`E18&0@n@C->9;ZqUDxPX_4FcE4Zf`Bj`;0q_rXaz4J;XIJ=
zqF}NJ;3XnlD>D)dK5&L$oCs|U^uvF`%)m}c!VUsjR6s%#Vpl|D5W-Zch_qvLKqM?g
z7<LK439KN)NRAkX9wj1TG?5yxaR4C=EY4sz#Q*@~nkcRWpp`_0OhXqVN^0l==t>Ld
zg8x($X_ScQAY>yZ;e|s#hrwDX27AMc<nRKUYlWmhw~hn|3wwc3*dj>8LP>vE$Vp_m
z0)e6srUGdsQb9OkI7Um@OTm~3WaJ#W47>;?h(XB(3yEO?Ooaxf6s%4R4g(Pkk6>Fy
zi~tFgCMJ}@2*fiIgq1K(!gvYe6f6WA8{7*H%tQ>BhH+5@JHa>u?Ls0^&><Mo!jNlx
ziP#7Z8~BlUxbT7}$Z&9opE!Rw1bK0+1a5@wQVfy9DFqtTMp&j{S9k*+7!n}tWUfIY
z;NTbwl_3HtWeP!Y*o;MhS>WcNN-zV2W}L&(2o8I25dl^Xd+^Y<!5$osQgA$J1#ks7
z_@>3^x8Fwe>c=7>^i?)5UMBf?nJ$WKIkMkp@eF$QFJE81Jo@kH+qZvlaerLI({#*&
zy?4poY8vCfX?&NH(9JkF$R5bwd!T-M9Mps1Nog5;9?|`LoXiWN42(RC7q64_?jAlP
zF`~FF_U$q3bUW<N@1_Z~K*ME`%svnmjOfR5Rwx)Oavv`*lY%^><7_sIX|l-EX*Q=R
zozoop7Brv6`8_S3J7|BeQdp2j5t#0~(eJ-+CHm3z`Ck_w8ltO>k_V;SJY+kPTj)W#
z<K;5@exGGurpawnO3=F}NO^I6{^|N0q<ojn;`w7|8wwN>Tn@920#wzLGBQmm%_b>>
z`fSahjQe!|ZW(_|=m9;XFX<6IipQ%Wp|9v4^ff)EZ|Es~OV5AkIlZ8N(s%TdUeWjT
z1HGm(jor*RFOp@Nf1x*YOvmG7l1`^FC=Du$Q=JJ-XyVpQ#_4jrn%z#52b#F~78gxs
z6V#?;?j8^0X*{F1^cMf6)c%99w^MqXt(NqT-mPGpWR?|pIP0&aUF@FT|5)57sH~~C
zVLC~ZWs;{k{U3k*LZ@^Fsyt8U3C(Ec4a=Yb8W(gCFO#`l-@duE7a(jlp^ND%r(fyU
zRgxDeNcwe^Aq_ZUNpqSfv(!<LC*J@_o<3CeLW}!llF;INMpty@?YpYstsFDo=y&=+
zf6#yEKglv{YM^+E2A-V$adv!GX`p#T0l`D>Vf2M45~6<sM!&3pX4tu`=96TZkF#ac
zlutfIzO$3p@6QiB3v(z2<bw$A3`|5erI0@>pXWxT+F)YNve2ZC!JM2iIa7+A(O5<C
ztmGCI{?1q9N?o%pRP(FVz@nvHwK6q%)=%O2>fre8$yMpEFMrH#vT6R9KZ97fXB387
zh|5}gWP^VL|2dx>2Ah4hW25p*Gr&p{@D8vpoo09GIG)Dy37w_$Ro*1SJcW$+uTHNo
zKQ+lvkC+xv5n}cVr07WPfC|aCpu!hY1W$@x@Ar>hU)kg&n`fs59QHvroeUWk$cG8H
z7MT1BvzD(RU9grd7;qRU|A1I)V|s1P38RxUrcZy?oF;UVK>%7(G$XX3v^Jdqv$3u_
zPZ7b3B4=yssa+G8&W|REPjbIkCzlr=&)OuO-%L{o9|K%QLCIxgT3o82sVjlU=N@Oe
zr7LC&P9a>^RL!0IO>v*(jo*B_x_I|TDej}`4&>T<n6hh^|9eIuO~V=6&$XbO|4g>y
zyW)QnFSn^On~zqDyp-l<8IKdIG4{=A48DFzin<xzUB|eU_tdIbCOKbM@zhIhY)Vt+
zGs`4~O?{v5l9XwZ=Ucgc<Yg#3c~VNUR{P-uL<CO@9H$?^U6v|gw$g~ojrba|S@j1s
zLWdhP;-KYG`n2M@tru}Iq#EmJ-h1}9kDh<`wo$%5VsKuQn`y5X+wqY<DLlS<d3bQ~
zaqR^*revmc0#WD4w~QQqCA&qna|j2HF5qoh*tnvmE@^H$hU}$gy?NPuHM;={)4L6E
zrcTfL15VFTJoFs{>j~gT^KmwT1%aRR_7<v$`8dhR-^^^Tld5XV)?S2bTW+Pc%DR6|
zi4c{ms+G(WvsCZW@epDB5~x@H+Ip<&I%Z2EOKO~MqQuq!kP)Y*)@ZD|v?^?s*_oBC
z-zpuiwB7nlXK<CB)vgdsw`=ro8fM=tbiwqAVZP5NMl{?$G15CXVsx3;PrMw&H|~X(
zqOa|(b|-kB<hc~W3@`N-uL8>o9j|}vN_8b%uyx^GRn?t(8-_*w<uKu4=vTn-t)U8r
zhbc=@yov3vRX=Z~h$5`+j|gnlxLAR>?sS1D<`e+wwKq(7wMSE^90EGW3p!eCw_D(H
zdm<V&0P6EPCnhqeiUMLnuP)ebi!kWbad0?Ry9qGY&|o5k)nB3m`U;XddRBi47esXG
zM5GzsM^>5v?}mQg4vms@AN(FYf|yB<0lx@9_o14o)R{y9y&w^<6q-a4>hqR|X4;<W
zbJzKU*InHd_7fYy-5$hwf<1)3zCJm={?jYV%i5t4GYF4dGEHBl%e+8m4NW6@8do0z
z64&c=Qrv^0DwlTDknJsgZ&ca@Z2!%F$?0E5H84H|Om=|jAz+ZN?*Q1R(@*aY4l7^~
z_?qQ)8=r3D(}9PNVJ%SM(`py^He6-4u$i!pjTxUiEL>~u*e<XQUvjmfsWvntJ!tq*
zA(L_!$cC?{+Q_2KmLQpTpk^1)2J8DKGW=n!g-j@4)wqvrC!{@AG`9hE4^=mRY(aTW
zB-{nS;WD=kt#hjAI6Uq=h11baxEm_BTF6+?K^6`o+ll8LtP0x5cn6sra=m&d$NAXL
zaBbgfHdEKow~p^s^63B{`LV3+N;(9FK0f@Y;h9~)d-QI&Z518e^JACs@pZz33Vy=V
zJ#t;!hQ~J=Z6ha%c7g9#LTl)MQzw0BqGKA-zZ$<<35oGStJwv#UvR?O53P}}Z@hy{
z{hK~m`JOKFDbu?E_6s53&)|dyOm`U5!M_@{27$3%0Q-fYH3&>>1MDKcOY#vt%vN~$
zIfCz{y=!6R?2~i?by{SV07H&@^3Xj+P(CB~3~m4CpV@-BM3^vD?%`^GHpuDSH+SYm
zxSO_V4>`04=gh6a%e92t6aUu3J)_6g#)78=9Fzc^G21_I>P|ji71MN%^X-w5(!TJ-
zNR`F9m32KaEv5;$3)i_%s@kQLshV}MOuiA_yfAe$gKB1#P_<^BB@YFOM0aLY!NE+?
zn2CR?<!#D5C9EJgk*Y#}+ljQtTkG>`{VE~oU0?b*wd~@o!Xd098|zda-!7wiBvdu4
ziuKO4dn(;Cvu0H`S(SbXUv28xsIC(F*^o8caueIkN7kfX`qWn+<z}q4SxtS|qTW}h
zut)H)COecHW(p6bWIfB&%!h1v8Q}}ti>5vXp?jBcGkcC+)O3q~Cf&?e8qpwFGzex5
zg2UGGHNo5rFVD4yQuL@cui55u!!kbGqK9o>v&~uWGIl2KA(+<$GrdVGeY%?_z<m=C
zauaE+J`=Xl1emuO>v4IkCV!J(@wsO`+^-eAe-Ssa!8ZO71+n1S%WS-NS;WiYIdK^(
zd3IbRvlr~S{R`uNbpyu+7cid1i$yY@qz^ClpA#3Gy|x2rb5Zu$ZF;v_CNIYE0)Jk>
zHJKyfGmxCl(xQc+JK=L1Z)*ggVr6V>cM0e!!+*Og1X<kg_T<?Df+Qj{jqd;^SA4h@
zB*bM`KKL%2dUyxA>p&h^V=n;8o$6IBh_B30$`*+&+HX;R&=NLgX{4965!Sobqxyj%
zlgyVG`QyrK08~tHuK_@@(1)q8!CwO*xv0~DR3jP!6v15OFJ|ySOXjMdtm4(fi_j{T
ziz4kFlu8ACJt&@HeLX0rGQFSyQ)h4oeRBYkq<i;4wlweSLE5zF>p@Z~>+*Y~HP|xC
zZS|nWiH=@>bWnC?bp*?kG4}rlM{`-?D;sft)oelTgJu(w9yXhh?WoxV%geBh*WcV5
z*#)_}sh75-lngi8krLI@4)`j&YqSGM5q8=w=`!lHA7HzVIuf*ywWn+n<p3c^o+u4;
zxSEKDI$>rwI1?le)leshErY&JklY?P-yoxf+&iy-SJ37ln5tCY;+<i=t@RGB;t{38
z6{Ud)mm%2y^}#)z^AJ4P6rBbQq}-(pM50tVQ95<OA5rEl1mL9rTx|llaV4n6VS?a2
zf1Gp}L)D($ja<dJE<URo(90z3iHR!N!|`vkNkZS}$+}=XhfHAKVjxkSt^6O{7AgA*
zWo~4bw37#N0yiL&ktZmBC6r5SO;H$y_kZs>_qJNvYQ6fRw^~}QXSMo5t1qo8svdn%
zgo#KbL`+0tLJXKl$C7^{F%)4!Vj@A(gv6i;rba}FnrP~N%jC=Y*WPEJ{aAa45W-?2
z1RntV!C)3~urTu|pqdlGGJ8=55}*@r4=M>Fum^89Dh4Sqg4c<EN`oA52(JT`3zmSx
zc<rb>kPlAawV{@RWnc=g6;%KV!7035s3Nc&Oyjknia`lDhu4f+0amiq9K4;BtH5f!
zLcAu*HJ}u)2yX{v87Rjq!`n_-0V?ro@U~H|1?%uy@wQS{fec<3-WJMgupX})Z!={L
zsKwid*GRbmYy@?GK;!90nnA0D{I@zSO|r#8C{U?&Y+)2FdMBzFtOBJ#>(I#cU=wJt
zQ2Hkuf$|}Zq8TtXR}R`NbS$VrM<#EVg$>u`>1cN|sJ6Wabc0^dWuYZs{j@fAJnjcX
zFYdE&samZAw3Y*{d<YDKBVf?Nm3!)U5FDVNcI_xQ22O&1Q42Rds^4+C)PhRD$;4w|
zf@P`8xP`laq$cU2Ae{zhz*)RHi`w_n#kmGfcHJyIESASz@Q8jS!np>{HE_c3xik<d
z&$saOL3VdP{LJF(tiC1VPR5<YdY*;HpVUCmow+zC=!z|2_0?vLFM`?l{Vc9MQ)dmY
zbe5Q{n3t!2L#_hVU@gdi^+4k(rwT9;^$N4voBEa%I}vqG!82x0M%AFi)|$P4ppt+%
z!F1x|8_ix_P(wZcs5kp@O{FqKY`wwkU9UW@fp0bYR;7{vJ6F=Tn|=SkIZc*Wcqzr5
zb{++9wxs>vcJ98DI_ITvo+T$z-fqd<ZR*0a<RsC538D8fD;^miLh+2aGNjEOM(HRB
zmydu$K(CYziV*rJAaFiL1Fw%0JwFak07B^FKrx#HQ{WUJTt02dqUW0A8B5+;CUw@5
z-*tceoJB)d1H%VP-<b^-P5e@67M<^rN?0`iSt@DK;%}+Q;?c`evBlG`rBW7O{415V
zcy2^LD#udU<)Lyd^=3|LiKRQgNacY|paJO7(krE_+XH%mwzD7T*6s&`K)b7r)t(*%
jBbL5BmtD+ECj0~AL%2(qhnEK)3pX)1HVP#rMNdWwvw|6)

diff --git a/src/Makefile b/src/Makefile
index 5626ef6..d90147d 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -1,10 +1,11 @@
-SRC=archi.ml ast.ml builtins.ml config.ml cfg_constprop.ml cfg_dead_assign.ml		\
-cfg.ml cfg_print.ml cfg_gen.ml cfg_nop_elim.ml cfg_run.ml elang.ml							\
-elang_print.ml elang_gen.ml elang_run.ml e_regexp.ml generated_parser.ml 				\
-lexer_generator.ml linear_dse.ml linear_liveness.ml linear.ml linear_print.ml 	\
-linear_gen.ml	linear_run.ml ltl.ml ltl_print.ml ltl_gen.ml ltl_run.ml				 		\
-ltl_debug.ml main.ml options.ml parser.ml prog.ml regalloc.ml report.ml 				\
-riscv.ml rtl.ml rtl_print.ml rtl_gen.ml rtl_run.ml symbols.ml utils.ml
+SRC=archi.ml ast.ml builtins.ml config.ml cfg_constprop.ml cfg_dead_assign.ml	\
+cfg.ml cfg_print.ml cfg_gen.ml cfg_liveness.ml cfg_loops.ml cfg_nop_elim.ml		\
+cfg_run.ml elang.ml elang_print.ml elang_gen.ml elang_run.ml e_regexp.ml			\
+generated_parser.ml lexer_generator.ml linear_dse.ml linear_liveness.ml				\
+linear.ml linear_print.ml linear_gen.ml linear_run.ml ltl.ml ltl_print.ml			\
+ltl_gen.ml ltl_run.ml ltl_debug.ml main.ml options.ml parser.ml prog.ml				\
+regalloc.ml report.ml riscv.ml rtl.ml rtl_print.ml rtl_gen.ml rtl_run.ml			\
+symbols.ml utils.ml
 
 TG = main.native
 
diff --git a/src/cfg.ml b/src/cfg.ml
index f03588b..a174394 100644
--- a/src/cfg.ml
+++ b/src/cfg.ml
@@ -26,6 +26,29 @@ type cfg_fun = {
 type cprog = cfg_fun prog
 
 
+(* [succs cfg n] gives the successors of a node [n] in a CFG [cfg]. *)
+let succs cfg n =
+  match Hashtbl.find_option cfg n with
+  | None -> []
+  | Some (Cprint (_, s))
+  | Some (Cassign (_, _, s)) -> [s]
+  | Some (Creturn _) -> []
+  | Some (Ccmp (_, s1, s2)) -> [s1;s2]
+  | Some (Cnop s) -> [s]
+
+
+(* [preds n] gives the list of predecessors of a node [n]. *)
+let preds cfgfunbody n =
+  Hashtbl.fold (fun m m' acc ->
+      match m' with
+      | Cassign (_, _, s)
+      | Cprint (_, s)
+      | Cnop s -> if s = n then Set.add m acc else acc
+      | Creturn _ -> acc
+      | Ccmp (_, s1, s2) -> if s1 = n || s2 = n then Set.add m acc else acc
+    ) cfgfunbody Set.empty
+
+
 let size_binop b e1 e2 =
   1 + e1 + e2
 
@@ -49,3 +72,22 @@ let rec size_instr (i: cfg_node) : int =
 
 let size_fun f =
   Hashtbl.fold (fun k v acc -> acc + size_instr v) f 0
+
+let fixpoint
+    (transfer: (int, cfg_node) Hashtbl.t -> (int, 'a) Hashtbl.t -> int -> 'a)
+    (init: (int, cfg_node) Hashtbl.t -> int -> cfg_node -> 'a)
+    (cfg: (int, cfg_node) Hashtbl.t) :
+  (int, 'a) Hashtbl.t =
+  let res = Hashtbl.map (fun k v -> init cfg k v) cfg in
+  let iter res =
+    Hashtbl.fold (fun n oldstate changed ->
+        let newstate = transfer cfg res n in
+        Hashtbl.replace res n newstate;
+        changed || not (Set.equal newstate oldstate)
+      ) res false in
+  let rec fix () =
+    if iter res
+    then fix ()
+    else () in
+  fix ();
+  res
diff --git a/src/cfg_dead_assign.ml b/src/cfg_dead_assign.ml
index 2d81284..c94352c 100644
--- a/src/cfg_dead_assign.ml
+++ b/src/cfg_dead_assign.ml
@@ -2,54 +2,8 @@ open Batteries
 open Cfg
 open Prog
 open Utils
-
-(* Liveness analysis *)
-
-(* [vars_in_expr e] returns the set of variables appearing in [e]. *)
-let rec vars_in_expr (e: expr) =
-   Set.empty
-
-(* [live_cfg_node node live_after] gives the set of variables live before the
-   node [node], given the set [live_after] of variables live after this node. *)
-let live_cfg_node (node: cfg_node) (live_after: string Set.t) =
-   live_after
-
-(* [succs cfg n] gives the successors of a node [n] in a CFG [cfg]. *)
-let succs cfg n =
-  match Hashtbl.find_option cfg n with
-  | None -> []
-  | Some (Cprint (_, s))
-  | Some (Cfg.Cassign (_, _, s)) -> [s]
-  | Some (Cfg.Creturn _) -> []
-  | Some (Cfg.Ccmp (_, s1, s2)) -> [s1;s2]
-  | Some (Cnop s) -> [s]
-
-(* Computes the set of live variables after a node [n] in a CFG [cfg].
-   [lives] is a mapping from CFG node identifier to the set of variables that
-   are live before this node.
-*)
-let live_after_node cfg n (lives: (int, string Set.t) Hashtbl.t) : string Set.t =
-   Set.empty
-
-(* [live_cfg_nodes cfg lives] makes one iteration of the fixpoint computation.
-
-   This returns a boolean that is true if some progress has been made in this
-   iteration (the set of variables live at at least one node has changed), false
-   otherwise. *)
-let live_cfg_nodes cfg (lives : (int, string Set.t) Hashtbl.t) =
-   false
-
-(* [live_cfg_fun f] computes the set of live variables at each point by
-   iterating [live_cfg_nodes] as long as progress is made. *)
-let live_cfg_fun ({ cfgfunargs; cfgfunbody; cfgentry }: cfg_fun) =
-  let lives : (int, string Set.t) Hashtbl.t = Hashtbl.create 17 in
-  let rec aux () =
-    if live_cfg_nodes cfgfunbody lives
-    then aux ()
-    else () in
-  aux ();
-  lives
-
+open Cfg_liveness
+    
 (* Dead Assign Elimination *)
 
 (* [dead_assign_elimination_fun f] performs DAE on function [f]. *)
diff --git a/src/cfg_liveness.ml b/src/cfg_liveness.ml
new file mode 100644
index 0000000..63f3a65
--- /dev/null
+++ b/src/cfg_liveness.ml
@@ -0,0 +1,50 @@
+open Batteries
+open Cfg
+open Prog
+open Utils
+
+(* Liveness analysis *)
+
+(* [vars_in_expr e] returns the set of variables appearing in [e]. *)
+let rec vars_in_expr (e: expr) =
+   Set.empty
+
+(* [live_cfg_node node live_after] gives the set of variables live before the
+   node [node], given the set [live_after] of variables live after this node. *)
+let live_cfg_node (node: cfg_node) (live_after: string Set.t) =
+   live_after
+
+(* Computes the set of live variables after a node [n] in a CFG [cfg].
+   [lives] is a mapping from CFG node identifier to the set of variables that
+   are live before this node.
+*)
+let live_after_node cfg n (lives: (int, string Set.t) Hashtbl.t) : string Set.t =
+   Set.empty
+
+(* [live_cfg_nodes cfg lives] makes one iteration of the fixpoint computation.
+
+   This returns a boolean that is true if some progress has been made in this
+   iteration (the set of variables live at at least one node has changed), false
+   otherwise. *)
+let live_cfg_nodes cfg (lives : (int, string Set.t) Hashtbl.t) =
+   false
+
+(* [live_cfg_fun f] computes the set of live variables at each point by
+   iterating [live_cfg_nodes] as long as progress is made. *)
+let live_cfg_fun ({ cfgfunargs; cfgfunbody; cfgentry }: cfg_fun) =
+  let lives : (int, string Set.t) Hashtbl.t = Hashtbl.create 17 in
+  let rec aux () =
+    if live_cfg_nodes cfgfunbody lives
+    then aux ()
+    else () in
+  aux ();
+  lives
+
+let live_cfg_fun ({ cfgfunargs; cfgfunbody; cfgentry }: cfg_fun) =
+  fixpoint (fun cfg lives n ->
+      match Hashtbl.find_option cfg n with
+      | Some cn -> live_cfg_node cn (live_after_node cfg n lives)
+      | None -> failwith "Unknown node"
+    )
+    (fun cfg n cn -> Set.empty)
+    cfgfunbody
diff --git a/src/cfg_loops.ml b/src/cfg_loops.ml
new file mode 100644
index 0000000..9175654
--- /dev/null
+++ b/src/cfg_loops.ml
@@ -0,0 +1,11 @@
+open Batteries
+open Elang
+open Cfg_gen
+open Cfg_print
+open Cfg_liveness
+open Cfg
+open Utils
+open Prog
+
+
+let optimize_loop_cfg cfg = cfg
diff --git a/src/cfg_run.ml b/src/cfg_run.ml
index 137e622..e09ccf9 100644
--- a/src/cfg_run.ml
+++ b/src/cfg_run.ml
@@ -7,7 +7,8 @@ open Cfg
 open Utils
 open Builtins
 
-let rec eval_cfgexpr st : expr -> int res = function
+let rec eval_cfgexpr st (e: expr) : int res =
+  match e with
   | Ebinop(b, e1, e2) ->
     eval_cfgexpr st e1 >>= fun v1 ->
     eval_cfgexpr st e2 >>= fun v2 ->
diff --git a/src/e_regexp.ml b/src/e_regexp.ml
index 53ad472..1872417 100644
--- a/src/e_regexp.ml
+++ b/src/e_regexp.ml
@@ -108,7 +108,11 @@ let list_regexp =
     (Cat (char_regexp '\'',
           Cat (char_range (List.filter (fun c -> c <> '\'' && c <> '\\') alphabet),
                char_regexp '\'')),
-     fun s -> Some (SYM_CHARACTER (String.get s 1)));
+     fun s ->
+       match String.get s 1 with
+       | a -> Some (SYM_CHARACTER a)
+       | exception Invalid_argument _ -> Some (SYM_CHARACTER '\x00')
+    );
     (Cat (char_regexp '\'', Cat (char_regexp '\\',
           Cat (char_range (char_list_of_string "\\tn0"),
                char_regexp '\''))),
@@ -118,6 +122,7 @@ let list_regexp =
          | 't' -> Some (SYM_CHARACTER '\t')
          | '0' -> Some (SYM_CHARACTER '\x00')
          | _ -> None
+         | exception _ -> Some (SYM_CHARACTER '\x00')
     );
     (Cat (char_regexp '"',
           Cat (Star (
diff --git a/src/main.ml b/src/main.ml
index a86df17..1314160 100644
--- a/src/main.ml
+++ b/src/main.ml
@@ -36,6 +36,8 @@ open Report
 open Options
 open Lexer_generator
 
+open Cfg_loops
+
 let tokenize file =
   Lexer_generator.tokenize_file file >>= fun tokens ->
   OK (List.map (fun tok -> (tok, None)) tokens)
@@ -49,6 +51,7 @@ let speclist =
     ("-e-run", Arg.Set e_run, "Run Elang program.");
     ("-cfg-dump", Arg.String (fun s -> cfg_dump := Some s), "Output CFG file.");
     ("-cfg-run", Arg.Set cfg_run, "Run CFG program.");
+    ("-cfg-run-after-loop", Arg.Set cfg_run_after_loop, "Run CFG program after loop optimization.");
     ("-cfg-run-after-cp", Arg.Set cfg_run_after_cp, "Run CFG program after constant propagation.");
     ("-cfg-run-after-dae", Arg.Set cfg_run_after_dae, "Run CFG program after dead assign elimination.");
     ("-cfg-run-after-ne", Arg.Set cfg_run_after_ne, "Run CFG program after nop elimination.");
@@ -67,6 +70,7 @@ let speclist =
     ("-all-run", Arg.Unit (fun () ->
          e_run := true;
          cfg_run := true;
+         cfg_run_after_loop := true;
          cfg_run_after_cp := true;
          cfg_run_after_dae := true;
          cfg_run_after_ne := true;
@@ -289,27 +293,37 @@ let _ =
             run "Elang" !e_run eval_eprog ep;
 
             cfg_prog_of_eprog ep >>! fun cfg ->
+            record_compile_result ~data:([(`Assoc (List.map (fun (fname,Prog.Gfun cfgfun) -> (fname, `Int (Cfg.size_fun cfgfun.cfgfunbody))) cfg))]) "CFG";
+
             dump !cfg_dump dump_cfg_prog cfg (call_dot "cfg" "CFG");
             run "CFG" !cfg_run eval_cfgprog cfg;
 
-            let cfg = constant_propagation cfg in
-            record_compile_result "ConstProp";
+            let cfg = optimize_loop_cfg cfg in
+            record_compile_result ~data:([(`Assoc (List.map (fun (fname,Prog.Gfun cfgfun) -> (fname, `Int (Cfg.size_fun cfgfun.cfgfunbody))) cfg))]) "CFG loops";
             dump (!cfg_dump >*> fun s -> s ^ "0") dump_cfg_prog cfg
+              (call_dot "cfg-after-loop" "CFG after loop optim");
+            run "CFG after loop optim" !cfg_run_after_loop eval_cfgprog cfg;
+
+
+            let cfg = constant_propagation cfg in
+            record_compile_result ~data:([(`Assoc (List.map (fun (fname,Prog.Gfun cfgfun) -> (fname, `Int (Cfg.size_fun cfgfun.cfgfunbody))) cfg))]) "Constprop";
+            dump (!cfg_dump >*> fun s -> s ^ "1") dump_cfg_prog cfg
               (call_dot "cfg-after-cstprop" "CFG after Constant Propagation");
             run "CFG after constant_propagation" !cfg_run_after_cp eval_cfgprog cfg;
 
             let cfg = dead_assign_elimination cfg in
-            record_compile_result "DeadAssign";
-            dump (!cfg_dump >*> fun s -> s ^ "1") dump_cfg_prog cfg
+            record_compile_result ~data:([(`Assoc (List.map (fun (fname,Prog.Gfun cfgfun) -> (fname, `Int (Cfg.size_fun cfgfun.cfgfunbody))) cfg))]) "DeadAssign";
+            dump (!cfg_dump >*> fun s -> s ^ "2") dump_cfg_prog cfg
               (call_dot "cfg-after-dae" "CFG after DAE");
             run "CFG after dead_assign_elimination" !cfg_run_after_dae eval_cfgprog cfg;
 
             let cfg = nop_elimination cfg in
-            record_compile_result "NopElim";
-            dump (!cfg_dump >*> fun s -> s ^ "2") dump_cfg_prog cfg
+            record_compile_result ~data:([(`Assoc (List.map (fun (fname,Prog.Gfun cfgfun) -> (fname, `Int (Cfg.size_fun cfgfun.cfgfunbody))) cfg))]) "NopElim";
+            dump (!cfg_dump >*> fun s -> s ^ "3") dump_cfg_prog cfg
               (call_dot "cfg-after-nop" "CFG after NOP elim");
             run "CFG after nop_elimination" !cfg_run_after_ne eval_cfgprog cfg;
 
+
             let rtl = rtl_of_cfg cfg in
             dump !rtl_dump dump_rtl_prog rtl
               (fun file () -> add_to_report "rtl" "RTL" (Code (file_contents file)));
diff --git a/src/options.ml b/src/options.ml
index 39fd3f8..63572f6 100644
--- a/src/options.ml
+++ b/src/options.ml
@@ -7,6 +7,7 @@ let e_dump : string option ref = ref None
 let e_run = ref false
 let cfg_dump : string option ref = ref None
 let cfg_run = ref false
+let cfg_run_after_loop = ref false
 let cfg_run_after_cp = ref false
 let cfg_run_after_dae = ref false
 let cfg_run_after_ne = ref false
diff --git a/src/utils.ml b/src/utils.ml
index 3fa505c..3b1b122 100644
--- a/src/utils.ml
+++ b/src/utils.ml
@@ -276,4 +276,13 @@ let string_of_int_list l =
 let string_of_int_set s =
   string_of_int_list (Set.to_list s)
 
+let string_of_string_set v =
+  String.concat ", " (Set.to_list v)
 
+let string_of_int_int_set v =
+  String.concat ", " (List.map (fun (x,y) -> Printf.sprintf "(%d,%d)" x y) (Set.to_list v))
+
+let string_of_int_option v =
+  match v with
+  | None -> "undef"
+  | Some x -> string_of_int x
diff --git a/tests/basic/loop.e b/tests/basic/loop.e
new file mode 100644
index 0000000..24652c9
--- /dev/null
+++ b/tests/basic/loop.e
@@ -0,0 +1,15 @@
+main(){
+  i = 10;
+  a = 2;
+  res = 0;
+  while(i > 0){
+    x = a + a;
+    if(a > 4){
+      res = res + x;
+    } else {
+      res = res - x;
+    }
+    i = i - 1;
+  }
+  return res;
+}
diff --git a/tests/basic/loop.e.expect_14_12_3_8_12 b/tests/basic/loop.e.expect_14_12_3_8_12
new file mode 100644
index 0000000..919b014
--- /dev/null
+++ b/tests/basic/loop.e.expect_14_12_3_8_12
@@ -0,0 +1 @@
+{"output": "", "error": null, "retval": -40}
\ No newline at end of file
diff --git a/tests/basic/loop.e.expect_1_2_3 b/tests/basic/loop.e.expect_1_2_3
new file mode 100644
index 0000000..919b014
--- /dev/null
+++ b/tests/basic/loop.e.expect_1_2_3
@@ -0,0 +1 @@
+{"output": "", "error": null, "retval": -40}
\ No newline at end of file
diff --git a/tests/basic/loop2.e b/tests/basic/loop2.e
new file mode 100644
index 0000000..985a305
--- /dev/null
+++ b/tests/basic/loop2.e
@@ -0,0 +1,12 @@
+main(){
+  i = 20;
+  while(i > 0){
+    if(i < 5){
+      a = 5;
+    } else {
+      a = 6;
+    }
+    i = i - 1;
+  }
+  return i;
+}
diff --git a/tests/basic/loop2.e.expect_14_12_3_8_12 b/tests/basic/loop2.e.expect_14_12_3_8_12
new file mode 100644
index 0000000..42f3b7b
--- /dev/null
+++ b/tests/basic/loop2.e.expect_14_12_3_8_12
@@ -0,0 +1 @@
+{"output": "", "error": null, "retval": 0}
\ No newline at end of file
diff --git a/tests/basic/loop2.e.expect_1_2_3 b/tests/basic/loop2.e.expect_1_2_3
new file mode 100644
index 0000000..42f3b7b
--- /dev/null
+++ b/tests/basic/loop2.e.expect_1_2_3
@@ -0,0 +1 @@
+{"output": "", "error": null, "retval": 0}
\ No newline at end of file
diff --git a/tests/basic/loop3.e b/tests/basic/loop3.e
new file mode 100644
index 0000000..a99573b
--- /dev/null
+++ b/tests/basic/loop3.e
@@ -0,0 +1,14 @@
+main(){
+  i = 20;
+  c = 8;
+  a = 5;
+  b = 0;
+  while(i > 0){
+    if(i < 5){
+      a = 4 + c;
+    }
+    b = b + a;
+    i = i - 1;
+  }
+  return b;
+}
diff --git a/tests/basic/loop3.e.expect_14_12_3_8_12 b/tests/basic/loop3.e.expect_14_12_3_8_12
new file mode 100644
index 0000000..feb4775
--- /dev/null
+++ b/tests/basic/loop3.e.expect_14_12_3_8_12
@@ -0,0 +1 @@
+{"output": "", "error": null, "retval": 128}
\ No newline at end of file
diff --git a/tests/basic/loop3.e.expect_1_2_3 b/tests/basic/loop3.e.expect_1_2_3
new file mode 100644
index 0000000..feb4775
--- /dev/null
+++ b/tests/basic/loop3.e.expect_1_2_3
@@ -0,0 +1 @@
+{"output": "", "error": null, "retval": 128}
\ No newline at end of file
diff --git a/tests/basic/loop4.e b/tests/basic/loop4.e
new file mode 100644
index 0000000..53bd91a
--- /dev/null
+++ b/tests/basic/loop4.e
@@ -0,0 +1,20 @@
+main(){
+  i = 10;
+  a = 2;
+  res = 0;
+  while(i > 0){
+    x = a + a;
+    y = 1 + x;
+    if(i > 4){
+      res = res + x;
+    } else {
+      if (i < 2){
+        res = res - y;
+      } else {
+        res = res + x - y;
+      }
+    }
+    i = i - 1;
+  }
+  return res;
+}
diff --git a/tests/basic/loop4.e.expect_14_12_3_8_12 b/tests/basic/loop4.e.expect_14_12_3_8_12
new file mode 100644
index 0000000..4c5f671
--- /dev/null
+++ b/tests/basic/loop4.e.expect_14_12_3_8_12
@@ -0,0 +1 @@
+{"output": "", "error": null, "retval": 16}
\ No newline at end of file
diff --git a/tests/basic/loop4.e.expect_1_2_3 b/tests/basic/loop4.e.expect_1_2_3
new file mode 100644
index 0000000..4c5f671
--- /dev/null
+++ b/tests/basic/loop4.e.expect_1_2_3
@@ -0,0 +1 @@
+{"output": "", "error": null, "retval": 16}
\ No newline at end of file
diff --git a/tests/test.py b/tests/test.py
index 4a70644..3ec9d0f 100755
--- a/tests/test.py
+++ b/tests/test.py
@@ -21,6 +21,7 @@ parser.add_argument("-p", "--passes",
                     nargs='+',
                     default=["e-run",
                              "cfg-run",
+                             "cfg-run-after-loop",
                              "cfg-run-after-cp",
                              "cfg-run-after-dae",
                              "cfg-run-after-ne",
-- 
GitLab