From 3a11914eba99fc3892d84da5994ec8493e357826 Mon Sep 17 00:00:00 2001 From: pedrommaiaa Date: Fri, 18 Jun 2021 17:04:20 -0400 Subject: [PATCH] operators --- flow | Bin 84424 -> 87112 bytes grammar.txt | 31 ++++--- src/cg.c | 126 +++++++++++++++++++++++---- src/expr.c | 153 ++++++++++++++++++++++++++------- src/gen.c | 44 ++++++++-- src/include/decl.h | 11 ++- src/include/defs.h | 39 ++++++--- src/scan.c | 60 ++++++++++--- src/stmt.c | 10 +-- tests/input22.flow | 26 ++++++ tests/input23.flow | 28 ++++++ tests/input24.flow | 16 ++++ tests/results/out.input22.flow | 12 +++ tests/results/out.input23.flow | 9 ++ tests/results/out.input24.flow | 5 ++ 15 files changed, 474 insertions(+), 96 deletions(-) create mode 100644 tests/input22.flow create mode 100644 tests/input23.flow create mode 100644 tests/input24.flow create mode 100644 tests/results/out.input22.flow create mode 100644 tests/results/out.input23.flow create mode 100644 tests/results/out.input24.flow diff --git a/flow b/flow index 1c1371b66a74cd3680a76b3c1151659999334c8e..cf59b4126f88e6f863c6792a9ae9e53a9a20a2ef 100755 GIT binary patch literal 87112 zcmeFa31AdO_CMY|lbX!rn#?32Hw;H0D1>l?#?}9iZ`C%x$(xEb-|q&)O-;&tLXebud2GIXOgh)cisK}-ESIts_I?! z>Q&XNqpLd`bLY-7sj8w~W@V~EsY4C{$&rY>IewZPWr7l^p|)8VqK-tA1O9Pd1I?}wTU%9Cj5B7Uioo^~Qe zG`#%krAS1Z2uAYhN>9By<<+uRR!=Pe>xtE^k z#{uq8l9ZjdAc9Nlmko#y;*h|fWk?eJz94!9?X`rO=Xj-TZIxRoudOSqQ5xL!rJg#a zyrRrqqAXutR$pIJyS%!#q}W|mOW4v{4@m1gz?PR(*EWKrQ2^T7dZ02vd^&saVtW2_zl8}RisozH9rwkRTW9S?^X%(Bvsjn?_NQ!X#QKPpMA12S4jV? z!7q_;>rTO_!L{^?Ao!sbg03M1YhE*Z z=UPR{yKJA^#<(+V9iTto?jFO^*Fod$FFTf$doP znR=QW{IT|FdYT;jvG&n=njHGE_JLX&rTgp}D&0(lmk;Tpp!B?;bZ$^OJ1CtMlpYzB zP76w>2BqVI(vd-F7L@+JB~bsbjOo#z0ZeG*Jd5woV3kv79u(Rf&s#_vInoB`; z=@>=v#k~fW<6DqiN9~}6)l)FB%N>WNaW8PxG;F>@_5qi`ddkx>1bsfI&zerb@E`J; zI`f|V{It9$yUcm&b9t}+;EsiW%cKCS?@&3nv&K*D=aTGf@G72Di}D(?SAtT>YdYeN z$ZO6nN5Z@K2cOSdipqM9#eq&;23|dX;%{FABt?qAhsGS;%;tTeD2-i7?(z89IH|EK z(LESH8#5cb;@zQ*T?y{+jv@PVPf)|{7=;M6*p8uyP*d$lMTFXDM{F}QLsHXoDCWB` zmN$A1lxxZU{By*^Mk-1(`zxZ2T@H`EIrl`ihe<`QNE30X=rc{Z zN1Jnxg6^K7T&qQda6?>POI8lFePTFRyr1TwAQ=!iZ7&s92tz~&n?gK$P*`2q3JCLl z1EwwT0_o>0)60M&WTFV(Wdn%X+g#-3Lb<3{A12vcy-z;_|4P3^_80-ag+Q+(A3q7> zseW@i8`r~y^J&_2FyeD!L#a|87IJ~cY@AEa~9{27b1~wSl zHFgd4lsD%dhbir7O3<#WnVEnU4(pd z#|U%?a>^Zp5g~8fk%WkqA`WVT)IY||M$tP@r?zWo`2OsyJUc7TE|g~%%CloUJBzVL zQg*yYQg*yYQg*yY>e+QrTe`HT?DCq{dz(Cmn~Dyh61>ehA*gI&_EvZjRB2sv?qO8p zH6pbVxXHPPJvO3lKZr63;$4HOnRf}=U-HBWRO;m16C1*KCA8noX-`bf?b?uvX6FSd z?_FqnNkDlonW`x5SLg!sMSii3>klcOD4DB;a_uMs%ue-oDB4pfvhPF_fv&Se{*i)r zf=KN^3I)LSJ2a%GqHaiNo_9j(fb7xK;3ANH2lW)MY&HG{Mzum_f>lAObW{_S{Q)bg zF0Z65uc<9h-Iu4f<=gtp7c!YmF{Iu7i%JUc};IoZ~3%~ z3gThl>4L9B^=i5qcxvLG2pqieU1rwh$Ls5FDV0f%xS*PpSkoCAXxt=8Kf`nk&WRWkG)Zj6_$I&I= zle2*(pBxIb=99}w)Sj>5V*RByM5Tv<8|%60e|x!T`ZOvahxd5WgXlcmMP2!r@3dq^ zA`din?iajP%FAChWMNt89{bksAQ47JSJ{D`6=boNvOpndzd$QQ7uvk{i?4zOlPhoX zc)c0q5ps3IJ_}B&zYUv7UZeUwan3b7Pmq-tq;SL}OQoee)+Wa_wY}GP$D~yUg~@t59?8=>%Hub$O=rD!dWG z^P0(%uu6)yWW^cvzV*1z2MGgDB4L_e!cZaM@JvI=S3-i;xSo~vn%_v7QaA6V$e(T2 zwR(-BEm^l1Wkw0D2AxE!yZjQi2npFn2`_!g%Qe`3**N&TUiB#ROPMXCSdCIHhm`g& zsRB-JT~2QtrwL_FX5{y|#dtM6Nzs<9y+#S&AM0-9_DjizCo%GsewnL< zOpj6K?;sQ9I+>AY`6ZkxBsh!`Due_W`8Bl0UX85yr5xGB%l7_sgLMW%O8Zs__yywN63~AHE{VQeY`jH?>)N7vo{K3!PlIC-GrO0FshOTRf63lIrSzFCWu{p%+!2H zm=qRVBgZySCfr;%QsuN{B^z^i{R^H0Mu9(LE&`zeE?Lh@jL%wL+qq2YN`X3D?$7H~ zk=J86hN`LHd37PL5}sF}``7adlsQJvD^Q0de_l^e(Oa^X8}s_^bFEz8eDkBr_1t>h zR_6(sNk*A>Kql&{fKV7Gnc^QOO`!Ac=XnOI-{2RSAVhv}n!zN6Ld}4h%<;1vp+dG~ z{mIBOP~-wDrt*^gC@UVlm`Wxlk~GuOYVr*Z=dEL%$ZN4NuRndJS@AwhE_!VpfknQg zm%J+dc}0r6zME<=MZTU_?vKwawwJt4TtwyN<+_E;*^T?VD?L3oa4j4^B2%@K<08X4%A9x|`!FzbIZ`Em>}(s5wGZfH|}U z!2t~Ee3fxDpso`95+5Tov}DaPO8mQ*l=Jqyx@z^??NY&;Y~+26^9EMI@7CzHm@in4 zO)}WxD$YXNqL+(#Q9x1jz8omCh|A;)rEgIhtm{yUyNzPU3Qc+z*41<2_LC^NKpLac zx(ExT*D+f01=0&La&0_EncQJmAi2+Nw<1XcdXJ06YHsW9wYuj5-6#`@q$TV7i3X#1 z{)V~g2gtBj!7;rEzQ`~55E-c@>mj4y6cUW3L+^qgmZlAEpC5a4jjs@bJx0M#e}aC1 zZR_6b02XcXciS&8=3g+Dbm;EtuqUCcr7ct|-#{9QJiJfhfrqBfWzZd^Vlhw$0t4!o z+I_Fn&re|((qO;$DzTT;E9G9l32&w-OgI67wq5Yf5$YekEI2Rr^A-!ZBXiTQVJ_iv;*C$jfXKuq}(Ot=6#+QL7LKo{?n=b zTo3y0n>Jz)fF&&(s0~H%HgpNmug|156gV-lH;{_dIgbZ8$ZzTi&L=^wZm#ONMpX~~ zl^Q@G%VEyK`+1``G(eh-=fb7U7t;D0rCrs7vTNJIIy7qAx(5=Asj@|BmqnUNd;R+Y|J^*6BS)`qw}1iC);hX&#;y1ysTJP}BQu zM)xYX`g}5V_bPC6I5%1%*{>z*J!46WkUKm=u&F=vbNv;jYMw`XeIFPZQ^4q5gDFJN zPN!HKiV1{&+fi->%2i{J4*q(|hsKN$`)2Y@6uI_39+4wNcKa?QHUFh8AnvcDg7X4S zpjyQg&ZwvRFYwdbdf@wwpHC5diAKID;Oi&}&TOck=|wV8OV(H85NIAPl$d(=-Mhh} z`R+Hs=Y4o2m8Ta^f0d-(@7<04$iOB=4%#~gGnO9qJ~!2pL8vA4;#voi=E7nYQHXM5 zA*LVVO`=LH%iERz$ouL$m=*axI&A15ti*2_A%MBCF>%iu>K?r zPQQz9!qfrf{rptkHhVG~dPC#-<7n5ya)?RG9mm5)V9dJZ0^RD~)jeBoABS_x0=?U)Y^O*jl5o!ygFC9p{!? z4U~7!DM6NNX4gOne-w5ZA^~p1MbEpuulab>=TEWln4FGiSiO&NARbQSdYhvqDjJUm zn_fYq@(#iU06&5n9fhgf|f)mmA2nEq}NkmWKNjx54(|C~fE$p_`Ar)3dC|V%Pc*u`UuaJ@DBBG(vmVMdTbF+={r}s#)HXyhG&hB zk3zEuG0{{f?vIG$`SVoYAv{X+?!WKrVgd51}9>?rK_ zCSkL%{Ryy26yWo^nqC3s66`&--=<*-=*$a_FQoIrTQNOtZ_;qQ!Uka6YrjATS@Dpa zP7tKZOnKMW*!vUvY|x4t&XHWytLYd`936^Eb@%U>OnGu>LAqx5a4e(Sql_E{A#f*z zCaq)P3fjLAlXGvgI0N+fNcfk-=xw|Rq9oLsn)5<5w%4(@*iL6!n&VoZ$FHp9*8mne zwrV2%np9!mx_z?-=SKK~ta-i;f)U&)vJBD9&{K+?&;_#Dlv{3B`*fWgo!07}h@Xvl zja?=(LWsLx2Odgx@%0f(_atTM5R8w*1`1&J5R6?VS>%l;0lYw!Zh4{37Z zZ^qYQBcc5XjWVE?)`GbG)*eyI2!-K(2*>whb^-C5{^_$p( zKp2Wn8G1LsxgwVitJf`J5a)6q!>`Sa(^n_L+@Ih#(tQZO5$<;bz{57IVwU3A}f_nJ)eGU;CJhzs|+mkvsF zEZl3QVD8=s3Uc>`Q80CHBn7|NOWOqps=zwt791U+M3#)JY-Va)O}4)fm3b63g0`Gj~KN5Vj!nA zxNXDBVng5pP@t{)s{>}^a|fAI$3*X4V%Q-IdE!7zdurt1)VAkH$*zvf03dqlmC>|k zaOwK4AJFGFJdQ_;^QlnRy5xi?FgFy7HYl2k^pjLGA->V8;&hWI3e3Zac>$O^2J49R z2`D7Z>ab|$`W%8jc;wjW(;&#y1bUB;(wd{LB;;yzBGEV6psET zZ%pqbsLadu*)OX{bHPEr<@U{$hzXlbM+V5{ub4OxM)$th?(oFCN+PEudVq+Mi0DZ_QHdn_>{U_x8;GbM5w-e>rc0s&oXB&*UK(FIHpqO2 zN$l?h_ME)~2)jaJqb2rgfz8>QO4#WV+l78f)~^xRw7v0!9kQh(WlKlmmX3Z~I%2kT zL~rSc+|m)YMSo<@U3NeNmra2^Pz-q(TImSh50LHMi0pV?P3+ge_29PQPcM;NF2vmw z$Eo4G{j3a8y7+7-<Qg_3c45(^%s-J&PqN0jz&R22LTKE6`Hv$cYU67pRjMZqIr8c|Y! z(9Vf#dv`7?A#asjbSmR03g=BjUv0mJSkCLtLW2sQz9IK1TJALNv@ex%a84I&B6k}h zW{@aXcTqHUwGRanqNZx1q6jFbZ>aYfx+ogr+Pm=My@JDvyiL>jgnPf@BIpyCSJFCV zGp+AXlqpn{CUo=mrv$)^DV%qcZkU09w%>^#Vf%LcKwra-H|_c3 zEON7g{r)KW=)LNuz0u+eV`%JtElG*j4C>*w03w44jLc!XXGG7nwn$ zB%Mm`F;Al)JVDqh9%tYX_)+`SXMq!j1S66c8)d#LW+pwA0T#+cQ=*(z7$>iZ{r*w1 z9s4Z>7}@7}*S&}_nyT5w32-R6Cu?Au&wS^ArzPtzs8-$N&EOU$zYj5B-z98I_M24q z*AS?Q#V-Y@nMG58EXR8-T9)^4f~QCyA^TRN>`}l9*+qy=#XUbg3X+V367uB*Ncr`J8Wm zZYODh!lps=6Um5szl1mRZpM&HOD)A45BHEq;}5z8t#~aP_{n&RMr?3#Xb$>+k(ZYT zN9f7(dLM`XATICO5agvj1*Gt9$mb8Eqj#lv;!uK*5%>OpKJJ|=@SQjsj2pcHc}?T; z@|zCiHNA?X^ysnBh(=@YcDT8KazsP_N_5yKQVBhl^nV6FLjSYjDUmniikD-A{`@@| zp?@b{bU>z^0s8-dJc!GCBT3s%P6YZ(-8wbh+BlD{T>@o~5BvmbmkI6K20@+vg#IOl zM(mpO*apOX0uTgSn+qb zWUuyKf%%koIh-wTyHrB=P%0HQE!EvmizfTu3QO@YZx*=3%VOCG@QxY1Ox6VvogE|o zK?mT~?Gu&J+00aI<2H7s*)OAE${R;=(FB8(ZOK0N0Mz^qDgv(?;bDf)okq`edu$x{ zpQSYpcMKZDUU0&Z{AB;R&PlqS+{+nS6yq_a+B4-$|mpKM2zckIOYkhg|G)pz^g2C0zA3 zv|Vaggb6S-JbL!idm!thV;IueUPS3t!!YlY=m71bRM?08mIKoPT!QYSw z81A&jG^E$YR9?u~c~02fCNE{~pO^HX4kV?OU7C%!VPB z?E`S*z-E?&1O{o0lgbk@`0+N%cDbefa?bbnKXL*L^paquBOX#E)VTod0$p?25KuaW1SMFyItJ zYi+Cm^KOd=u?>MD&AyGJh>ByUr6F> zN&HPciw_cl#faj4OSU|IZ~;Q1NXRK9r0_=x8A?L7YC>)!)myTkN2l~2!9y{x-5|tY zJ;SjO^^T``h^Q2*4b20)NMMc>*l{+bT}0AuBx&S4b&Keg9Zu4`H12hmHjtzpL%Slj z4x9JE@B9+{O_AQw$9ncr?+TGYTQjpD)27@5jq48#a!2EL7`({(1HjGfyA`wxPtXrLEsfij36cGlW82|#`i>c-uRLTD0mX@1M?+8Tk|43 zmZO5_q8gg^quObu(AI74-SnaNLTX7UNi)0n9)C?l@S4Ex$bsP=2eJCg)z&dX$j*W6 ziMfy3uU>_=CqPjE(I_cW10=y_dM!Ih2tIs}7x>|W9PC%%J@cn<(wh`%jkPbUM9$bYfc5tHz}^RHEI3sqkR|oY-@r_mxnF&Zc=swNE8T3C|lO zfLRS-#iEu9uYS zKv~&f2+D&Ka{=Ie;9=T?@nRFkJ2|)QVl+Kw=J+QchI`WwtJ<+}_I?Ul%88y*)1LHD zZxNRc8-Vg_luH^Nqya->KFG?SvyhIPFYs5Nie{E#V}|VF!E1E(Y29( z6q!Np`Lj>*NMhipH{vi`^u7$~?O)TlK_$#d?|Ee+zB0lOjZuFB;-CW zgk3CiqKTY#X8JJ@drOGuYC&|iBnmeW?I5D5L{uS&#`HjRIT0li(R4u+DT&}n_3Ty? z(eVdClq!h4r;E~~Y3W1@i0IEm)J5Z5GkdxRqOnBudm^HT8X(%<15qpyT}DLr3ZivA z5PgN&v3CU#H3_1^9*ABbqRB*5Du_n)Ky)7w^&_IwI1#FiydE54Tt>~#FL>%$Fe-@WlWR$m@|@5CvD)CeI1jY5)0NFx`*<`X{X z{JcU1%p#(51<`OxWHnUZ5hsYEiD;rA3h6=8^F-9~ClJN{Bb{@JUFiI9E-(16z^ogx zoP_)t`JdE!ieHFF2w7niGLVE^r3<0j7=((OO{A~^X8L;T97~#y27SjeP^3!=qX7mG zg`Ftq2$F0AzL{M02xG2y?EwwV#<8Es7d78v55l_^2I)`(A4Br<=}jK&;GA|F|K13H zB0m;!?-@9p-Vp;Kofr==xm-ZGe+q?-67UckV6pVQ4KC97=%Xd;6v7Pw3;&czATFA4 zX@pzdjqhuy`@~Sfo!JfdKH-KDE~^{vDZ&jVTw)MTKCy3(oIvJkX8aX?F$!)2lV0iP zV-yy<_ctP@eVIys;7^vy`f3IjaXSyhF7`D3fs18ENyBtW^Lmif7)b+-_-41wI6 z5^{za<$Uxo$Wqb}z$#L6@512)4@`uFOlojtcD`@E_6meyJM zO>a#r%5VB=TH&;&6GeF~BbNfaaPIK$VFs)Bi`^LDp8VeI9x(bn`F*pwO~>XoeLl14 zZ_|9SALTVZt>#Vq!1F16AMc!H)0R$KHtpPL%bzayXGvy#8d+0FGW}oD;~M?{?uWjE zOjmw&by-DmwTr&`Ji_I!Jr7@x#zQ@2eys~%aCVoiE~{}jxTe`hkM#H+*D{HG86eX>G0`7^pM`zN{Xo9RH z5dDnK1T8%{~cYboZ)f1YRgd~@onk`C6_*J?Q++ztE#Dhm0acZWo0^A zv1Pc+*1CDQWYm^H3RTBXX0ok@zVx~%wo+uXELsfg6BxU`gH z%2b1g7eLc|wTG)ElQOpvut4!zs8e!&E!m~Cii}An5(I=D!PCVxM%lIXhK$w*q`*kF zMLuaI)ezKBN%uf^Lc0;g%Ou)CLosyoHw(Y&S~Z9~iJfxvSG#6DBQUVC@Xhzt4fxD^ z`f#-J(qeZp+OyuY6*OajSFS_BGLc6HzTjRVV&{8`ODR@Vb6!pDni}4xNsed&BmrG@ zl1t;J(xdSBnmjDPf2%24K|lB&JVndM9Vn#Tw1tJWbwW@{?drPXdN_od(&Zo`E%7mW zX*e=1p-bi>H&7SkoR6Pe;IFC07?7#0eS@y zg}6vRt(Wsc3q6Hz)LOh=1+xBmcIVsD(;9~RA=Lc>A;$EK;+kP@bSC2&OHcws2wo>GMhXin1CQJRO?V*6Gy=2$E&>#cq7@ z|IOEZzI$=vj6%Biw)uQ7;l35O74V+!L%6+_iO}#uz_r>9Aq0Vz;ZTrj&+OqS7ougrktplkfh2f8Y6z&v$!}9=U*> z57@WR(T4aR5YCYLu9M;8GW@Y+cp3EXK~_EPp+WimSQ-BcT>|nY{$U6UW&B@}_s{aa zkMfrw-wuT15f(KRSCmb{IOIBKWZ^RSopQA4Fua*sR6~CegyvlImrX!GL}AJr1%JXM zqrreKsV~EP)y2VrhX1`1>N7mTdlU5{(OsxZ;nLc)n7Y>2u67l>_{3Io;#w!mui;~j zyNYWAXG-Q$^vFNHEAS$fikoN)aBs)`9Ma(kNzZ`h;Ws=Dpv9(CYJw8{9P*xG~L{wmg59GJ<83?g(16)w^AM7K4S>wB@sk z=Fce1KVv@cG#J)r&Lrr zbWVLbkLS-XoSR?hqFEahnVCDk&{dC>nao50sF!N<2#TFeV2UirEi78VW2D@SX>;fL zm0KXAGjkW@&f+qOgQqC65Y)LmTdfn6dREs3Oh#bi_wcl^77yYm48GsQi-X_d9)PFy zGjUhpz6Q5OHx0OQ+|9UmtK5cOzWCgum`}8O~)F9nF!}R2!4c1_JSW_+C$(+SdVZwLgypkN4NlC zC&E|poG%(X^97HAA7S0&;77O??hZ%5dM@XLMRM_BSC__09vH6Eg3 zNu<2-H24vIhOiFdfoH&v@a$*7kMQCbz>jb%!cK&@BaFr~h6fO4B76;D0X=hg5&Q^~ z5pF@~LAV>?)d<@VzKpOFAstSO#+ikXm%)#)9$^8UVR!}n2p7`a8(|Z|-3W6q_iaPi zfUpzc-3TMFt=olpWG2FWmBHV^>A`U+6 zLD-0}4dIIjk0Ny8Xowa2ms=1PAfyWqOZcT;xIj_YMytsYq1G+fj3zkFswkIi$9jY) zW`;t7g1?!mDC2P7+3NEhLa0PV&x%TzZ4X~#y+k=JY0@cUhYTVx@h`=_;%3;40P-TZ z8}}l>+cY3T%Ij*}e@A}5B6x08^yQ`*krq=6G=lB`-Hp3;htKy6LLHymXf{2-Nw^G> zY2WGdJ#C~hJ*>;<1pJS{-w}Y{E(8EZdeGB}Ecl*NjWjF$d5i;|eAH+ozS55`1pZ9m zYmInQIVT|bZs2#G1b+kYUjRQ0pjtl{5ODK4Ieqdh_ChQ zcO3Z3fHxcEo4(cgW3i=L3Ew)=$Y1B@9|!!Uz^^vqO{F@2A@HvNzc>J2pyS=Zhr&l^ z8u1l=`8NO`4?McOzx>nv_&vazfG;-UO^bB-Zva07_}=nA4*bQy;}oS|zG<$`AB(Z( zKH%TPnBlkoOCdx+_NOl!m;WB?_W=HUoxc$HZNOIt;7fG88~DQ~!QTLU=3Tw>?*aZ| z;NK09|Eezk4dBOPEb1-) zjr@Y0+xG_G?f3SM-vj)3;6E_(o8Hj#e*^e0fwvpmx7niipX0!P{0E=!#Q^@NbpBY3 z^)0)7zIg%onL2(P@DBsOGeG{0y8J@mCt-}wG4ikB?7Vz#;FkcuF@XO9o&N^lAHtkq zqmkcqfu8>!;1e)Ma0T$k>-=vJ9&?7?`qy#b(@%nr#av|q@cRPte^AeV9PkH$$B71i z|Cr}5Um@_X06#B4znQvzZs5Pe9H!35ZxRlG`qvG>)7<740sI*{{~q91V$L%u06$vC zzXANkm;)sm03U7SKizNNJ-}}Op7PS=FZAQz0RBSYGmQ8$ zKmIuIR|1bSpnm=Zetay(+eYA*81bevIRW>7z&{2&y#}P`Ki|(^2>c%4ry22U{dhO< zZvy{{5pQ}{mwyB0zYlAg0Q?FazX$l2fUgO_ivp5oK_~w8*+{Ei}2=H#;=U^?8XvAY4YYx|| zndj3Ax+z$zTosVdrMjIS1^#y6`Bs+J4$k-M`9ARbfX_DayZ!hRz<&UIZ+a6QGdhj(UYfbr43D=l&qg*W^xl!p?vzbwums|3pCNzeg9+guQHDOv*=Cr8v=~1rf zQ3=zdqNhh$`QL+n19B!n4h>IzSDyv?EYN3xJ`40&pw9w*7U;7;p9T6X&}V^vWPyEn z1%R$gWJpVCy0j2WCvovjDuq6`!mmZkMab8bh%UNWr1@SGqS$)jSCR}@NIYL70;b`= z`awKC*-3jWxU{v*0U4nsDP3(6k0m|7d@{t+mS411ql@pwi75Y-Y|5e?0!T}7x+cg1 z(sL@huvNw{zSo7=BAJl}PnQu*?@TEeTP*z2^6xLx8r^sD@es1(pdVzqOBT%M$8*k3 znLZ%#f0t>^u2TF@7F5c52^L7-w4f_Th6OTQA;UTuULwOSGTbS{-7?%K!!{Wnl3}L| zMJ_-7*ShoMv{bFw_UFbXgB$OYaUNPBu!m*nmEmVHJSM|$WOzb`recL(RvAXh&?&9xp$uLTW4jHO`Ry{^dn%X~bn!{)Z^LtQLI1hz!t^IId%A@D z-@*`rexGzKStmVq;5GEZdMN}*236rPx1qxKb&%@aAcuSh@+PvqHZN%S>1B?GpuJrTBD7QSB0EuuR!8Tn~BP^IFjtL#YPWd zL(Yk>2WFdXG?6V$T#v*~+XW8kAPYh>uQQ- zKq-rLEux(EdW|+liK6d|TAHGE0A%5n9o0o5uHuj=>Oq!f5vLD?h9*Vi02J{N$mtA% zT?wUnwpeM75&90IQ6)r{oJ82@(2&ysw?ee5!-Ka%ys<;MeTPp%Obj z2MKcwLfqmwNHQEBqwKsLDmKUEpbT?#pd8^2`V?z~gB}e>I<5gtlw&yJcE=Q8qaCvV zaX503uhVfaWX3p7Lp;{u23MS;6_9?8-yk0ECLVmiV z8SvqX_3!XGR_n0n!62~lM0#irP>Ss~uv>@oM2KRd&z4wEF_FPE^JQ4lA<1zYh*d`d z@FvGDsAA^ln?f8{0>T{U0c&y4^T1F?ER1M%Oa_z9aS)VY4tkCo?%0EPgo8eU66pvB zO_YN=irtX}Y_#Jk@H!lcfIA&CkbR7U{-QvvV>RM&4kv#5Ip}Trcn3Z8NpL&@If)Jr zAW4oTh$lN9goG3awXRf07-aT$e2vl$aJ-JV%kgK>40IIWcaS3-@WBr1BtsnZ&EGUf z8aLdpAYqtZ@JW`{;B?S;nG^>d2~i!Rz+!R?1;FfR$8U%u4G`v_zt&)J&~bxM2QgU{ zXNdK5^RE$&;RepL<$ydEFJ4&lc{Jt|cy;S+9#^dQfH2dV6RjYxIJ`Y$ofb;;ijBS) zX`Rj!A-30vWd=`JZS$b9b!H54M8~Zr!MQwF6e;k0}Q~ z*123at%?gRV1nc7HO~Bh0QwlS2!GM7T%v+Mbx>-&lVx#?-PAwDz$9xUcQ9ze%uwAl&JHGDJu12z#^y&(J&!L`pilc zJ$|*>Q+=cjeI?1};5o%VM;18W@(E4ZaNQvSMQtqucLIHCQmqf8xM^!;0@aY(zzb;F zS_&guATDt{v{du0L^N26d0H3q4xmY#FMnVTpr);Jh1A(n>WYL8;-Br%GFgK%s&ix} zOB2Y#>KupQU8KaPlMZQ?IOheRBvHp>Ga>*738QL+Ar%0=mhM z7&z%e@tRl7u%yDN{GS{+S5m?Mg@N;0@c&Z-=T~6(=LSyV&<9RR=mRGu*FFVTzT!`8E*}^7LwNAG_yAxLREEPE(l9R4yeVK@ycxb;oouB~ zvF`83M+k+VpyopbLB%LGIho?7t&0+#D0=%C}xPlr+s38-4AveV1sv8mQs`KTcr05us`ob`u}Et)x9r$ z5BI0@zC$4G-{yS}LwI!1s^oQY%~S^3CF4kg_oespjNaGrF8Prm+>bn#ARGvPzl3`p zI??Z>^_e;(hPKAweVu%TF@!H^;C-F6MpK6j%i-7pCtpJh86%Q&owQCM5OUoyQy;+HQm%P0#;%tCy=C)ge zZ;l|J++v{mj;O+-)^n;AI|WtDw*(EB&`UJvr38(T(47*>^Zf|yJYTC4OAi;-6gA?{ zfZ5D0jf^s;Z8J{Bl-S>qurt)CuQ}O1NfvuMfvYvJBGrydB%ym$mIEnE#^47Re{%_; z+Il(U_NyOF6mdC#U>VS_ehek$$XFTA2g*Hann0H-ap5F!mykGEPVf1o z8!5a&FF`zCIBhW4gx+^oYlXxu8A7RjB7npbV2>Y&hYTQ*TENV(daXK4D#fi{tBw-M z()cV?F3`Ua=@m-i3#3B1YFQzrOS3`xDagBDH6b;9l|)9=#i}K<8}%YdU938V>}n-0 znWz^E?W5_j7cLieG3ioUe-93!{X#W42O!=^p#4I1s7O|F?H8&UB3Y^=E+Ko&R4rTS zAr-ETB7n3mng2{xTSdmdO4-j;Q^l;OAohA<&Q{qFz&|d>le_)i)k#xaNPqpY$Tf?!P zp9=mTq>ZXm@mUZgrTM}BG_ill*^?yui-H^MbV`WWzl_cS4E-mSy3?2OBDE-H94Y^m z-knlrQ~DDwEPR-d!e3rRRBgRY3j0LsPN}q0@rm3quk6oT>L-JQ>{2C#{+x^Y0T-4r zR0#V(1Q7P76!wAM_)<>5VW@9&`oE<@7EhX)HbKl|tisr&;`IlyVkKhRI4pnL}9 zzMHep@5WxIvF{GZeYZdN7-GMJv%3e0+}{-es`3vS`yB!7clg;GhRQg8*^RwgW4|_l{aQc!Rh0YX zoc%+W$bEsX{O^gK`qbr;Vd(&Lw=4ZUY8@4Q0q3T_8bjBcn2yk;wtlT~FVI{d?@|lo z(6ESP75ZhJO`6Q&vi8XHc11!IWX+7iqg;C9R-L5{mi_sNJ*$5Xh_KQnY2u&-8i?Y` zCfcc%bEKrjx}@_ViI-`r?Ajo{g^DrO@@tkz|n365kY10dW0drA`8rwEHMOyG2_+Pt>`UVUQi7kZ+P}?WX~twRZ41 zEAlvfYwff8wdiR~5Nja+LmGT$T&TA=`#L;>_DdS1ZVau5k6X(a!I!QfbnbHjtA3~V3 zxaRR$f`JaC(WSN)Vth=l0X~Le^w5&e_Ro?tgu;Ym&YhM6YSY$&)R#%Mvt_v|Q$OQL zxd_o7Q}&-vJd^maedRdHM^Ua70dl-k<~S)u=9v0D37M?R3@7f%+N@3KpGoOxF72MN zLd<)*w6CSK=tNE0*CfrMSw59Zb4Y2G%79@cO+1d&26{QOfNqI2;|q(*fq0ua^A?$l z@&z&pQ9goTIaRn2LTIWGe8hTCRNqvg@8s}*&B@_W>KS-w<`{z|J-XCYX!JP!X{A(% z<4Haf_25Om=>Zj%Rh^N3l8i!DJ^tnC#>Slby7y z73t&$lb!rvvXdW7cJhPC&RojM$qyzwPeVM`$qyzw`N3o-KbY*~2a}!rV6u}ROm^~v z$xePS**OnfsZM?{*?9=@0Zx7}*~t$kJNdz6XD8r;odaOIAG(hC``ghC``ghC``ghC``ghC``ghC``gk*QQFe)wiS${fQN zU-D3DSX62@U=dV?^E9Nkg&$^5T>=>2!VeRNQe*#s2BiMkaTDM+^C9V)Emq1Q?ghfV z%W`1SeEPw~Kb?e7ZS4R@KR56(#ETIwzC=;q3(Wx%n}e~p5$}6pB3Z2@9HaDW7QWO5 z$#~p!sjcy7f+Xj)6d?z@mNygauldMiohs@dDy1@*U}-z(_8uWwH?RiY{vvWKrIu{PdSm-Y!l*SJF?@>1p4d=m+ZbNvDwf#Kc zS0|+RokN1P`d$|LKYGx2lBJ5K3IDtEuG-`LLd#VoJ@&|T>K^1Te3d58(q3|!7Qj6d=X4VyVcqlK@~-qpZ5LZdyG3LpkZ zn>kvemG5ux1J>qrNy`V#Es(7Zn$Gh{WK`-#%Fmpmk&#Uv)W|S=I^QEQd+P0+%%$aF zc)J6Soh5T@5&6zkmIIdRnfSrQzY2&@Z7o1?<7RORz8-?7kDJDmNrb{$updUC{-HUb z#yA@Ppp>u{X}bEY!fO_i6C1G>D-B}_lSx8c&DUsMW?U6xfTwpxBB%^sXh>~UjA8vlz>Ejm;$NT<@(wGV ziMnPsA9s~|M1WC}pb7Mzta@h{#Z6mRh&NPzCzF*JmigPN>dNI)Yd-|2Y*krM$aknYvP#6Ir`@bO8$Ld&f&s%p0J%L zawSJz!tFd6t7%?F$ypLxkWj;uaRR$YkkKD1RHL{6ZBB7O7a&x%OXfuhpA)fNV@|k?C;Lmy73DcBJVTVlk@{?92_`Ny zTM7OoMiJJpeY2Im*~-uSQFGsHrSHoVeP5pF`|`v;`{fC~HA@E~`9XN65)bfOIz^n#HE+FpV-lYRWvgL?HEqpF zqK|~A*{VaN^OES3`s!2-Uy$S!X{W$1O5$g`PZLLu&08Pcn8cqO%Ew#~u3KdCFMgxX4cC z*gap6^1pt7D7IrTzZrl-1Q%`wypy`c9`d^n4r z_nVFN_CNLMj@@AR=RVy*9Qvm_D4~D4gA(%79rW!L+9x4>v`=?XT;C_5H|T!4eUhgj z`lsF}(a-yBf~vv$B6Ap+`JfLmguof0l6cbm)#Qwe@<$5-@a) ziKCclYhGd&lBG%fu-Vvnk*rK! zEwdXAX1WTHMGBspOpMM!3J>v> z6X<22A+k)>iF_kyh&-ZSnaD@pAtQwGRwUBL-qbXy+)`!0eI$JVmwvmHE)OU|`UXw< z0Qo+Pls-VtbSj0o0qHqViasvpx`V`7xj1dWy^1u(g^zWSqE;ztsZi7^MJ*DF+9HLb z1qt-UI5kWr^Ah=tAzUVNM84ttgab|XQqVvm!USt2{#-0<6{2K1^hv;9p%zU7g1N^|oGd>&8x1IAZZRhAC?gsejpKin*^=}w)^(PZwKzQ&g_a6clL1l=5 ztK&$+h)bWRGCrAzu|&WpPq#FmE8KIQ2;iodfjbuG;-d2-Dv( zyF2DMVG=DF-7(J-Cf4HYhUxb?VZtriI5b_?EfxnC!{wBsI{rIOCeK-{0E3J%#9}n4>0zPY$0Lo*#p4mLW=b_*789m&+(t!psgRW*`(0Rp?NK0&9$F zjtUPK+$sRJNQ1Bm;0W_e#}lU*V5eZR5}~U3F+?9Z5OPL=E^3^C@w7xDvJXU|qC?cF z;gqL84@WvkQ^4blSB-hc81qKUL(=LmSDZ0Pn)TyZqt@dy)YB3*6AVivyW}MNYI-8+ zmta)Olz{!FK;rzE0P-YeC{`T_Q5SwC7Ecl2Cn*~)RmUTgpPG1N+9f}3q@20FUvOv4g`>L9LH+2~}! z)$w1}#x?tr!E`4|7L1huMqZTwek%dg&4!wtbnqf6pJoS)$g*$)h zEB#MW!2<$w)HMEYt76PcoZ37mM)NY7Q_&6OcPhNUX~vL!L31iPd3vS z^UtUrzcGUu;jV_19T`yv=r4n4J$}pUaF)PtH%%Q5^MMdIQrGp)mZm2I&MtK_QM^#s? z992cl4?(BnV^%2?sO}w+zmg1WR!bdU0EQZ z0wwfJl+v=2>J02vDoTU9w6v@|qmur-Am>69555}Q^_~*<@>%(Fa{<7Hs6Pgds#*Xs zfooXTu)M6kzPhTxE!ZHc0WmyODlK*wivR_N2(y;6h$W0Y%K!>XV`?^YjbRbrFiSaO=dh^9IKfgDYRZUVY}X?!%sP%S z(~uZuzJ;la*|5u5)X_$szJ4(aJBL}WXVxkf>S6sJXXDBhQ;2F=gkRHk?EaZTLM*eH zmBKk}7~$M3nSyc_x|oGO&Q$AS<{HZ)%wZ2R*2tn3Q||VqEaGhzUd|GUbT%7DfprnH zT8~)QvZ!4|6K1ZP%|gwNMNA!JGNWOP32apRfIisp6;vuxKYoU6B;;ZG(;HL}R-pJ&z=DQ3Ne*&A7?^)Vu~ z&Sef!3ScZ%EJh@3tC)4WXk)Wk0>RJ@=RmD&7F}VzfQ79>K}{w!m_MPZm=*fU<}L?V?#NM zDrag18<@i)9-%6Y9tEFT&YW{tly!%wx*}0$v#WXiEM`N-u&5)<0xC9#MO#q`po}?< znHv`)dW6NE#?(fZdK$AGVP;br@TOA|Sbq>4F%2W?BW%bt7H%EH%$re*P1kiaEBl5SZ~bX>SGlT34|DN{8^Ou^$N7B+-5 zOCH0*KSAMiRRJ(t2b$(UqaBjq$E3%`SdW;-#^Arkml-H0DJY%XbGio+Mo`>n*crMa z8z|pH3W{?br~sfCPNkW{ER=MLzR4=ApGXq!xl!OKs;x!h;;5!0OjF{h zF|x(XWWCOMBvbt7(*={+jW78OAOX^uAUoA;-@=B?L)MuratAYS;-qGbE}(;;Arx5m zi@{`(XwU9>yeW>EiKaY{;V&(cTVfT={3w|s)9S|L$&?vG2~p3&ma6r6YT>Xk#iq^x z_nH81HjY@pOBIbCv6y9y)y6;=EQTye7P1}(#S+|^bffHKAnG9T=p5)d)He!w74_#0 z4mM4Th3F-?GwIfZo=UYar#CeBkL`RW^fMXQD#~j9a}F{V4pRH5TM~=h%+w<+1(V-z znH6)0O)O$DGha>Ih?jjUgC+5G_-^zF-TF<8Ecd#%%Cq`eu1Ujq{y=GSs z`!3L+`z&T-Fw3n}=5+p(v1y8r@Z9Vliv))QM+A%l7ym%AC z$cSY0VwOk zU}7$3p>Br1gUZ#22Ui^C^>*tt>n_aMF!b0ry(5Byk3RYY7ZwIKSS1$Cxsl-$(Q#8{ zBvwQgvqVJD?{=^OQ(5?zgtgJ|10S79T}Iu(8~bBeMwyl5pT}gNp``fV(%MUCJt0<) zJuen%MyGw!D2at)0*z)jhed8>5omB&!=Y+z7=d9{G^5ch{2r!mCEo;6TjQupwb``` zjuQ)pk>p{^*(3xZnB7%@Ya9!Gf>|1wV<$QWn)uvUkGNQ($HSsM@LzFEoywBOvd|+Q zX1R`qSFvc+EnyL)$N@2B zF|UzMezrMc3$tO2S&UG^Vpl&_~v8LZf<1tP^I7 zPJ!fL626I<%@Ny~1^pMu8vOW>m?=5#8Sb~!BiYl5K2QTMQjduVBuV44)q(zmmO9n86j zjYaur_@iJu%casTVoNC4&VdLL784<#xdgLdMB|s^4z<^_FdKgj6gOW)0D( zV7M{NCvRnrg*>v0+0J79x3kcl2JCIjVZLw?$N!euikK5UVke7R#$pyxyA4O>En>E< zEcB6cXaW<8^fGM@(655UZf6b;!=%_biaF4D_)-Xa9+fQ7dJYRe%wo{5wlW8rAq0;$ zm!j>2nO!c_o{5&B?R**fGuh%=U0n5VabP`rEgG)1Z~K@dR2rmF8@3%Z>!Wc26SFU^ zZ?i$SVoEfI*>2&^0-YZH9b+H11+YmGGm7=2{{I&1hxz4p7Cwq`C-xT>k9LAtWfBFn zyrJ-JzB6LVlZzn6-ewkan2WZilK+P4oq|El#Vl{J>5Ca##KvLM$~pxzL+33R2QvsU zl@K(sGv8wU(t7-n9gERk;8sOtU&^OuKayH)cWf<@y zm$4|+0v54UL5oCvVMc-Z7}l1N=dg$y_}1lO>YU-%)A}=prC}2N_>W=c4Cyg!Fc|iM zA?h4v-bzwWlBZpx3Hz04L>vpJAJqgQL&vaqY-N}RJNb0+F~|!$=N$khVZRI`;A2qv z9llJM!-kG#(T}kxv&}SGWuaJ1W9FCOVaXnhmn_A@?EkO2tB;N2xb8z_hCJDnl61A)+dH0gcYE2plf(qD-3Cbt6lo+oNdv?| zsGx;iq)rW_AE{H@Lfyt+HQ=Ug+{S4kAaU#lMOqg~ni^=_-l^ml<&t35~ch(jlrzGIZ?!MS?$_6Z?rP~8UaHna|ku_*B3E?v}(K`Y`LHqwB6fQeyoPah3?^pD{&^xi6 zB(~?sekbvyvr#Y2HXWz61!Nu`ETGrDVicNK$V(PT7X!9v@YkFTn3V8U3C)G^INOjp ze3FAFEn2obL3CStM|L?^6rJ}F2Ugrc^GoY8%!k)Gxa+JB6V%2LT3h$^Lwas?`j#}y zmq>Q{$|y8e9av)=ajqYsJh7e_db)pSL%o3X)pzLAIhWzfpZ2Dc86wvh%@Hqn=zWkTC*F z;O&@&9&wz+`t#1FCwlknbo!rjc9fmXe~8jOOQqlVq_Y7_#7{WeUvPFj;%t7j{}BYS zb{)%4)cm)cEAjsm&Sp@5+S%NDaF>HZ=mkX4Il$?ZoNNBT*^tNlxliAkZJ-eKBFVWb%{&8o+ z1wZp7DNI`i3;|2N`x+6>zP3HzQ zO(LZg;|VMm`lzKo06D;1h1IAYz_FSnlq?y~;ahtPI`MBjYaD0evqYvfX6Frc(Y)ak zoFakl#Q&Dgl@Pu@sL*3PVLkaUjV0Rd1|!;8twA7W^U{U&uma`6vlOJQD(!hzzd_OP zJT0zB-H*bNgi_(OcK-t;<9)ruJDeoO#*q_L3GeT{W1G`=!nuxAUniWKI-I@cZO>bF zZtvZ*jZBtMTO2&%tjCv4?;Sgx;k((p{e;6TZ!j$BEtZdcI!o`PEEy*2p+4(>)mcAC z{eQ?AA@+SkiErKu6Jt-}IhEA2+*8LfBX8;wdhCk6B6o28~gY160GM5$GHW% z(jjLn7U$?K81%KV;4S#JwPWl&goQoX5(coO@4vJ6mhH~F$hWWe=9sVd3XFDXcY0Rk z-CSN}YsGRUP;O%}jGAg%Tzc*> z+`A9MHm_z{%>~atttrn&9Hf3 zyh^+I>Cx%w9I(vv1YXl~bJ@u$^Z15y#-WX+MSu6%V(#?;Nz5I`w>jtp=w%ncfo4} zrebIEv!I?wYD8M2I&OxigPKdJ&gExw**xk9jZ+KN+)_192_ekXK|VV@1#iye63NeI zOp~An8s(1#Xg!)FbjnfS6->IcU7|*nGn1apOu=JHo0jBqIt~VpFoXp@~cIvLoER|p?Gnvj4 zGD&YndeV@o*~|n$N|nksJ*g#!gpleYO-!P4X^{kz@SXR=2t)&ASt*`t(YsCUeI!5O$~pk%t_~WJaCwqK?AWy{Lh@B^rvU^VODW>OCmr zgqm(OO{a3}USU5`YT-jk$)nseT4>y`SZoAM3Z77NTC#Pk>Qa)Z{i~U^YXcliIWmHvK6sQO5?yhCnh%O1wB-l07 zv|DIZ>*+bFa5MpBL|1aT5V*9F2HcKjr_d*mh7qGmP;BBYlbg$^npX|f%H3nO?v*lW0 zP*+g{fsH0Q&R{(Xn}Od9qe1KjqRuD*5X8o!1VbJX;1^@>l+BFNBN_@chp_{1VWqHA z`w(1HIkc^aXpW8M(fGRj8B}+Ab~b%nq0%beLQtVvLC{>DyD7Rwdr0sXy-4qE;w?>i z({0QcMAAyN)2M_-6ph%L?lCK)jg~ta3n#d*;rH}NtVVro-(pw|_SJ(z6hfio?L(cM zLY*}B6)WLcY#{>e#3D? zqM(5=&JampT5Ax;(8CZ*aVT|~iYRuuste|q8jBS_tYPv4eM!%PCWXU810g;Wcv@5lEJ6wBjMl z71c8P$R&|A_N>O~avi;74!sw02hX`exm0ed)4|eNw1HU-XmOYgPU)oq5&5-dR3VQc zCSE!jNC2UYy64lhKUb##M0+9<$S9z(0=gHPYI`Y|Sc%?vjQRxi*^A$#+5+oJ*CM~xvAFI1j6``I;sM3tDTy#?eUsu%5wwU;9bmAibY=#jj9w2BQ5W z)CNU2f!j}l&NGl(17m>+wMiwr;`m)ZjSQ;3 zySfy1!*{4djc)i(HUH&q_%3y_D}I$)?27-gn*T~SKG?s$+zr24Enn=0F2jQ-ssAhW7jS#jZgt|72Wo{spH?Ub>aH zA2{)m+byxbMn7b}Z0=&*zR2_1HTdskdfAS0g8ARfxP4RC2;=r`U$--E-x~IQ z#_gNQCKfVLrdbxP6NKml(It(*J$N?Q{GeW86Ni|9Rlu%Jm(l7jxOyIX^EmZlA>Z z8sql)uK&)seQNB_8DDk&EKKMmhxSRf8-bJD$|=A(&d+wHw~x*p0N$-!H!;0^NZx+t zFDK(kzqoS^KFEGo{^Od@4t4#na|UBhxBSe49zXwGHGlb<&+7TB!u0k$c(2A+&!_im zKC9=uZ)>?-y-s)-^xIJX|C}@#pEZv96UJv;10cG7zRkFOCGp<^-->=D_h(6czRdLY zbrnBhd?;o3$~g8jjdNl#X9w0>l+S-d67=Bg9{nVNQ@U~&m!!KFc#>)2&M4E%{4V|d z`-qr?ys70lwNiI+y4w#K`~V00%tvk!lXMrE-ah^?VqAWR@jJ}ty6Kea&Aur5VaDwns=uM}P9F63G}CXp*@WHOW8A-C ze3*}`TxR_Hj6crva)R+6GQQzP6QA}q(?j>ZQa)d~$-MKi(drV(L+|Q!=6`{n+FkBE zQzuQlUofBRZZ+=*ng2R85b?K9>)OP4V$RU-MtbznMQ=p^>J8?7(m3iG#^-k#K$f#N zGQMol4>A5E%dN=y`xu|uXZSEXHOBbWTo1I)poh+KrTk1?XWlEuQ8SF6wEEHAjN6x& zFKC=2$DGz0_;0R(Kg9g)^UA)?_$72DdhRfey2QAPAKTLNm&Q>qGX4#&m^$O%15Wa6 z_s3V6-afqaKQzvfW6nB<<%Dm+1DSrd0H^x2&uGJsR)Md6ZejZMywv}DW^|D8@4Uyv zImA&%fhXA?cRtAUyKgY)r#bL$#)k$BAni-X=WXrXt@@XlkeyS6Q%+ABK+3hmeC!kE z?qmEz{0VcM`J89`(t8acUpNmkp4w~he`5OIWBmT>4Iugd8sm>y^7$y^Cx#9Ed$~XU zIpdf4+`oYN|25-JbBDN*>Hk6FOcZnemFbJzkB&0^PZ{4bXo!=H_u+e++Wnh54bH=a z+RXTa0|uA+-^qB9>t_q6J;1nq{NPQD%kMLJxKzJ}ab*j}tHZy<8DTy{O#dTXTu9GD z#!;8ipp?(cTMfX)Q{zl;AGCOc@vHV5`WsMwdS)4K?lJG*Gme@EPWiFtivrV&L3otu zPcd%a92o+qaaeB16gm7D(_hEsdW!jcmT~*CgfB2IzvtlLLw$wu>>db7`K{8Q%B&-Ebf`#5mQzud$r^XyYh{|1lS9;ZQfcoBd5G{%>hkKFz#eCP@< z;xAWt_COBk`GMwR{PF)kW&Y=RJio+&{e6_~>gQL0)A(SwBk7MQpBHX1aqi`)!@!fP z*{B@T@8y0i^)t)(zi@w%`R*f({}B%u$CzhH+v~4+-MS}=e>>I{h5;N&Q(+h6pLTco;+eXNSU@Q#A zlE5YcZA1_iytWrm0F=4pkXoNy(){apZDq(?>IIW@_AZ(XbtjSy1ly z@u~FD>{w@rG5)wNjMQ%CFmpIeCg923^k_QgPESnCWnkVV6T2HTSZMX&}1$m=JjCA;Vn#Zu7pJ9Aq^SF#}2w5XN}>@zCYI%BZWgt~I4`PJSTqV3Gu2#kRXCK@s{ zMX-s*j6BT<*4$3^E1NCYcvD0_sWpq8R57Dz%$n@Fr7HH~n4FWKlAYI>yOD)P=q{pO zXloa3cA||xF4^V9SY#Wqb(^>C)NL!QG3jbME;X+)40D}PFEEC`n8CiP2SGdkZ9{V0 zj7zq4vE(E7FnA*qZL6&o$p&qL(I!xt308I4Jv;XnXft+EZv*M9 zFV{s!=TU9Np03A&t|Ni5w8u777=h9ALo+J0ETLPmDq={(coasR$s6OK>-y(B8s)qS zwh?qvAdDKtU7&$%C1`~A3a%hDs;LwvQEcadi)|a)T@)X(7({iIg2_Kf;qajptjRDk zHfFD}BOpyClB z`|6dZN@*cZ!J8^!>w)$(VB1YK$%LPx)dZ+RJv63*MP5HF7Qjv33=gxAFfqiBq`Ybw z%uI9$r%Is{Xajhv5G=Gxp!8}bta$jfTq}m+_ZG0qI3sU3qbU$S%|`zp4=pRPl!tEE zJYwe+*S5G3ZTz9nP%QD<@x>l2ZZb{`e|!DM_yM@_`11)9ATBSHnVNLNolh38@%Un2 z7B|^RzAFCR2>;oeZ-!ESu|tb1dL(=<=*P~#2Xq7eB)-_I#U*__J(NfCN_XJK?z`#*?) zc>E;C6Zf)2WY=P^^$79!_}DQIyFxE)@yH|lMu3N_rJg5_|pFBBongxtP~2Ij@sjk#-gEwfA$WM9GeWZSRq2!GfDKu=#Fz0)f+aiRUJZ}T-AxJLZ_YsCNIPfUa*OPOS+Kek5vkLVK{l^RHL!tB`b$qrALU4Qos z7|Kl>yT=zkAp#Hgi+HC5{Tf8ROh-nla*)V^o?f4+Y%%stDu zobP<+JKtIExi=ef3+5ON21UJ0%5;TNN1Y-kTLKPb2XV5MiAs!;tqf5HD`vnW@Kf=^ z!y`rjajBt2Boz}vqD!Vo4`G_fR@6`}okF7P?b;e8AZn<@iZszNipq3&_}iHRPYqSL zR^CbhSHi+a(?z}->gh-~%i08d*)KxFG+Bv*6(V1yBXtp7m87eZbZU4)DnboaeG)tR zO_cf!58Z&#<>q%q38z~o>B7U=5?>9e47!#c_m=-x%3Cby-mevW!ov|#4mDKEy8v{g zm+yM1&AddG*IPS0Anj8PrFxZ7HPx#oj2l%`KC-5|&bMadnu!xeP8gTjRG&G9i$HQw z8Dvv)7ZxdCvybwm_`EIRWt!kWF7fYvW#{r2Ix;%q-g0y#|NhmTttt;HlW^!FdMT2Y zb|FSMy#9u3kcc%>9`UCuBmKs-L!Q@aC!K6nyNdwm?t>90n(*ssWVpjKkM0yiuwjmozmoO zEcZ1i6_p-unNm{XX>6>kFR7_7EA>{_6STbE2h;{1pcQ2`^-Uh7wzLLt;FfvUHh4-_ z5jG)$RH<0qSnc%yzp=W`TR}K$N=quL>q={?uk=t^Wwi|y0JpvoU=pdM$y?g!EvYT7 zu2bd~V5afJYQVfmlQ{Hw$APs;r3!}7n9`CG&C zPs{x6Vfn^VgKH`TN51Tgw!F9SFT3vmP?s;K+B&MfXrBi9G|;Dkf4v62aP9mdAXJ*$9}T2 zR7=yqcCzyVElm#oWM__+CdYoVbF`KwhkmkipqfVQKD&u(H(TNLL%Jv|y&x=|8qr$>L5-*V_jc`YC2H6J^%xUis&J&}#3 zZi|`0gK32siV{e810<)m=Cw^LB|B(i7gI2)+nWH>cmyyq4Qt@2W5CtWp7NXwfj^q# zk3W}!bH2@MIgz*j^BH;jyG?n97xE5$>x~D4&60s7aI}K!S*0iYxq4bUXcgaiMS0EB zRsmDVYdP+X&TE}kfrNkgw}F7a9F6q?`x4bQtN^W6KGAos29P2}po1~Twz83bR+Q#$ zhj#*Q8zwh*+r5Kv+mO}V9qo;5?vC+Bbq(prJxzw&H3|{3*sfuSkg0a1BSJRX72nGK z^tqz6ynt%HTL4+EnhxRGroDzt|C+&y(#oDgw7EON=V;A6-O}OzDLA#{p6+^gE7C7M zr%JUHVr8_fd%u<4%<+?bbzpNHu^G+TT*b3veG^;LeTcT^z7J-3V3yNzF3f9QcS7++Lm5Ar58%zf$ZO3#(Mql7vr#m!HQU`4!DB7C z-N5fwyirJY6HYwL1bQUWWgu-`@M&Ia(FxMt3wvpr>aW5AJJ<|l9R4@{9tgDLp7KW# z0W(3m=I%saMQiRUsL}ybf^^-j?88qL1tvd%ilSW-We?r*fO9E$!lrX>q~w0yFng%_ zkYqSXl6M+B&Y*f2YU{FzQjSA}R(8E8fpu1sC)yemvt`}s=5?oy-e}xSUNi0yzDVAB zU2GRg5o{EJ%DgThnK?luC$RKJ02R1f)_vN%?$ZeG6uNJij=RY_jP4u8;BN3*a5u^> zLcY0c1Udvc<*vbqkT>p1MTFdNmy=A8`p1}gsCqH>fkF&FSe%6yXW_*~^5PGd|=2%Qgc+|yHXyVs|~ z?EFCGy$iNSODF%QqZOs|I*nnzC@;Qw-BHD7m!+Di)GiP5jMQ#NO};`={0W!{WSt|* zj}f#JMe0tZP=Sxozu{}p@`m-vtqV>|8BlyO6<>?uyQru5rPTxtj9P`%1g!#7>8c?t z#}gJbU0&J2yq1G`hJAU4gL(Upn(|tHgTdgf7Bcw=qvHu>;(p(xUhy90c=1N!m)CNb zddnx>R1qHoO;>y~d~Ped3|NzLPhZut3x*#E5evS10ibP*4J`??5kdW~S$8@BBUn#8 zJw6W=tDAUct7ipUy=B4svs-eH2oXB`78D`06!207J3B}@Eh1M%x)(yCFZWunx2~tY z9&PLqVSip*!fqf?<3zwfd(a`F{DPw#JsZk;j`IH5P)az;5rGm^T?hLFmPTHvl^sK@ zg}sY=D|?g2U*hrSdHiYIw+0;uxkS|rW{~XL^V;G!lU1PEZz8$~Bka%}4r&6ZBZ7J< z>V3MaAGIvGtM$*InVz2m6?aTflpY!w9xI&JaIF~99``0U69@bGoOy^y-(1VfrJCwI zrvDVW1blKjIFV0|1X%US6~yZCzrw`^Ypsh)4+S^Yv+2K!0?G7gR6q&O@T3pX1^5+p z=VQLpHa-Srz}UH8@LQ;?VAGI>Wu<%UTP@%S{^%-qW8#V;mQfL?1nn27mFUhzCI0+n zIAe0KT9hMIb;^vR+i%01`3?8db|c=Qm@*(PJZ>kC{df&3@fR)Iv0S zH1XoiK3Xq<2NHyHBqMF{VZiI=9ZqeY$&y*Pb_el%uDtt6A8q50&(bN+Buao)2fm@Q zxE(r6>Z?bXmj zd0xPIa%XuMwSjMkhHllf9VH~`*^;|^t{k<~f7MU+!ZMHRT1-Z0v{rl1qw6)LBoIp5 z_)oHRO1b>cnxE{2@t>sz!n^wFAmiPH(l-7+J>z6z3_k-O)eGaF^}_fM>okeW1mjhD z#(O^(ezF&?c_2~! z{3&i!Pwz6iZ}8&Imvg5hyhFMwFo2#Wjl;)SfvEbJv8213!KJGR81MFg(T^}LCycSc z*wq7ui7*xshBk#WP}cmB5Gc3X&}-$k2%S&L?RMNa6H3&tgXPpLuf=y1^wgUTWG}f# z^Dr0dIv25SEJz%C4nnBGBvjk@ho4S_nDox)jlL;2@p zIs_3zdIycI(CB?2Y%Mws+Pn3%flqqUC-AS(@Ym|`U+)oL=)YwFc8o%r;4f3r1gp+H zvk9(WOR7Gz2^x4lSK60UY19-fw3=Rk(&0VARsC*|YA>i-7tnnFk9xvn5c-=iF9=)h zi1`$32V8?o54jwWGp!z11oc!7&8;IGn>JIAMr6xlJR)b((>m`$GTcx9Y7JGKS1?{w zaHd|)hEDkD?LE-_JV^IG)wXSXx}I(#=(@_n3mX(9x?d3eZHi8tCL+Qdw-?`iBS=)= zeFSv=LFZ6?dcm%c*d6{yu`CJgqI|WIiMdM;6XEr%Ng-qjy|~uD2P^R*Mcc+-s;|U! zKR1apOdgGgeMpOA(=KWhif#Eu#ITQrbfmYa^OGJF{rMHDJfTyM!#tli+$BPc?#Vh` zKKU^k?!g}T-O&rbYlHlv1iz>C{3^k(>qp@YdOyP_-*4%EM&owtt2=~<_o#xhk zq-idcUwJS53WEF&QN7#7KdI+868uPWq0EwcVHWU`&|J7pg4v~dW=D?;&7ICz0a10rPCsqw|-h zV1^CN)OoAS2v$f_*jm6v8|(;23Tm}bL;5k0xGp<$RrKr(lB|EOW)`*SDeY*X|UrvBoV5<$Q znuI$L#~$?bz){RB$l?y8CJSh(Q3Wzx-o2Dp7@GHY%F7PTE5hona|H6R%^u4)+nv6C zLYmeE$A}>&da$prfX09(LC9aw-SQeB$FNt{*(Ii+{?^6xObU+|GPqz>m^ya8uEMx7 z7h(0%xm(M!U=y5n_!E6`Dq)BJS|Zy{-4X2&=)6f{Q%|GETXuR_ndt4`HHAoc?&1tp z7ppPmbr$O>7Du3q6PTpE8r`#Vnp(VgHkUXaeSX(KSvOGwYT?$r2$gIGRo@J<)`Vk+ zL?JT0+lCp<-9}PEgg35hERgt`1@eqUV|L-uP4^zOl!A;j%D8|sV7ZhLMH$&#((DX1 zb3dkPG*1Xx)bD7`lETr1j-1$R^WWl@O%fc#L_ciBv_`jiEHdv4&Gc7d+Mq)UZU959 zooKbN2@LmjQD`nmCZ6G(#!A-^ z818Aw#8MBU{lI+82fRQ`s%?09&E5lA^FBihdjk>R204qp>lXGH0AaQAuZPv5lrD?k zD`H^h_MXJu>cun0(>Cu%xW{;p;vVgNH-s-$#y?FXD|T$ADUSau^|{-Z|2LBqb5-+-0jAl9({>D(vM27?ZrR+-lIuZkt_6~KU1 z2b+TmB8!nFbxra=C>$$k$d>?I+K3`|VL12#3EAD16_N?#zdn{$#n-Is{uUj5{T}Qy zCsU;o(&dmJS{kZFOYoK=?RnvBuy6Jo@C?sq2k{r9L3|_)N*b&I)+M8oG;hJOkjrxv z@?aqfHm!crj^cbag#`|Nu=Ep z=`}(cKuGTdksg*vKj%n3+b*bF=_DT{xonXLS4b|c0PV69(#=7nI*D|F;8MHG0a%w$ zvM7?!u>!hemz$s$N$7M5O%TxYccB|7U6Ukqn1p`yE`Q{kCVE=GtzB_jyJEL?#cb`e zZS9KO+7+?2%dnNZ&JaVBO~NuRLxnJ4&;#EQVCi3%Dr?xnq5k5v)1n6*aCpt#>mApfkL-|Ek3q3&s~f0Rd?JEs`a1+S zx_3SdGLeUf(s`?vq#>yD1}zC|Ryu#IB{7{=I%~9~i;^p}WIQDoYRLpj&d`#Hl+4nS zNt7I@C6g)X(vm5ZG$H9fjA<>ZjHT%`pF@ajCg4XfQ|JLEY{&Q`0LW50U&YKk?sx-x<_{h zzu#Trn+YyY)7gIbm-Q$VZBtLhwoPjw5hiit<>LxJ2IYr4Z;9=K)st<;K_VKd#A4h+ zm2jdG)ZL&I-ASkp_EDucFVMl>M2s4#gT00rT^;Obhlqs@_`+$j3gFShZ;1E-+8-`( z7oq#@ZwCT z7&xIo*j@QOqsEfA-%jHPZ3pjb?k@C2cd#_nfm4yi9|c2l)tNM2&?%H2%hWT%Zt*s; zb&W$mpE_>55R_0P2$8%>&+}a|M)y<)Xy{F}0+sAMj8<%6w_z}Xi@KQtjByM6EpK78 zqGrzG2snh&lQyu5XMgs9rfvLY!BFV(c2EnI??;SmhM;ZJ)>7NwL0K&P=F#Q z_!HG4pXCU@A$bJvJU#CjfC}Co#Bz9nPoWtUe%g=Eyiw9-2#bM$ z_$^o+`=`U6h4gn~Puc$?bPSQa7fHx+5y=9DY!WW;t9J`7H; z>39VP0qbgLIE{QjR(>X=BO z1&W}tpti!Kq{)Z>ThUr-jgG3C4a4O%dLtC~NH4gY?|r}xsXdOD*`Gs2d)#*KUd0Ff z=57N&kb3L6kc?img~on`_+B@O8VMo%+i?>*Ixmu|4R-Sc28y2f?jXMOTv;9@6`OGR z@Q`G2{6s4+@B%7u8(0%&Xj{^xz~3%w?jJ94!mD;ZL}>QMG^M8g$69;^!A;7s{Isn`a7ALw! z`~zd>&Hbckj1xHjy`MU9f@3ocHU3wLFHA60U+CZcf#&}hZWl*HvH2YE4y9*sJsQUc zD^=t0#=#(t?E}lUX)))3K{{1-Gs+NZNoD|%E9s5ZR>7)u!6~W~j%(5!&%Z}nlK&zh zZTON8<3GyuPvX+j`CTq;FV8hbiy~14+1-_8$DVN(8+A=ZFnQl+L!>{1NEAon1g^WiFnXjLct9 z=3zl~`dLslfC?Ne#NiMrPWFl+y_)iiE4aO2u|{V0I+%cd)-cdpAY89xHwm)VB0T!o zOY2krwbGcdmTa3=Pr{@?7-47~qy%&*|1@Zi?51l-E1M4-{@mn~p+G)HkhW7&-;0hl-je>?Fi z0x#-gbUJ4ruLpVX$4n-@g*i8)>;k^($U5?FJUBhOVDtyGcy9GzT2in5VJ>!*~T-NC2=yc zAkKFn@jYqNb4xrZdzUs`iQaV*woWb9W%cjGD8ju&NQ=<>Fj!0M_D73S54N%^pFxA> z9%x>7z~zm_Jqdkl-GLOx=ATpZx8@$~$fnbyJlgq!=ofQ9<3EAj=hoZl)ERT8mOuEfB*9S= z_&>NxwI!l?OJHSsAjRh-(qO#~cFhvJKLzhexw{=VUdq=&RNT|ZBBvk_UX}=(=oN@C zCV0sxFZ3m&Z0tAUOmiN+z|pecNC9M;-Ll}7y;%^@zx#kRC#;o)He95QOK7S}Mvj3i zRz&2(%OU+T z2O`nRZ91$tgc4i9be0x%IMK4;Q}wkZ$>BvE2M`-Vi18lgMe>2~K}13x_-3KY9BJ{r z*#gO7chu!$y>@!&xG4f1qH`N={{I7Za58d@)P=gTpMy~zJgu8FIIn{iz>6e5gHCJZ`OAZ?&YluA$W zG#i*fI5Z2yP{Sw6FA(J#D5T2}`VfYn18wnP<^6vi`UMOrI!4e2odj{Qo1mnxS3(kPu zNU$WL8-E6@kzjEIO9_L?=Z38@4=tt!Wh;2VH^TEkq-l=rQ+H0!Lrk|39?N&oNmJvi z1&dT3;8ZCF(;V?KnV!=#dsR+3R58 zV8J1qb)t`ZUm|fj$lNX`oL7eH!S~K%WNs zG|;DkJ`MC~pcf6$caZ7Iuc`4=me#oGtIs3c-ulb%_2?DIUs&(P7o5GGT2Gy~$z5IN zuJF~B(buEhtE;_L?z;NAkyq4LmvcJe1N=sh*VhQd`o^;&+h}W8DXMGql+{<(RX2Ic ziG4#ozAf!(Eb-P))_C@WcSUK9&r?$Bl~{%K_3qlzy0z}gn)+3!M$_8bRrNJZiZZlu zB7T$b8=XbB(Uh}_vgkHCi{D4nePTJ~(rt7WzmG0g7WusH`U=!Ye4DyS$)!(QyS?v^qt;9ksKz?9$%Y*07O@fTY*mT2p-q!*)&^fw)#cWq zLmO8$*sQhnSMYdK!w9#?QmhU24annQDA%S4q#;Agfzl+BSFQp^QwAui8_v;ZQ`u)^ zpMg8GR5T$qK^a6YEho7rE7lrM>E+gfq2-}0O3TZMg)FDZ#|xLK>RMlo4k+r=Gy;;9 zu7Rv&m)GN7U0zMql)@uM&=I;c@gCY(UQHDEB>5SrqT)@ZC@Mq`tE5;`UZET!C+R{m zRT;I+P#xeS=e14vu6f2eXx8#lZz&p3YfA;~hU`^qy&h{8%E-hg%PU3fa$jjV#pG2~ zcUfKi>N;-A#7-!f7{Np*yHzGb%WX=N2On3*t&ZPoC|XH3dzZHliccm6rgCgvCeL)v7_Vp-r0Vgo%h&LW@oY^wQb}YFwLgDGI$5|53`NDDTor z1e};d$=PB@BQ_McWIRL|P?l^45n@Dgu;KlCyMa{@jHmWTmGL ziq3!p^$l=Sq8X8cq^Ggei!a>2{Bj_0;Y)!))r*0^Rrqbi?;iYi_44~0@)LlcfgjQ8 zf6pNA5BPnJ-%!9@_!Z)(7VK#%D{b(&n>?5MJauIr#q(+)&=mF?iS)RzyeVPnaGIH6 z@O+tGEW?WsF7@Jr|CR0Ds5CeHBI<40nku& zg#vf3aBR`!%Id0W7#NKi$}_J80^i~x_fdolA;sx;t}fo7i>q)7ZwkwQ3F(LM6YbdO zxztnU6~ma@ySf?*3mIrg%F;4aN6B5&08ETM!;6Oxcb9tIp1N{!`Gld?m@Jv$q(cgh z%l*Ipoq`bocbMogdj`Q+Xb4lSQNn8m7pVK(lt^Ow9XyHHeOO^No5oX{w3csSd za!*+ehNPg|haR-N(#FQpwKTEJp$Jr2?pfomZo)j0Pqb+6S4r*!a)M0w+$%~OtNC98 zp?Zt{O75uCO+$2P<65_8O+%xnsR@(P5$;Mb60_H(YwNtFYux;gk*G6TMJcSu%vPPd zf`g~b120y_$L0Ell3>PUDos&_Y5I59`kK7%RUS-i@h4JNqk^l}x=ZWa)tVP1{B!>a zd^e_&=MoXFkY);2hz6okRIRd(Cg9vJjC$JxLvpDRvQMQ)EeQVbKyEBjIM{6chx7TOy;gbC=}K;XH|grzo-%*txt| z)ws%iwGAPII&|##Qy_5n9|Hm32Z6wC`0d5-7=G5Hfj}mHOYvKS-!Jg{4SpZvM>KZO zL;;WD^vgp00P;S=&-Gy-(2n0l_;ul@jyuW}<;Ti8B||w!(HRn44SGKQ@|1@Q3&+w! z4#uf4oU)J{#n8_*B?HG8%2B7;cLf5)h!43t5ZHup9Kv>l5%&ZFvk`uV@NtCAc>4M# z!nyYa0^JC0_Xh&WI4klP!l?+~M_7z7<^jxk5MG6_9bp&3-3VR33285>(9zmFf10f?H0X@Pueg%4j zLmmY^!mS9~5uQf48)4OBphr0KKS7T$2FIb&aI*Shgi{fI{W$0mPX0CM5kB<<=n+nQ z67&d{?E*c*>k*ztxC>z#9-gmx3iJqXLRgIOy{AEsaQ-u(N4Rk}=n?M5BhL2`zJ>5K z!bkUj9w$s@>;*l-InRL};Ux&KLfC+?9pTjocOz^^_&&my5S~VO9AO$(6Eko~WGcc7 z5f&r-Il`+DdTkVFXSF zuS8!Ng77Ycvk~q=SdQ>rgqsll72!PyU4H^S!c2t65Y9sw;lLRugl>etLpT*-zhi;G zGKA#_y$Ih#xEmpzE}+YBhHJ21Wx!tBUc3Wne}4!@&! zVE&3wvB%D_C(m<4t+rgP%t)Pl?${xND4Xbu@!Ni9AixPJ6Bp%s@!N|0gOnjJD(go4 zM(+#+enxq@_SkEUvtrD~Hb|r>Ze%@#-~E6;k5Gf>Hk*u3a1<^t@tk{CAn=?X$N03y z;{@_Q0sQ_D_#J`)@<r@~ZvlMxJ(!0g)aq&KZy*Ll|2Xn9;jexk!v7|X|C@l{3;0Amygn%3DZrlv+@$Ak z{92=r$JW>m_`ykf`i3C=IKZC*yjBl4mTUC%O%gNwkFV`|s* zKMwG^{|E$dbV)~_uhAC*z60=@5O|pe_X7UuS>U$-J`v+bZ}g7?z6tPmL--%k_`eDG zbc{PMhroZM!A}9+3HX8#_-qXxkMS!J&tG&euKzayKLq%Ddbsfot$wEfzY+6*Eg|r0HF!Mc58nVD z2|a1`H+^d&1d@Lo;2&Z>K&Q_%xadBj{Q-abEO0O2uK*sar=J_t?=67u2As;$_%98@ z9|wFF;F)^3CkTHN@D~8b@vR{Jk|6vP;QIl;SPwT|z!9j-c+7vk0h~_BY2_~r(vJiD zB;YxE_?jTR5b!w6lU~!qjlb3Sdja1Mcy$PTr3SwRaN9G1KwSu2RFLF*9Pnj;9}a=P zs?om*xE=Gdn?vm92F-p>0e%hUX%qDHwL$sgG2Z?h@Ja9!TK!E~!S<*5-M&Czte*Z- zL7$AgLcpH`JY@Vpz8k*=z>We|03RIWJqn}D02$9_=={7Vgf3h-lq_trn+G5@?1^UCHB`YSd1aex~!-+VX(evbw(1bhqN zkA%SQ)!<&h(>u`qA?>qLYoA*HufV+Z?GX5D8vJphf2sHJ{Y}8f1CHa`LH%9Gi|76G z6yW0kFV@42qJwe!$Naeg@DD=ZhdF~G$QuXvDD2Uu=-UwUFjJJ)jJ%v;;JIJzy`8QC z{06}JmV-LqyF4goJK*;KK20x&HwfPi_0!d@M6Fho&|mt;PcJ`ZwGwNS>U??pV>5IV~^cp%(o}sWXiR> z+ahx988@=o_N;5odG?9Tk#p_Yb@qul_N*Lx#!S0=ragJ4J$9zu!aquK3;4uhU4>z) z@9NV)p9cCg(5Hbu4fJWCPXm1#=+i)-2KqG6r-42V^l9LKpa%B2giu$@khZYsQbR25 z#l<&&@tj&FckzcQio*ADkhkm?0>Jlh5yh4rzfxtmQo{M(4DwX?m*0xVZuEBp=u-C( z4#)^?1<`d-!m$O!uYe4(Ey6F_BcY4$af>LwOEP8Iog$OA!04JND@e~b>B1H(zxW<9 zV#{PfYJP@{sB&jX#@L$Ums&nPCBQEg?;H785ykN=d@h4OX6%*~3k2bu?u1Mqknq3B zw5nIh{(B3mWV?hj%#!V$EyKk!Tq(l_8D1^Jtuovp!$)PfPlg9&cvOZbWEfuVKT2D6 zoE?Ljl^%nTvcrF8qddA&K#$4LFT>Adcv6O6$?&ucjim~|EHaFdp-YCzGHfjqcw1%o zGa244!yPibPlf_Jc#kX>@hBPEW$2P&q6|}HXb6&OF*0egclwc?(l0~)#vs)Hh<@&@ zS(DuvMXP*uUY~nX=Ge@vk)zM|@#N_BW3n={#+@Uwl@Y)eJ&PN;@}l%6&#T=HaQ!9l z>A8r&ZiC*9N$r(TL+T;Tu2t>SM#Pr%Mm z-A@pe#{_;ElqdM_=SK^$%Px{(*s474EEWF*f7F7fVrQ-I-tj8_15*Xdxe;fu*2(jG zY`hBr{+uoFZdKh^7@3g&&>R*2`aFR^Ez;8^@UL2^;!j;Hu;`oJJzbB2j}X;j_)n9f zME{CXaOpi6hVg2&qVZ4?>BMA-{2D<-1fw&jrie)L^Ckb3u*vM=Iiq(jmhzZu8Aa1c<0`?K-^F*xmMo1hnktdR^^bPcgNj%}U(zEP{$vlx^ zT>{F8DLj#7y&K|0Oy!A*)=Yv-@GJt);B7ZX(D67kQYgt$(9J7dkFQ zVxu*hSTC|%guG_!Y@)fqK`OuAdLbp2$7}+^R_k#>yCkU*knPsZq>$p2bx7>6dI++D zi}Qf>0J0)}WZjCqN39=HqQo{5iCtFuqcjmKxorEaw~;ujEX_c8UNKgqAQqYOAnAzH(TZa!E7NwG_@Pa6(jnO*)ko8s1K2Aw$xH|BZM+r)*#ApZ$^aU#wm9C z?7O+eekZcbys_=C5#0?u$3C3mts*`Pn31W`*~p6i0O)i+#i2yL$SG+a5%~_H_Wp#{ zFO{INkr8u|Z;3Yl76LdoBd$1SqkabG=ZG4eTaj&Y-bTuF(&IDcqz`kNokM^_U+M*| zGaihr&Kbb5IUR^cInTj8+DV@~i*e2c2fK3t?hYq?S3lNS2o6qXA#z;K7r-ITc{}ps zoevhh*oK$WL)zf)Z1m^yhy1Io|?)n)5zjraNZ>+TVFSat1h` zK-{fZ{t9Peu?&d)3H3!oM!{dEDWb1mXF=Oo0VobBHBt{Kea63iC8PI=2D)B zSBxI8vlJSsH2af?TO-qnfqfosR*QC%a#2Znf)h6PgQLIt@scYKb#myQm;{5@z z#-x+|@$OuP;W&|ZeWPMuNksPaCCH1WI$W&+1181(7y%vW^~kfYp^}`uq@=Nk8!k70 zL{lJK_lrO=w7&(+gxyDnr-v zB7ne~wUUOWW+T_Qt)L%F#V|}|rKCMhv{8(p>bUze#OX4$i`qp?>>8Lo7)B^}P&0}# z`w7&R#_aIP*?C~wH)cZ#ePcF^^#?m!X@jVQF?jS|}MMhQ8*Q9WpQBYD)}jpEwqMelBWf1}sK;P!owUSwW; z^s0p~4IjOVkrz#MxIqQ#MlYHxg^XVG!iiyur9XzA4w@t5;%Ckg8rmsWj5SmGQQWv~ zS+auAFlA^q5RBUjQ!xE7Ovw_d#i=KV+tf&rEKfa5$!RiKmHH@8+6A-*O+bsTq*p07 zgAXaoqy&6B3k4Y3JtP4i{4!jEt~m9tL~xGeTB9WWhSDjVL8n~w2N~R_F-VCIVUVgZ z==Uu#h~*4+Nd|K94GE5D3}WRFTBD@-iNeY$)S>J=$V->Hw^y3m#+VnVNmnFO*C|VZ)=Ak;Px-`zQ@2kHf-(iJLE-E9SrEp z9H{fYCrBFI+QFFuM_?Gj{m8S)+*B6(2w!->`?_c) zWf(F%n?o17_)LGu7?CV+(Q3*tBwHl&;?`o;A1M+wO8h`7I+5>4Y?eh&1RJ^x?a!m= zIC%CX4L>24@NHaF)ot;Yk2ro}6JYUD$hc}O5i~;OE$jqEC>z01dcPEiMcyxb2Q>jD z^m)HN@Avv@||!t7+v9!hu5`M7dEi_v#%y zQ;FL}jyYQ9?vS~{uY;VIYf<8+5Y}_iK4e)O59Px`iuQ`j#s8ji z?FN~xNTCyQNSq4|EE`OIbS`eV`1@)I4ejTGD6w%gVI*WD$GEK~v2hF~<>*zF#0Rqr z4MPRETuB&99A^uT!_NT`F8+obLPL8E=ST?Z)LL+uZAi`r0=CzbgiR#s6v5%i4CLZ! z5CJ$mOdM!OYlOBForX~&S)SAa(*yW?kzT2!7^nn`!CWr6 zXMv6`L;GtaZw&!ejVmcRBrqO&jXMLIz8OH+CWBn6)hPWgBJ3|&HrT}vC8k)0YZIJ# zkUNbF|7E{yKwu*2B>R`cM5-#C4Cc#Bkt$dE*OR2j%|9IiWLz6W06}j7r*ss3TwUX( zSvYFCn361xqoNx9@cu@em40^->kgI;@ZmuMhvIY@+6UrrM;f>L4#^)%DyIS-2(v^dqA-+{>vu-GX|72vFV~lKNha8s8cLdXW5UBEOB3_m|`^ zYvf&${I=L^|2qc~=BLJJ&`vLHllT2zsqT*irr|_`k>}EM1p!T zr?$!iP5j++a4@u&snm;Aqa30*AJ%>|2E|2vTX=OhK>a-~0KS%X?!UX5^ z&ju2f6~s+E>m_dey~J(0`4Y)#xyI=asvOhh^8p~=L5#01DIsAP-ati7Rw@HpbYg>c@DF>Sec|zE3blg zghF3hkqeuB$e@Ky_)(96u${hzP2a+%Z(-Al4)QmHNebLr-^dWp77nW`6eTGJ^FPBuPO(N(WP+M5Lwg*2eKMa}9!wN7%VjB; zO&!vP@ziW0f5luZN!6pthW2cb@`vfKXl14SfuuWNE|AEvq8OBuHkQ~tZ$4i_5`vII zg6uO7Is=kqAjpMW@_r))0sndjmz-vK{ptXZqZmEM;md#vQ?r9m}~rcAjAKp2n?Ra*It-xqU(0oT}#2IX9=|R;3IWLfpg?8g)39<3D6ep$Wdt zo(=X^Q`Sydit-d#MkpVEQV!^=5v2h={4C~Ym^kze=zRnF4}3sZcO6F=7U3y_a}*YP z=u+2_(HotNQW4HQl(IOtQV{EWlLEK%BMP#e^pQX1YFB??8eG3d!sz-v?h&p8DctlU)1+ zqw7lKr?~hDMi)Q9=;9|BUHk;2YbK!mUHk;2>j}i&@&u!GKx_f(#E*Db-P{R@6O7i7 z6O7hDMyk5l`Lr&Ky`N}k5oFb$i?iy_#aZ>|;;i~}an_J?an?fPGH~NNpEljOIGgTV zoK1Hw&ZavTXVaaFv+2&o*<#YER{Uf^GTdGqU+ld?;_gQZ6aBtB-4(K;RW+Gl8+3)=Z})l3u%H+m6CEB;oio_n9s+7 zA1?ldB!q@`Cq_nkkab(C7~6sGA^dANezL?r%&7>U??*zkYvdqWoVdzYf#hI8zBsX_ zx)#Y1*`T0WU}3pY)&d)iuMq1h&ia>Q1WNnY z=anOQRcpK=Fsda2zaUxQ7bo#8pamMQ%M`=Hpj>w9%_BLlrZIxaYZ|X{;6-JR3gU01 zvfUhijKt5;@M&j@@I|kn1$F9h;-3=JPvRzNxLc*1DRR32+Zrp0x0Ul&hv17feBx`< zZRaaWv&Fq;R=(heWIWzKvVl=d z6DC~zBYFr8?Tb-|gjpPeuWYd4nlPOwQwfAsT_Q%H{*l?h#yFaEzvQq6X}S_G#gi>b zS)<@|9t~s36Ny7Y%wUNe-2U7|#pQ8m3SrX2kCX+Jj)_rSt{jUXoRSJxj9Uxi{o9gVzbszZqiR9B%GMi(MafBq(^gGQwLEwrGTnT-(#*TW*fs6@HR zq+7!SHi{d!trW-I|3fCL)Hk%AAT})yLfSh+&^K#rP7oXZQ2&O=Y~<29C*@tDsO1#L zrVG^Ib|#(V5hc}WC8c~p6tg+SM|ka;u5U#EQE7FQd^=&}N{YqFck^VtD)}l(&XLf( z?!K41|79J-VmB>Vv}#qdW7 zU7Y0LNtb{w6URM2Yc>j zO@C4rgAv_86u;zk9w#Y^HHsHN(T^APOL=UpI4OY$9^@s{oF{D#rMGhi36g<41&AWM zH3r-JWrHo>4NfJBEu7-_vqf1GwIa{OtUwgGMcWfjrN1w0Sl}RKm}d#px5d^D%BTWG zIvzSNR4c^~pe>RTmMf`)iFzof{zZRm-H(|%M6z-Q^nb3NOr|a z|5e1!#@VSel}9x3g?^(#L{VRkFISZNQG*C&kVBjE+zw_m=L!FE&dij)IZxjQZSb9j zANB`r{yQ7i|3hDn=bvq%m-_yx_uA?ENB`V=?L?uy*G>uTy>?2-_uA?60rXxw$)mp4 zPH}DBPutGl-@3mF+`jL1KW(Y=b$BBZV}^@lb}Bz-G&WKsYf||k zrm+r@EKlXfj>gI}-BtbGk;R<@UUbph9BJ5fpA?&o6dnRA{f^8dfPz1IDK2^ilu&Xd zO0kmu{CojYQ3zbb$4G2Y(9S%)C*B`_BUCY*$Fo~xu^1@$WoTc`x#E=52)?6lH8se& ziZbA8q8nnN+80PVx&DWC=o2!@^iKZ}S*My5zOgYx9;vQM;WL*ZBZTr+rcjd^hDzaz zl>zq=_W_){OLCWw4#0f~hCI%FKw>ro#SB1jA0THGRf64s3;``y+^xjU!r7_A;tjlt z$ZqGXERt2RU}cf4mI*KxlzefF3qXZU?9;pL0W~s zgaoZb;Ao6CR3Cv@G*pLwwC;v9)T-~{1+>-o@B#+X_weEe{_sK@JM+HRvGZ?mn&0=> zsqL9R1yRG_S$zO`(Nu@SDo{6e{uX)qu`}))a=J6kUtJ(PZJr3=aEHU?#p8t3O!+;6 zs(75inJJGyl`Crx+2CsbpBXBcU=NnAK7bPbL zHAyEpntbBE5+qK;P`Nqozbnips~sbkh(eDr!0~;FV<* zYG4lJVlF`eVMPv8D6qsCO!lZKL2W>WHAcs5A}DZDM&*u=DaIi&71NGrgCReT@M8vo z&nV#8$7y)^aWhf~$uSU>ij6Q#kD@YzWjHf{ng$wIl0jc~oW5+>0g{$ry%O|Ek}Q!I zjaE;}G|Wg*g&dwjddW`y*~}D@56AdaNPe6#8Cx@<$oX+0=&39Wy&vc`A&5S$S9(;o zuXVT)o~?Dl6pnMJVeNyA5QV3Pw_v}XTj1xS!Fy>RK!1?!quRK$=SoW}cZF*)F5GP6 zGttpSXBwUo)&>c^@TI6s9>*>gVw?gOOLIjG&f~b%qXAJ!$AzzH)|I z26-YfY%L?`i8#YhKcqDYhp7!FZM>HrAdMj{+!)fs+pxdJ9o;p|VGf9b6LVqV<_zY@c7{rBE zIi!K&!y70;KMhl-$b8D3*b5u%k%Tv@G8|`6OiC=yQWy;1*kf=vAg)llsj*BMz>|qH@m5uPo4y0eDDT<^ zPbi`SA+$o2a!*-JCN>`xrO8`f?y1PEqCXbJsSw5XYLmCoSLQ95lV6aF4D4_QW1y(6 zM3JltRV zjAP6=B#xPOGQ)B<{90!Jw3(-GUe0WnF!RmKQq3ZLEO8GTSD_dq4CZCH8}Gn&o-rcA zJdar@oX>_6%**;wP{AUXv#34HU|G)GV_CGx_B3P7%)XpTcNDYew^>vLOCi*GY#ara zWz1qZZdt?ZcM*=w)G&`lnw-m+VUW=T!x+g;#reZ96=4+rHd{%8t*GAwPi5wZVLZGI zs6~u0he~GiQQIbsCLq^(1RPP%8e|A-$k4($`Vf|mCP~I zC1yIuN#l1B4`Pm+z^oRS+fHV_Lv3&_-W|-cfZ3Z_%*`({%gYqA>|~B+7HN5wP%Q<_ zDQW?Txthg^1pY3Rx7+G25wanGbVvkwAU{2%UI2KR0 zSi0HhW|+ns&H~SgzkTz=Xt=V8N=+ynHgAYK8v-W5r7#tgPEF_ zBYK?0&tQgTmOg`7k28~TDB#9(lUaWt95)Up?Bi@m4vVr3Vx~=K#R=4k&DeNjVf@ATtuPkG!G#zzxew_#mat6C8W}Q7mVw6kFo!#dO+Pr9?~ooFXE|;h z8;AcvIy(u}Ou18a0QYEO$gEP#0i#(Ql4lh%bpkVg#1e#^vq}~VtF~0K+KE`C7ie_8D@HeZd3qmy0Zc<&A#fyo8F)J>p#{^XSIH+Ev z)|9d7vp~H%gqn>b63~(&(fZ3-=2+F=LvwMYQfg1jDPUZTUl#qK1Zqw)h9npQtc2{K zklR6j-hi-xq48jSF@9O}Q<F!u%YH~4-qPQ21n_wREC@o)y}SEf=~%qC_y z&eAZ^`?KL10fz+}XE zc}1t3$DHVtmaLsDX(NlwWaFM;12(dWpibV%TxA}5p=LS z*?{RR>I;He$&UrHmlN0sBE2%6J zb3s_ud=|5fJY*!6Bjms_p@mvuC8Jr?!_2UaTn|vK&7-bSCyH*E4d%Wh$%R(1$p|7a zQK<&iI2O5=nVXq&2kageToCUQ7fbQ^Sga2Xp1=HS_C<348o35%*`v1rM|XxC;I zb)#B@$%L-MhpO?+`d1nN>|>Z^BePX8`+;eES!BGJMUx;0#OP~UExq_WQ}kA5#aObO zjfOn1H0x>>Gn!UDSU4r~UV|QtRZ}cxW*4I?tl0>oIxL2QdBXOQq!Gfnk(o@NWAjO~VR*<}E%JJfMViXI+1WF*aWUHXnEEEXM_ z4}zF|7_bP*X0d;z9Ms7EFpGYe76Hk|$w@5Z4wif;W4JH>Z{1xR*;pumhCd4KV6#ab z%h+-X?%HHFq?@UvW$(x?ulh8CUCBu7_2f0Fr5H2>oV=Md|^5D z%$>_&FK~*YvDfo?(+{Mvo4mE&f8WGu5E@&3dE69ZVEwUF+Kk~kW(BjO6|kD323jWC z3(bYe(ladP5*B?6-$GkXeKYE2S_j3kp_t(A`3|%kKO>F}2L3+a+b?0JZN#+q5*;dv z?Ptaj2`q|k1|xV38^e;Ypf(P6aoL^)JKH7iAY(FiZ7_H}3nP7pPvGaXVWU~>v&?R? z8b=#gB$jlTlO_9DKOcrVmgZxQHO#P+4a9T`O1PFq7c?vVa(7J=!jU$ry$hD0&_zVlUyD7tl=nrOV*R!Uf@!w~Gw2oI_-J|`N zn0>TALi=$T$!J73V3|dBXBmyAeGes6e3m|z#qOc0yVE!}k=ZKPxm2Ls>cL(iO@HoSk%L+EMVOb|$)Z=# z6gJZ0TS2A-{MhA~OHe?=c{H+)t5bBo6ou$m(?vmaEd1lJ#K%bXHrYjFH7bPJ0_Fzu z*^sf!d|cg$#Lkcja~&8m<`FP&>`_KlGArM*JjY~*yZeaNw-z9nvAjl<<4$7Ral^5FFca8V#kW~CnQx0I>Oi3kYwg< zVvDhY?@ePG8HcgpVa80>tt@7baZm!Yyu{+Gnd4Uwq?VcoJHWP>ZKLp{nA1@%ZEU}UWoazj=f)RBz@lFyG`_pERbW?$6jrN5 z1iXvSR*oIU7l|EJ9Zzhg7t=t+AH(38%4)vICT7dj{uWCqtiN9*5Z`3iMmwIuTKr|2 z;?V9dDn}MdmE)Ve^T@^{jbq}O8$EsO#iWE8#z`&~c`+MIyF(YVjF4cMNDcbV!9?RA z7d^qk3jh51%!=iMaZ&;sbCHb3UCboQp@Jo)baIU1B26KY1QRQEm@FSN>qrF0v)EW- zADLy^wE<6@45pV9Hy^I<`a#W(tDDOHef?+v`jPsI0QIA2%P2V$GVEb&1U444m=jZE z^cHw%zIXf`VlIs$Asf?c+FBlniM3^#aYP(Tr`RatdAgX<25(nbQc$Sm*Hu*4c$AW+ zs`^GReg3v2e^E(Iec5FtUS)Af{=!0fK8q);JRk59PhGiEShBPrXK5b7i}LV%R$1)x zt|~3NjN`0stoC{YmS>GuDXD;)YV(cGMc zvmwfbi}GiaEQ?EK<>f3p?3v0uc7K$n$1IbmcC~XX>NJD936O=|cIjT6CiIMq2$T`X) zpI2CQNkeJ*c*5i+f_hOzDY=5TbxD0iMU%%%;5o`tZg0GCAS*tw?4xGp^DCuRbzc!y{~DcuWog9UHM2}^(FwDys+qz z4UP3)PnoyAaU>30P~T7iFrKC=6$~2!psYfdCNXmr?kb?crRb?h)z_2zFlDWWmQ|HD^5Y}&)JUN)b>RWX z_((fVHTA->gcS;t=4M2GW{&I@c!?Ng)KPaBRaIZ>8P(t^Z>+}-N$Du4;!>!hX;ei` z{c5Fs;?4k4n$$R8_ZR*oag(LRe( z!A)3n5~}t*Dg!Z5xz$9SsY@@}vXMk(S8~$D2iUj^J$&4TUev6kogy`jVjv9+mgw88 zVN{m>Y3Rth#^a#_rCKvYwVwW4XmynodG)SL`r0z1Oh8dU4RhMp* zoMXwPqmYf$a5l&=9P@rUuCEq_%_a1}vDu7rYiBlFH&h%P%oVHUYS-+J z=l3FG-BZ;T>b7{7eZ-1V)abTra^RH3myHJHC}^h@M)E-2-jXJ7586_#+Of25v=wRB zxLj_Bt%@9kwN@px9wMGMdUd%lTMHYzO>6LSv%S}9A)UQWSdLBDF7J`A$e`aSqrM^C zGSF)8k0Y+gil*)8CDYtdwG<%pyK!Bz#FmB>!QKkq77`aw(Tjr5HjDEjZJxP-y-pPc zmDa7dnmuW11HY~+CIHN(i^Wf=*-oI%R)7>nF^UH{)<&XQxS2RIvv^WVf^mQCa6Sm5 zNLr{=t*|{WDy8b2+1mQ3=-T&yu+wQqre-}zS~&zHZQZssI21_gi9GvUm8$PXB)x{X zw1>7+uEl%sED#_3eQPh(;;@9=>V~zV6CKlu>s8a9ZA)R-Y?U=_C&ak!Uh3;%7iC&= zT6-(#9<3Ai9bt0he+`%|XJm;CKj8P9S)GaJ%ycG>y$v$)<4r#kKfyekiJxc=W8$M9 za@eosFlIgaA!klDZ)M`|G8f}dVSdP&Q_M8}qU?v9S%km-`lyUbo@(-$IR37@BuoD^ zY(tZUFE&Rr@g?T5ZCU!K8#9xIpJ86CXW>iDNw;U=XPW76X5q`sOeTJosbu2sG1Cub z`N1FO`dRqdX5aoS{Jo+;1cg=@P`QrtDP`Eg3R*sIB>bIgS;pLLtggF8!c)#y}yc6a*NJ)>sA?lxq`&+BN30(Z-`#3SJn#4Z@g7I{n??mJ#>&oI4MAmj4yh*O?5r(*GsI z{jF#wiTm5xtS0Vni*qe;f9su%#Qp7kwi5Su6uO1DzcWz?Tz%&#bjN|emHMg6eQJF^1-R7D zE2#fTrbm|k%u0Wr`u=KNGMirf>k?gB|F0b52g%Iz{}JnFsrlX=Oh`gxrRN6d-26{{V)0)Cbc~8{Ncs{hiKs(vNP3qw&sA-(QDq7jd0-{#8cPA+G;) zd4Twx^#6vJ&d*ZcU+(8#;ER#|F7@>;?x()LcWIxvziH~j7FX+`e3JUhE_B#k3!MBV z@m1%$^FHzCh(E#SZ;tqj#9z%j{Vh(I$E4gBj=nek1^QCHx=D|jaR#r^&q}V>cNP8r zjkv$4&^yHarGj%PIH~{B%bedP)3b=UzZv>j#CNQ8iZnCl5kEKYaCr}qu!4ATg*(@N z>{8PM8OX2lzXogr}V_-y!~!iyhD+ zeh|3SH^03+L4ALf!^0M*aYDQZ+?Fr5Tf(UgFVl~|1k_*0_*sY!O3LwMzH)z?_2E?F zzq`QsopQp+R*QKaC&fzY>#I06WwPN?;7b-RHz)N8P+TK8V%B=8>EA>@{z6rSHev*MDw`pAioDB{FwFUD1V=R$iY~A%caL(XYEAd{w~h%CVm}XOny&4OMy#z z{QfpiedP<+Qhx<;e+#iofJ^f+mo>x_6dZ?luQzvJhO z#WhogayznD%FAD_twTT0d*wS1T+**wvgz~mF6zIHu3JLrg!uw-e=)ZE=tsAKQ$MnX ztoYZx+!ml7NO;itamUH;N9q6m6%IYbi%*Zye;&BB>$&|&FUGt?KVP}X;dk-!>%jAA zReL5IluN$7%66g8ku!+@knR2Bv^~e-qmC}4zRugYn<^h3qyI7L`%CfN44hqFDw034 zUHEJCcE(=JtppmjQ4QQMCPrK_)L3eRD-s5-J`a<`Ss+8WDOIvfb}%1F zb1cb_6al1+!GI_ja1-8;z9NvW8n7O4!P?%`e5{&uc1OfQeVEy&%l|{=^G@N8cQ)?D#L6PM4g_kTxm{3 zXF^Eb^akaXEeqri>y4%`rTfjJLv)Hj^ zoiqwNsX*ptfNx5BNbwwYvOr=8T`4|{lq-*}WI2b|gV>VM$a9SIJJJrvmKy@mQ$maE z#OVl=e4P+tqC4Oa!I3F%XQyu{gT}FXB?bocWr{0Q(k;o>X<|^(OXav5rPESE1M#51 zm6t7ZOfRW6(iS8Kq=BYMLVxPPkg7y?1S&#^lr}h@A&Y_90nRb)en|F{q$q(#X>?0z ztppdC;5>t%T*pKXmvX6wLc=2RPBW;0Ta{@$GTTKaiv+?KD;?sKthOwNJnDe6WX?!U zcJx((G_KnY%ugjb&QXe2*{7xF(OaU{<=J;iXB=_8KD6Cz%2seV8`_iAe)iR`du-jN2_!XkZ#i0Sk!~ zz=nb(?an8l*z+~=H@+82u zc3cZZkw>js*A#5^E#R z5mi{P!kIHiwKN5E@0P$V6yw=m8Jc0EjQ13tRvV?J9*47dH`t?RSZ^iPW8`4!ZR-C& zk=MZm`0#ahz*j17=`%;7n+zA?1g~ZTd*wA%=99`e9=x{^Uj>=8pT_uz1eJX4bs)a= zcZmYB%|Oy#c~X^mRiyOoZwCJNW5=3$|1usWL8Xq9;C0&uKm8$4EI&NBf8||OzQqia zG|Hjcb2!RWfk~7azw)yxkKtM}`1voi5-(*})4<()wPov>HFSEb&+ zpMJVC_u@eERQ)M0ta5_+sqy>wFXNA5zZM?}${(u~-bI4gOP=}m`+ELhsJ+f3nEs+@V~2Go2H$G0@&p(s?Mmq`efajmCky81-?ht~=0bTmC4$-~ zrI$rk`}&KV#y*b2UjQ`1N9&C~zfK0GWp54nb(lm*Un?$gjaPN0yUMb!2(gZEt7qVy Gn*RVqWF*`G diff --git a/grammar.txt b/grammar.txt index 1596ad1..8a92464 100644 --- a/grammar.txt +++ b/grammar.txt @@ -14,10 +14,10 @@ additive_expression: | additive_expression '-' multiplicative_expression ; -multiplicative_expression: - number - | number '*' multiplicative_expression - | number '/' multiplicative_expression +multiplicative_expression: prefix_expression + | multiplicative_expression '*' prefix_expression + | multiplicative_expression '/' prefix_expression + | multiplicative_expression '%' prefix_expression ; number: INTLIT_T @@ -99,17 +99,28 @@ function_call : identifier '(' expression ')' return_statement: 'return' '(' expression ')' ; -prefix_expression: primary - | '*' prefix_expression - | '%' prefix_expression +prefix_expression: postfix_expression + | '++' prefix_expression + | '--' prefix_expression + | prefix_operator prefix_expression ; -primary_expression: IDENTIFIER - | CONSTANT - | STRING_LITERAL +primary_expression: T_IDENT + | T_INTLIT + | T_STRLIT | '(' expression ')' ; postfix_expression : primary_expression | postfix_expression '[' expression ']' + | postfix_expression '(' expression ')' + | postfix_expression '++' + | postfix_expression '--' + ; +prefix_operator: '&' + | '*' + | '-' + | '~' + | '!' + ; diff --git a/src/cg.c b/src/cg.c index ecef560..51e9028 100644 --- a/src/cg.c +++ b/src/cg.c @@ -76,26 +76,52 @@ int cgloadint(int value, int type) { } // Load a value from a variable into a register. -// Return the number of the register -int cgloadglob(int id) { +// Return the number of the register. If the +// operation is pre- or post-increment/decrement, +// also perform this action. +int cgloadglob(int id, int op) { // Get a new register int r = alloc_register(); // Print out the code to initialise it switch (Gsym[id].type) { case P_CHAR: + if (op == A_PREINC) + fprintf(Outfile, "\tincb\t%s(\%%rip)\n", Gsym[id].name); + if (op == A_PREDEC) + fprintf(Outfile, "\tdecb\t%s(\%%rip)\n", Gsym[id].name); fprintf(Outfile, "\tmovzbq\t%s(%%rip), %s\n", Gsym[id].name, reglist[r]); + if (op == A_POSTINC) + fprintf(Outfile, "\tincb\t%s(\%%rip)\n", Gsym[id].name); + if (op == A_POSTDEC) + fprintf(Outfile, "\tdecb\t%s(\%%rip)\n", Gsym[id].name); break; case P_INT: - fprintf(Outfile, "\tmovzbl\t%s(\%%rip), %s\n", Gsym[id].name, + if (op == A_PREINC) + fprintf(Outfile, "\tincl\t%s(\%%rip)\n", Gsym[id].name); + if (op == A_PREDEC) + fprintf(Outfile, "\tdecl\t%s(\%%rip)\n", Gsym[id].name); + fprintf(Outfile, "\tmovslq\t%s(\%%rip), %s\n", Gsym[id].name, reglist[r]); + if (op == A_POSTINC) + fprintf(Outfile, "\tincl\t%s(\%%rip)\n", Gsym[id].name); + if (op == A_POSTDEC) + fprintf(Outfile, "\tdecl\t%s(\%%rip)\n", Gsym[id].name); break; case P_LONG: case P_CHARPTR: case P_INTPTR: case P_LONGPTR: + if (op == A_PREINC) + fprintf(Outfile, "\tincq\t%s(\%%rip)\n", Gsym[id].name); + if (op == A_PREDEC) + fprintf(Outfile, "\tdecq\t%s(\%%rip)\n", Gsym[id].name); fprintf(Outfile, "\tmovq\t%s(\%%rip), %s\n", Gsym[id].name, reglist[r]); + if (op == A_POSTINC) + fprintf(Outfile, "\tincq\t%s(\%%rip)\n", Gsym[id].name); + if (op == A_POSTDEC) + fprintf(Outfile, "\tdecq\t%s(\%%rip)\n", Gsym[id].name); break; default: fatald("Bad type in cgloadglob:", Gsym[id].type); @@ -103,7 +129,6 @@ int cgloadglob(int id) { return (r); } - // Given the label number of a global string, // load its address into a new register int cgloadglobstr(int id) { @@ -113,7 +138,6 @@ int cgloadglobstr(int id) { return (r); } - // Add two registers together and return // the number of the register with the result int cgadd(int r1, int r2) { @@ -149,6 +173,71 @@ int cgdiv(int r1, int r2) { return (r1); } +int cgand(int r1, int r2) { + fprintf(Outfile, "\tandq\t%s, %s\n", reglist[r1], reglist[r2]); + free_register(r1); + return (r2); +} + +int cgor(int r1, int r2) { + fprintf(Outfile, "\torq\t%s, %s\n", reglist[r1], reglist[r2]); + free_register(r1); + return (r2); +} + +int cgxor(int r1, int r2) { + fprintf(Outfile, "\txorq\t%s, %s\n", reglist[r1], reglist[r2]); + free_register(r1); + return (r2); +} + +int cgshl(int r1, int r2) { + fprintf(Outfile, "\tmovb\t%s, %%cl\n", breglist[r2]); + fprintf(Outfile, "\tshlq\t%%cl, %s\n", reglist[r1]); + free_register(r2); + return (r1); +} + +int cgshr(int r1, int r2) { + fprintf(Outfile, "\tmovb\t%s, %%cl\n", breglist[r2]); + fprintf(Outfile, "\tshrq\t%%cl, %s\n", reglist[r1]); + free_register(r2); + return (r1); +} + +// Negate a register's value +int cgnegate(int r) { + fprintf(Outfile, "\tnegq\t%s\n", reglist[r]); + return (r); +} + +// Invert a register's value +int cginvert(int r) { + fprintf(Outfile, "\tnotq\t%s\n", reglist[r]); + return (r); +} + +// Logically negate a register's value +int cglognot(int r) { + fprintf(Outfile, "\ttest\t%s, %s\n", reglist[r], reglist[r]); + fprintf(Outfile, "\tsete\t%s\n", breglist[r]); + fprintf(Outfile, "\tmovzbq\t%s, %s\n", breglist[r], reglist[r]); + return (r); +} + +// Convert an integer value to a boolean value. Jump if +// it's an IF or WHILE operation +int cgboolean(int r, int op, int label) { + fprintf(Outfile, "\ttest\t%s, %s\n", reglist[r], reglist[r]); + if (op == A_IF || op == A_WHILE) + fprintf(Outfile, "\tje\tL%d\n", label); + else { + fprintf(Outfile, "\tsetnz\t%s\n", breglist[r]); + fprintf(Outfile, "\tmovzbq\t%s, %s\n", breglist[r], reglist[r]); + } + return (r); +} + // Call a function with one argument from the given register // Return the register with the result int cgcall(int r, int id) { @@ -164,7 +253,7 @@ int cgcall(int r, int id) { // Shift a register left by a constant int cgshlconst(int r, int val) { fprintf(Outfile, "\tsalq\t$%d, %s\n", val, reglist[r]); - return(r); + return (r); } // Store a register's value into a variable @@ -214,28 +303,33 @@ void cgglobsym(int id) { fprintf(Outfile, "%s:", Gsym[id].name); // Generate the space - for (int i=0; i < Gsym[id].size; i++) { - switch(typesize) { - case 1: fprintf(Outfile, "\t.byte\t0\n"); break; - case 4: fprintf(Outfile, "\t.long\t0\n"); break; - case 8: fprintf(Outfile, "\t.quad\t0\n"); break; - default: fatald("Unknown typesize in cgglobsym: ", typesize); + for (int i = 0; i < Gsym[id].size; i++) { + switch (typesize) { + case 1: + fprintf(Outfile, "\t.byte\t0\n"); + break; + case 4: + fprintf(Outfile, "\t.long\t0\n"); + break; + case 8: + fprintf(Outfile, "\t.quad\t0\n"); + break; + default: + fatald("Unknown typesize in cgglobsym: ", typesize); } } } - // Generate a global string and its start label void cgglobstr(int l, char *strvalue) { char *cptr; cglabel(l); - for (cptr= strvalue; *cptr; cptr++) { + for (cptr = strvalue; *cptr; cptr++) { fprintf(Outfile, "\t.byte\t%d\n", *cptr); } fprintf(Outfile, "\t.byte\t0\n"); } - // List of comparison instructions, // in AST order: A_EQ, A_NE, A_LT, A_GT, A_LE, A_GE static char *cmplist[] = @@ -327,7 +421,7 @@ int cgderef(int r, int type) { fprintf(Outfile, "\tmovzbq\t(%s), %s\n", reglist[r], reglist[r]); break; case P_INTPTR: - fprintf(Outfile, "\tmovq\t(%s), %s\n", reglist[r], reglist[r]); + fprintf(Outfile, "\tmovslq\t(%s), %s\n", reglist[r], reglist[r]); break; case P_LONGPTR: fprintf(Outfile, "\tmovq\t(%s), %s\n", reglist[r], reglist[r]); diff --git a/src/expr.c b/src/expr.c index aa15cdc..4abb849 100644 --- a/src/expr.c +++ b/src/expr.c @@ -72,6 +72,52 @@ static AST_T *array_access(void) } +// Parse a postfix expression and return +// an AST node representing it. The +// identifier is already in Text. +static AST_T *postfix(void) +{ + AST_T *n; + int id; + + // Scan in the next token to see if we have postfix expression + scan(&Token); + + // Function call + if (Token.token == T_LPAREN) + return (funccall()); + + // An array reference + if (Token.token == T_LBRACKET) + return (array_access()); + + // A variable. Check that the variable exists. + id = findglob(Text); + if (id == -1 || Gsym[id].stype != S_VARIABLE) + fatals("Unknown variable", Text); + + switch (Token.token) + { + // Post-increment: skip over the token + case T_INC: + scan(&Token); + n = mkastleaf(A_POSTINC, Gsym[id].type, id); + break; + + // Post-decrement: skip over the token + case T_DEC: + scan(&Token); + n = mkastleaf(A_POSTDEC, Gsym[id].type, id); + break; + + // Just a variable reference + default: n = mkastleaf(A_IDENT, Gsym[id].type, id); + } + return (n); +} + + + // Parse a primary factor and return an // AST node representing it. static AST_T *primary(void) { @@ -96,29 +142,7 @@ static AST_T *primary(void) { break; case T_IDENT: - // This could be a variable or a function call. - // Scan in the next token to find out - scan(&Token); - - // It's a '(', so a function call - if (Token.token == T_LPAREN) - return (funccall()); - - // It's a '[', so an array reference - if (Token.token == T_LBRACKET) - return (array_access()); - - // Not a function call, so reject the new token - reject_token(&Token); - - // Check that the variable exists. XXX Add structural type test - id = findglob(Text); - if (id == -1 || Gsym[id].stype != S_VARIABLE) - fatals("Unknown variable", Text); - - // Make a leaf AST node for it - n = mkastleaf(A_IDENT, Gsym[id].type, id); - break; + return (postfix()); case T_LPAREN: // Beginning of a parenthesised expression, skip the '('. @@ -141,7 +165,7 @@ static AST_T *primary(void) { // Convert a binary operator token into a binary AST operation. // We rely on a 1:1 mapping from token to AST operation static int binastop(int tokentype) { - if (tokentype > T_EOF && tokentype < T_INTLIT) + if (tokentype > T_EOF && tokentype <= T_SLASH) return (tokentype); fatald("Syntax error, token", tokentype); return (0); // Keep -Wall happy @@ -158,18 +182,20 @@ static int rightassoc(int tokentype) { // Operator precedence for each token. Must // match up with the order of tokens in defs.h static int OpPrec[] = { - 0, 10, // T_EOF, T_ASSIGN - 20, 20, // T_PLUS, T_MINUS - 30, 30, // T_STAR, T_SLASH - 40, 40, // T_EQ, T_NE - 50, 50, 50, 50 // T_LT, T_GT, T_LE, T_GE + 0, 10, 20, 30, // T_EOF, T_ASSIGN, T_LOGOR, T_LOGAND, + 40, 50, 60, // T_OR, T_XOR, T_AMPER, + 70, 70, // T_EQ, T_NE, + 80, 80, 80, 80, // T_LT, T_GT, T_LE, T_GE, + 90, 90, // T_LSHIFT, T_RSHIFT, + 100, 100, // T_PLUS, T_MINUS + 110, 110, // T_STAR, T_SLASH }; // Check that we have a binary operator and // return its precedence. static int op_precedence(int tokentype) { int prec; - if (tokentype >= T_VOID) + if (tokentype > T_SLASH) fatald("Token with no precedence in op_precedence:", tokentype); prec = OpPrec[tokentype]; if (prec == 0) @@ -212,6 +238,73 @@ AST_T *prefix(void) { // Prepend an A_DEREF operation to the tree tree = mkastunary(A_DEREF, value_at(tree->type), tree, 0); break; + + case T_MINUS: + // Get the next token and parse it + // recursively as a prefix expression + scan(&Token); + tree = prefix(); + + // Prepend a A_NEGATE operation to the tree and + // make the child an rvalue. Because chars are unsigned, + // also widen this to int so that it's signed + tree->rvalue = 1; + tree = modify_type(tree, P_INT, 0); + tree = mkastunary(A_NEGATE, tree->type, tree, 0); + break; + + case T_INVERT: + // Get the next token and parse it + // recursively as a prefix expression + scan(&Token); + tree = prefix(); + + // Prepend a A_INVERT operation to the tree and + // make the child an rvalue. + tree->rvalue = 1; + tree = mkastunary(A_INVERT, tree->type, tree, 0); + break; + + case T_LOGNOT: + // Get the next token and parse it + // recursively as a prefix expression + scan(&Token); + tree = prefix(); + + // Prepend a A_LOGNOT operation to the tree and + // make the child an rvalue. + tree->rvalue = 1; + tree = mkastunary(A_LOGNOT, tree->type, tree, 0); + break; + + case T_INC: + // Get the next token and parse it + // recursively as a prefix expression + scan(&Token); + tree = prefix(); + + // For now, ensure it's an identifier + if (tree->op != A_IDENT) + fatal("++ operator must be followed by an identifier"); + + // Prepend an A_PREINC operation to the tree + tree = mkastunary(A_PREINC, tree->type, tree, 0); + break; + + case T_DEC: + // Get the next token and parse it + // recursively as a prefix expression + scan(&Token); + tree = prefix(); + + // For now, ensure it's an identifier + if (tree->op != A_IDENT) + fatal("-- operator must be followed by an identifier"); + + // Prepend an A_PREDEC operation to the tree + tree = mkastunary(A_PREDEC, tree->type, tree, 0); + break; + default: tree = primary(); } diff --git a/src/gen.c b/src/gen.c index 45dcc2a..c2dfe82 100644 --- a/src/gen.c +++ b/src/gen.c @@ -117,10 +117,17 @@ int genAST(AST_T *n, int label, int parentASTop) { rightreg = genAST(n->right, NOLABEL, n->op); switch (n->op) { - case A_ADD: return (cgadd(leftreg, rightreg)); + case A_ADD: return (cgadd(leftreg, rightreg)); case A_SUBTRACT: return (cgsub(leftreg, rightreg)); case A_MULTIPLY: return (cgmul(leftreg, rightreg)); - case A_DIVIDE: return (cgdiv(leftreg, rightreg)); + case A_DIVIDE: return (cgdiv(leftreg, rightreg)); + + case A_AND: return (cgand(leftreg, rightreg)); + case A_OR: return (cgor(leftreg, rightreg)); + case A_XOR: return (cgxor(leftreg, rightreg)); + case A_LSHIFT: return (cgshl(leftreg, rightreg)); + case A_RSHIFT: return (cgshr(leftreg, rightreg)); + case A_EQ: case A_NE: case A_LT: @@ -131,9 +138,9 @@ int genAST(AST_T *n, int label, int parentASTop) { // a compare followed by a jump. Otherwise, compare registers // and set one to 1 or 0 based on the comparison. if (parentASTop == A_IF || parentASTop == A_WHILE) - return (cgcompare_and_jump(n->op, leftreg, rightreg, label)); + return (cgcompare_and_jump(n->op, leftreg, rightreg, label)); else - return (cgcompare_and_set(n->op, leftreg, rightreg)); + return (cgcompare_and_set(n->op, leftreg, rightreg)); case A_INTLIT: return (cgloadint(n->v.intvalue, n->type)); case A_STRLIT: @@ -142,14 +149,14 @@ int genAST(AST_T *n, int label, int parentASTop) { // Load our value if we are an rvalue // or we are being dereferenced if (n->rvalue || parentASTop== A_DEREF) - return (cgloadglob(n->v.id)); + return (cgloadglob(n->v.id, n->op)); else return (NOREG); case A_ASSIGN: // Are we assigning to an identifier or through a pointer? switch (n->right->op) { case A_IDENT: return (cgstorglob(leftreg, n->right->v.id)); - case A_DEREF: return (cgstorderef(leftreg, rightreg, n->right->type)); + case A_DEREF: return (cgstorderef(leftreg, rightreg, n->right->type)); default: fatald("Can't A_ASSIGN in genAST(), op", n->op); } case A_WIDEN: @@ -182,6 +189,31 @@ int genAST(AST_T *n, int label, int parentASTop) { rightreg= cgloadint(n->v.size, P_INT); return (cgmul(leftreg, rightreg)); } + case A_POSTINC: + // Load the variable's value into a register, + // then increment it + return (cgloadglob(n->v.id, n->op)); + case A_POSTDEC: + // Load the variable's value into a register, + // then decrement it + return (cgloadglob(n->v.id, n->op)); + case A_PREINC: + // Load and increment the variable's value into a register + return (cgloadglob(n->left->v.id, n->op)); + case A_PREDEC: + // Load and decrement the variable's value into a register + return (cgloadglob(n->left->v.id, n->op)); + case A_NEGATE: + return (cgnegate(leftreg)); + case A_INVERT: + return (cginvert(leftreg)); + case A_LOGNOT: + return (cglognot(leftreg)); + case A_TOBOOL: + // If the parent AST node is an A_IF or A_WHILE, generate + // a compare followed by a jump. Otherwise, set the register + // to 0 or 1 based on it's zeroeness or non-zeroeness + return (cgboolean(leftreg, parentASTop, label)); default: fatald("Unknown AST operator", n->op); } diff --git a/src/include/decl.h b/src/include/decl.h index 0ed57cb..ff7344d 100644 --- a/src/include/decl.h +++ b/src/include/decl.h @@ -33,7 +33,7 @@ void cgpostamble(); void cgfuncpreamble(int id); void cgfuncpostamble(int id); int cgloadint(int value, int type); -int cgloadglob(int id); +int cgloadglob(int id, int op); int cgloadglobstr(int id); int cgadd(int r1, int r2); int cgsub(int r1, int r2); @@ -54,6 +54,15 @@ void cgreturn(int reg, int id); int cgaddress(int id); int cgderef(int r, int type); int cgstorderef(int r1, int r2, int type); +int cgnegate(int r); +int cginvert(int r); +int cglognot(int r); +int cgboolean(int r, int op, int label); +int cgand(int r1, int r2); +int cgor(int r1, int r2); +int cgxor(int r1, int r2); +int cgshl(int r1, int r2); +int cgshr(int r1, int r2); // expr.c AST_T *binexpr(int ptp); diff --git a/src/include/defs.h b/src/include/defs.h index 1d6d26a..a9e8bd4 100644 --- a/src/include/defs.h +++ b/src/include/defs.h @@ -11,20 +11,28 @@ // Token types enum { T_EOF, - // Operators - T_ASSIGN, - T_PLUS, T_MINUS, - T_STAR, T_SLASH, - T_EQ, T_NE, - T_LT, T_GT, T_LE, T_GE, + + // Binary Operators + T_ASSIGN, T_LOGOR, T_LOGAND, // '=', 'or', 'and', + T_OR, T_XOR, T_AMPER, // '|', '^', '&', + T_EQ, T_NE, // '==', '!=', + T_LT, T_GT, T_LE, T_GE, // '<', '>', '<=', '>=', + T_LSHIFT, T_RSHIFT, // '<<', '>>', + T_PLUS, T_MINUS, T_STAR, T_SLASH, // '+', '-', '*', '/', + + // Other operators + T_INC, T_DEC, T_INVERT, T_LOGNOT, // '++', '--', '~', 'not', + // Type keywords - T_VOID, T_CHAR, T_INT, T_LONG, + T_VOID, T_CHAR, T_INT, T_LONG, // 'void', 'char', 'int', 'long', + + // Other keywords + T_IF, T_ELSE, T_WHILE, T_FOR, T_RETURN, // 'if', 'else', 'while', 'for', 'return', + // Structural tokens T_INTLIT, T_STRLIT, T_SEMI, T_IDENT, - T_LBRACE, T_RBRACE, T_LPAREN, T_RPAREN, - T_LBRACKET, T_RBRACKET, T_AMPER, T_LOGAND, - // Other keywords - T_IF, T_ELSE, T_WHILE, T_FOR, T_RETURN + T_LBRACE, T_RBRACE, T_LPAREN, T_RPAREN, // '{', '}', '(', ')', + T_LBRACKET, T_RBRACKET // '[', ']' }; // Token structure @@ -36,11 +44,14 @@ typedef struct token { // AST node types. The first few line up // with the related tokens enum { - A_ASSIGN= 1, A_ADD, A_SUBTRACT, A_MULTIPLY, A_DIVIDE, - A_EQ, A_NE, A_LT, A_GT, A_LE, A_GE, + A_ASSIGN= 1, A_LOGOR, A_LOGAND, A_OR, A_XOR, A_AND, + A_EQ, A_NE, A_LT, A_GT, A_LE, A_GE, A_LSHIFT, A_RSHIFT, + A_ADD, A_SUBTRACT, A_MULTIPLY, A_DIVIDE, A_INTLIT, A_STRLIT, A_IDENT, A_GLUE, A_IF, A_WHILE, A_FUNCTION, A_WIDEN, A_RETURN, - A_FUNCCALL, A_DEREF, A_ADDR, A_SCALE + A_FUNCCALL, A_DEREF, A_ADDR, A_SCALE, + A_PREINC, A_PREDEC, A_POSTINC, A_POSTDEC, + A_NEGATE, A_INVERT, A_LOGNOT, A_TOBOOL }; // Primitive types diff --git a/src/scan.c b/src/scan.c index a747576..7fbe925 100644 --- a/src/scan.c +++ b/src/scan.c @@ -153,39 +153,51 @@ static int scanident(int c, char *buf, int lim) { // to waste time strcmp()ing against all the keywords. static int keyword(char *s) { switch (*s) { + case 'a': + if (!strcmp(s, "and")) + return (T_LOGAND); + break; case 'c': if (!strcmp(s, "char")) - return (T_CHAR); + return (T_CHAR); break; case 'e': if (!strcmp(s, "else")) - return (T_ELSE); + return (T_ELSE); break; case 'f': if (!strcmp(s, "for")) - return (T_FOR); + return (T_FOR); break; case 'i': if (!strcmp(s, "if")) - return (T_IF); + return (T_IF); if (!strcmp(s, "int")) - return (T_INT); + return (T_INT); break; case 'l': if (!strcmp(s, "long")) - return (T_LONG); + return (T_LONG); + break; + case 'n': + if (!strcmp(s, "not")) + return (T_LOGNOT); + break; + case 'o': + if (!strcmp(s, "or")) + return (T_LOGOR); break; case 'r': if (!strcmp(s, "return")) - return (T_RETURN); + return (T_RETURN); break; case 'w': if (!strcmp(s, "while")) - return (T_WHILE); + return (T_WHILE); break; case 'v': if (!strcmp(s, "void")) - return (T_VOID); + return (T_VOID); break; } return (0); @@ -219,8 +231,8 @@ int scan(token_T *t) { // the input character switch (c) { case EOF: t->token = T_EOF; return (0); - case '+': t->token = T_PLUS; break; - case '-': t->token = T_MINUS; break; + case '+': if ((c = next()) == '+') { t->token = T_INC; } else { putback(c); t->token = T_PLUS; } break; + case '-': if ((c = next()) == '-') {t->token = T_DEC; } else { putback(c); t->token = T_MINUS; } break; case '*': t->token = T_STAR; break; case '/': t->token = T_SLASH; break; case ';': t->token = T_SEMI; break; @@ -230,11 +242,31 @@ int scan(token_T *t) { case ')': t->token = T_RPAREN; break; case '[': t->token = T_LBRACKET; break; case ']': t->token = T_RBRACKET; break; + case '~': t->token = T_INVERT; break; + case '&': t->token = T_AMPER; break; + case '^': t->token = T_XOR; break; + case '|': t->token = T_OR; break; case '=': if ((c = next()) == '=') { t->token = T_EQ; } else { putback(c); t->token = T_ASSIGN; } break; case '!': if ((c = next()) == '=') { t->token = T_NE; } else { fatalc("Unrecognised character", c); } break; - case '<': if ((c = next()) == '=') { t->token = T_LE; } else { putback(c); t->token = T_LT; } break; - case '>': if ((c = next()) == '=') { t->token = T_GE; } else { putback(c); t->token = T_GT; } break; - case '&': if ((c = next()) == '&') { t->token = T_LOGAND; } else { putback(c); t->token = T_AMPER; } break; + case '<': + if ((c = next()) == '=') { + t->token = T_LE; + } else if (c == '<') { + t->token = T_LSHIFT; + } else { + putback(c); t->token = T_LT; + } + break; + case '>': + if ((c = next()) == '=') { + t->token = T_GE; + } else if (c == '>') { + t->token = T_RSHIFT; + } else { + putback(c); + t->token = T_GT; + } + break; case '\'': // If it's a quote, scan in the // literal character value and diff --git a/src/stmt.c b/src/stmt.c index d372f4c..53cd5a7 100644 --- a/src/stmt.c +++ b/src/stmt.c @@ -23,7 +23,7 @@ static AST_T *if_statement(void) { // the tree's operation is a comparison. condAST = binexpr(0); if (condAST->op < A_EQ || condAST->op > A_GE) - fatal("Bad comparison operator"); + condAST = mkastunary(A_TOBOOL, condAST->type, condAST, 0); rparen(); // Get the AST for the compound statement @@ -53,7 +53,7 @@ static AST_T *while_statement(void) { // the tree's operation is a comparison. condAST = binexpr(0); if (condAST->op < A_EQ || condAST->op > A_GE) - fatal("Bad comparison operator"); + condAST = mkastunary(A_TOBOOL, condAST->type, condAST, 0); rparen(); // Get the AST for the compound statement @@ -81,7 +81,7 @@ static AST_T *for_statement(void) { // Get the condition and the ';' condAST = binexpr(0); if (condAST->op < A_EQ || condAST->op > A_GE) - fatal("Bad comparison operator"); + condAST = mkastunary(A_TOBOOL, condAST->type, condAST, 0); semi(); // Get the post_op statement and the ')' @@ -185,9 +185,9 @@ AST_T *compound_statement(void) { // new tree together if (tree != NULL) { if (left == NULL) - left = tree; + left = tree; else - left = mkastnode(A_GLUE, P_NONE, left, NULL, tree, 0); + left = mkastnode(A_GLUE, P_NONE, left, NULL, tree, 0); } // When we hit a right curly bracket, diff --git a/tests/input22.flow b/tests/input22.flow new file mode 100644 index 0000000..e7e3f34 --- /dev/null +++ b/tests/input22.flow @@ -0,0 +1,26 @@ +char a; char b; char c; +int d; int e; int f; +long g; long h; long i; + + +int main() { + b = 5; + c= 7; + a = b + c++; printint(a); + e = 5; + f = 7; + d = e + f++; printint(d); + h = 5; + i = 7; + g = h + i++; printint(g); + a = b-- + c; printint(a); + d = e-- + f; printint(d); + g = h-- + i; printint(g); + a = ++b + c; printint(a); + d = ++e + f; printint(d); + g = ++h + i; printint(g); + a = b * --c; printint(a); + d = e * --f; printint(d); + g = h * --i; printint(g); + return(0); +} diff --git a/tests/input23.flow b/tests/input23.flow new file mode 100644 index 0000000..31bd394 --- /dev/null +++ b/tests/input23.flow @@ -0,0 +1,28 @@ +char *str; +int x; + +int main() { + x = -23; + printint(x); + printint(-10 * -10); + + x = 1; + x = ~x; + printint(x); + + x = 2 > 5; + printint(x); + x = not x; + printint(x); + x = not x; + printint(x); + + x = 13; if (x) { printint(13); } + x = 0; if (not x) { printint(14); } + + for (str= "Hello world\n"; *str; str++) { + printchar(*str); + } + + return(0); +} diff --git a/tests/input24.flow b/tests/input24.flow new file mode 100644 index 0000000..e8b4b69 --- /dev/null +++ b/tests/input24.flow @@ -0,0 +1,16 @@ +int a; +int b; +int c; + +int main() { + a = 42; + b= 19; + + printint(a & b); + printint(a | b); + printint(a ^ b); + printint(1 << 3); + printint(63 >> 3); + return(0); +} + diff --git a/tests/results/out.input22.flow b/tests/results/out.input22.flow new file mode 100644 index 0000000..6086532 --- /dev/null +++ b/tests/results/out.input22.flow @@ -0,0 +1,12 @@ +12 +12 +12 +13 +13 +13 +13 +13 +13 +35 +35 +35 diff --git a/tests/results/out.input23.flow b/tests/results/out.input23.flow new file mode 100644 index 0000000..90ae7ff --- /dev/null +++ b/tests/results/out.input23.flow @@ -0,0 +1,9 @@ +-23 +100 +-2 +0 +1 +0 +13 +14 +Hello world diff --git a/tests/results/out.input24.flow b/tests/results/out.input24.flow new file mode 100644 index 0000000..993b6df --- /dev/null +++ b/tests/results/out.input24.flow @@ -0,0 +1,5 @@ +2 +59 +57 +8 +7