From f880a7770108bcfdfe29f0f4b89f8544ac490efa Mon Sep 17 00:00:00 2001 From: Brendan Hansen Date: Thu, 11 Jun 2020 11:04:12 -0500 Subject: [PATCH] Progress on basic WASM code generation --- onyx | Bin 114752 -> 126664 bytes progs/minimal.onyx | 10 +- src/onyxparser.c | 2 +- src/onyxutils.c | 4 + src/onyxwasm.c | 379 +++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 390 insertions(+), 5 deletions(-) diff --git a/onyx b/onyx index 6effde6758ecb7c3e7c9778864efb32b9e3bbddb..1be388ef9e86b7705ff8d8bc501ddb7d0dcf39f9 100755 GIT binary patch delta 48847 zcmcG1349dQ(r%=O;ye(%0Fzu)Oor%s)!I(7C_ zozBrk&J&+HS7j=$Zz>vn=G|B(@z0DUO{8T+Aq4Ig>EQT8rofxAwVVT4)t`#|>hEuk zT~3iccnin+aydH6AiZvoUjJU-Di2R>@~WT=j>B0kNeU0q8!7$F!ZmXA2b7+%X=Bvf zafdp4Cx<^ZyyDJnTYg?!(yFRj2@UZYLR^Bml$|PoD?#`RDFVOwiik~mGkr7&A7a?) zL=e7?fj@2Fy(Xh9BjapPfm{QBAqd~yz*h(1dl~pELHI%gfBj~>S1K|xq^mdAY_NfM z1>uJqcr6G&%D~43;U^k+PY`}8R^b;ArMxg@+-W7yD zWZ<vml*h?LHJSwe)XM^ySz;pk*5R~zh zQJ^{qzumxJ3BvC)@YjRzFB^F2n&?ZWrH>nU*EM7On;GvJ8Cp<*4-I@=5dNHj_XOcT zGw}IA_}>it$N=6Le|{rlZXiQw9I{u$tAg;M27Yr8KEl8s4Z=qm__IOyT3#dLN>D~! z1Mm9zX454acux>M#lTMw!si-%*9YUP1Yhswpp4;0#_k~eECYWq2!FqUKN^HzZ{SY^ z;a@TErv=^{7=9la8E1nETsQC+g7De0mw%}J;@G%zr8VkNw)w`=+iFnu(?tMp+@|PW*rT9_iJ(2P*UGU?V{xPMg9WR~c^m~-1_PcbH(4i($A}qocBIq?K3E9dwo`|{4#srxAhe%^<13Ms`LB$_LO?^ z+xi z8|1fiXIhhpcO_|s68T)7e}(;}clF$~#jb$^Bniz}OV6$!TlHyLUs*2Go1~}759kH_ zoW;*I{5-C7->ON-vB{F8XSIs2daYGISw5oIy5(rZy^>TGqU5j1FRwNIUj55kUY4KNH?|po z=kINPln?9Qww)#)tQy>IO^Cctzjj-j)cug%Ht+iEQ1r2MBra>H?UnqpqU-sk1s;O+ z4HJ{}$sN-oX4LS0XGYc9jsq2WkAAJwXl39qePHKe<=tUbdpaLcV(&uLMqu2cYFnpp z)t22=wK%VzoOZsLI@Ii5V0$*dtbjzF$S=!{dyxhqS-s00`n7IP#iC+|b-`iDoy=j_ zWPM9_ue?=nnBP|UAzL4t|CI7hjy`lqYUr*)qOgZ;)m!xFr99VPU)19xrE{S^sOM;T zi+-f%LFIgwKBw0ld9(g~ulmYo-Kt`Gx0b^uNYX(_m8$!;(+BiPt4Vv>=}Y>oY|#=k zNy&nJ(!waT&CKy8^}M!{bUg0_mAqUFIYRDgT#S^d0?D1_jb@;6^8)$MyhvFVM&H&IA}d63AIY1@g{7k29tom4VFpx9AxK zE#)8ep#^p25A-<&tqTHqms@kq(RU0BEk`FI(UHp*aChl&d5o#$OBUJ}NeSv-(jR{R zr9%Bi!L1!;#g*mlD=&~?adh`wPw9t5u;qr|Z(u|l{DcL`M3fcn6I3O7;qA@k0)5%- z?ZQ79ZA#qVN`Lcqk7s`XQQC^jqEXSsO%+b+VTD<8rQWu%L3q~yX{}cJUU1_j2#Z|q zz^E$AyJ6{ab1|6AE;oe+7I(RF`=U`;l0L%9h;dXx@S6f&NbpMnUQBS6fR_;btbmsi zyw-rdlz2!am}!ZC?<4#@0$xDyWC1h%2n)WyfaeiScLB2!w+i@P!Z#D}T!Paq^mUxr zWT6I36ecp}6OrG+HDkfo1k8djTHsGC@H-ax6$^Yoz-*yy0$xu1pA_(eqagp1E)o@# zv0T8b37#+D#|WM#;B^F#5%ALl4;1ibf_n*g2f-Z$yp!M-0^UV%hJbeyoItR*+`fkr zks@Os!8QROB=|QwTjF_wFAMl3fIAu z{!zeOy9@XL!M6%{Kf%oeTt#r2fcK1o{7ZF2f;&i^FIr&BQjWUn1ESpKkWp{MKfI!FprLl z0_NfLiGX?d;lxJtJX~K9@N1(`;{yWb8E~6`-{txLNs;)7h;#veO7L<4e+BsRLU8B?9=(BMJG!8yjrs0RcxgWk)~yNr?JCu z(J>xJPLa?T71i4ifY@h$y0 zzw|ett8Zy%N||264GeHBDDNqk=4<(5Ud}&uAtYbEl7Ac}L47>eB~1WuTvF(n>&hjp zI74`_8?L^bhJ#CWepw&rjuS@d+q9)SCy0Q?rV&K>B@3#h*&m9!(q-OX*5!X!*TO`w z`PX%AFOCAx>VH*N%;u;oT{x`5JxcbFPD6*iQiL;oe#v*J?gE_9W?wtjx0PHEnN?VFJ!)3M<>rP#u*J;-JsadCZX_)&Q6_q^wb3w`NIA4Moyx6Q-s(2E zOuDIQa?v|Zpm!Wa@4!KU&!E+|lI!7-%Wud1)=kIIuSeFL3C;qx9z!*1QrE23c-+&j z_}Ot-2I}z9H(6`yUze46Z)dmS+|a09&4+ zMTBg5W&;6a%jqLw%i6-0Cx){vzeZGD{Gu>e_rEaa`#Aaj3u7J>S^sRS|D7#E;{L5I ze`vv$_`kE|8M0*+9b~va{Aad2i_0gr<=KSGB;KNW+hhK% zbsuf^e`VchRJyF_0$G>OQLrxWJ;qW;5_=DfT6Bw=%jcTC$3EP6(%$21vMd!#tXEU) zzpZZ>RQoq0dUn(QxV~jYUkCOcea*dx2NlQOW7VY=)X-(L>fh9A4S>GH)72 z4Yd^-?R9Lh?i*;{#D0~V_4C$ybEF!%S&;iPir}dFO=nmV3R&Of#AR(pB+wR zY4dQ2W=0EL+)Z>e`JO?oq|4p_jcfMJG_#3DA(|l;ntnI)$psDOAnEcgHTV!OW_OJF zfR4n7cITI40!Y_vCy-b{NXP1bu3ojJdPX+Z45}X6#H^i3Mw-`X|fDy&9TXsNUH?^$dK7Q9DyM@d?z9k%O;u_0CfD=ny&P1l$z)V{k-1oi887 z?wFq^EVt@Yi$EEol;)i;S#VyCT)IaX=4k$ZxBlefnD%dmSEEL3en|PBhnMC2Jf5mm zMC%Xc!`#3rL<|5A20%6X{{@^I&cc`o=;XKpppJ?JZ_zK1m5nX>?-+wf0#&orazZQy z7mRKAKj+`P4eu85Z>yT!kgEzVTvfsCf8K^;dcrJ1?slrH2X)oo?Vs)a^?nkzY%U)m zmXW6)+Gk=IFFL+#EK;DCF5ik;Edn0H`*?MO@BRMLWBFyG4Ec;oS5xuQlPk0mE<;`< zBBu+6MYv#CB+Y*DpXpzh+U1vdO_9v{)OUXWie==K|7Y^Z=T=k33eCuR9o1Pj(a;dM zVlD-l<+ajKr@$F{Q#QNpo7_wy86!sr7l&<9rNhl&&RM#Y}kv%7>! zR(|^M;xxy}hQvtEE{<0g@6w+x&d}!!iVqvn*IdWm(AN%1k}v9q2c>vtL6x%A^n~Ee zG%=KSh!0TSN!zJ%Ea_<5CfxqB_XaG0VOu_Xx6uHHXlf<0XD)(Od516hn9>>$4_e7e z^VVE$253zgU-Yd(M>*cN`s8Qm@wmMs!N&rHexiL%N!}WCQgPKl(*-RR2Wg1Y09r%0 zc$e)5sjX=GY@4@c#?yMl;0DUw+p1a(ejIN~{HDJ#>}f_ikuQ9nLx6;y*Dv#R6IJK2XR2NpSyxfqc~xge7b=Y|V*9`p z&5q~&%yllepEGd@z|r!78_`pp^#SAdx>J#5x<+ev)?>%_SKfM3pEQ1j(*H^Q+W57~ zuTSW!CL}5o*6F(@+^QUYLjP_;BW2wadfdciit`Em$%%uM?UnlP6Nf5&E0Idm=TB-~ z|Jqu=U)-4)cXrqwTxUaI4kfczM^#pRFloD@q&-$uG9^J)9BcITcMVat`1C*S`cQfI zQKT~UKc==&W<3f_UA@<|SC!SP^{DAhm1TG8ou`lX+nk@>3uvk^-YK~|r^>viUyb5~-QZf31&R`usx&7pjAzpi;} zD+}+}GrjjKbMCL&?QJD19hX&IT+~xhx-8LKl+09qSgda@xuG0gq;FctCm`b)T zYooiDO;djJ>fU7^C?0Rs9rvrU61z|zz5G#S`+}<9myfq8vl8{uW%otxSwVewSvHLZ z)a68}{$tr>W$7k;=!28nrEK8L=|<-Er-*2ogiA6M8A%a}e1r~!o*HXGC2rK^@;af8 zO+?t?tpq)#JX_hEp!YAIsPstCUnoyinkDF8ly_Htiq{*hY^0ow*Y8-Fs%(wd?_Jqj z85ysiSec>Z$Lm*D<||6Pe(OWimB;JqJ02PkHTp>wZt8pgGCg`#gN{>XQ|}nxG%^`e zCVtlsjabpMA{lcRcR*H?H*iHzRz4K=^+Z9(uy>KZ>vsL(8NYg>0zFjHRyI;S8n!Fy} zYT&%y{h3S8qCU)~OTWHdN06kXQT|m9xa-KO((8NkJc?2_C=M*vGoI3 zgJMLR5&cOqvjoybzC}yr4By-`IXTHJJR+yHL1%CyM3FD8RL-~yoca&wSI9~ceIU`z zn$yjiL(-URL>p7MNanQWv`K4Z2a-9heOJrmSZ|-aKK%*@jp*NFFiSO(-3$8-G})n5 z`m+H^qdKzRWdnKkWh@&z7nk*~Z|PV`bDug2zpxd7EbFegYbC#W}9mZ0tdNc48b zaV4k;jIw}?vVe@TBvF(Fbh}ZQkO2#H=^ZdomjMB=pkG0kzQWcJ->IwUbpZPpbvCWo zr>M8@?d5W^?+{Fu)=7*pvU$Hklccx??4RG;*SAbg^~IFRakraNp^7OLphYTDrc{8Y zRDh6b8o6taI|9b^eYsrD^qNY5&X5eqRD$^A2MYJkFANk0zECs;^{m2v0|HclxiVz% zPMvvF5!g4cJ1Ie6m%JWKO|Z8crkDWzfWo4_T}-mRd7TRLMDHca{ieRIjj26}< z(5NSYsHe%MPY<4Yn4nX!iS5#_U{L=a-TQhOfhw4)0yI?x7*G{(jiyM{Xvzg@G(|F? zDPU7mLK~U_G&ODAa(F;hLK~_QXs8O%RFyQPzS6C*U!M`M`b}vz#Xn(+d`A|^nQ{-` zqEfk*Z$zo=_LY>#>At~BWREX%nVjjnQX;1%QDNqap<&uXNI^z_-=tDd?_41}`l9`y zkg0$%6ip1cmgn0~m@%q#$G=v_;56xE)~_!X$**2#XQQ5gtRJz0n?o7ZBb+@P2^D7YN@Y z{2jrLO;!{_B0@uiRtTLC`XCHK7>95-!UBX+gw+Te5OyFOLU;|~U4%~&E+PDa@F#*3 z9alrBi;#-Y7@_48ey_g+fNlu=5Q-6K$95;eObRo`G@CYc-rRde&AhAW7%4Ng$J9Ba zrc4^^nSv;_i3is|HMm*xrjHZ2qNx){O&vRB+*r?;Q8UN2^Q4beC7gV*bKdOt4@GE; zjeHh1-pkjgqV_lx-1;<3{EWyXf(6e)5dD65Ss@hd`Nn{f+6v zx=b58&NF`64A1!4Q^(AjG;L}-RSHd?8Ja#9RlfN*ea5sg<7UnrF>2<_NfV}yAPe3^ zVCIjTJADS|z)SDBvCv!pMZf>Y7ySO~2n5Rr6kCIebc}(khj{lXzyAor34}8U7ZAQf zc;s!re?7u>go6mLBAiB8`W`y!Y0x6%zJF6_d=sMMyEkR}w^-8g@9Et(E%CZ=XS)a$ z`+11p-yU%6FzAXnVz}Qw7V)cymm>ZO@iU0)j({GBJ5Kids}Xmb;`fK+hIbs|CWu!d z?v40wh^HX#bC=)$AmR$d+Yx_&_!Q!CQ~mxccHGfd0nl*D?ljHs&qjO!aRFlb%cALs zpSc?@2E;RF!cd6c!^O>M#Cv9g0pgbtYfed8d@sr)PMeSNh_4}@j`+C+FeKtP7W)1B z2#+c33}X9YzyD_^d<5T=`2BHkl-QU0{cRAhK|B<3%>91IB5wB(EQk0GOu9=E(KDB7PO|I>cWi&fJgk;rRP0#NPS<4g%94l#K8(9o#4jV>jQBj_6NuM5kMf8cA3=HC z$qzc>_xdvdECM1QaVHEK`YW#~h*uy!g?KaK$``=^@m0jti2J<+2DpyiiZ~Oo3-1Eu zBOZg8{wiz@;uVNLLcAGq?PDm9cpBnr#1Fg-(`%A+>nrFC*#PFg0@EWdcom%n@eahR z5HEWToeuGrh)*Lv_BuKp;=0Gt>2NE46>&D=h9^)SamE{HI>gT-egyHlljwAauOmK# zxat%-9pd8{#j&{Wd(MlY+!8?48NYu3;x`e`LhSwk3=p41ybtlb55WNOo{uoKAin!7 zIxTJ)!_T49B3}9lRs+Pv=l%YuP*lco6%g?)rqP~Qhfy4WbGcPpWNCYb;BUPpJsBYlUuuA z=@Q{k_J%t#9_j%_uPwD1th;yB)^~3UX;6veErb1j`~gV~`Q1z{d4M{C&}Xn-xGh!b zH(sBEsQCn=uuI9Apnp~s@92ujyZr?HwtexAu>kL$p#Q!tNjWq@kKdl8d^$mIhe)2N z58j@t+%-{Oh}7DN`Z`3Rlk^u6t(c^LhUo4)^*<4XPu7!mBq@id=(i#I{VshtqC->l zg^0FJ)z=~FF;jmL(VH{%&k)U@rT@7j)f+ztQ#LIlW~FUznd(86-VWDT#65n0qnq;6 z1No*R6UOw`vUs>vw#CtQJylzNH>r_ zVUgdTV9mcnG#Hhyhnagc@^h{Eol0!?f`szh(~Q0Z1T^&r1lT6ni3Jf11^#VZsMSM< zsmZV7GV||4{>gH`{~=@t@|6cz0}oJ@$Zxw6cUx9lc7M=T5@LIY3|f!8zDGfH1+y?Y zfNPkLj*>)7E+D_(D!+f>KQoyjnBdQ^v9xTdz&`FK9{B+t^^yM}@{eF956B=zydk#T zp&%nc`5>B#X+8`sd=pWK%};GYG*duRw9fDU2jH7&lpjeN(a`$W;01t7x9Y+w_G1JpgBJ)7Jsa1$fss{Y8Ky0WRIHe+F<7z%RDze*#<& zFnR~m9t9Y_L%$6(&IN#*cj&_bN?2|acIpcOdH^=usjmZ=3ov`9{vyDU0N>ro6V)Ps z=XdIV0=phyyjFS|w>}(LdKJ0jZhav@55Ri`HW%PQfgK6(+HU)yPnaDZdww@f9Gbg}uhVVz3$c zZz2CL7;yO$$XEAcW=`+|dIOu2;+sVE52)h8WowVDdp-JrM8M4)Du^+{aG=tanK73G803QT6<7Hhv2)+R8y`nb) zcnaVXujoAwCONJE-1DkF6<7`Xm)l>{R|3oic7gX=8G!G;iF32H*2;qctNx7q&e*67wN8(=fr0fb7Q2FlZ(+xU zX*AHuY+ZPc?+R2)sD78&tiBQ`(ZWqz(}qJbBm%LJP{SN`3uDIVmq4Cw7}0$*=Eezr)J*5ZV0>2sLeJir(x*YmG@NO_HH0 zRkKfQkrR5RNs^&DrCm$eAAuaNQ&Ir0QGwDvG8X}=*m{?3X_(o5e-l#f+C z`%Za4aDi2Dlp(m^yBoZ2Y!93vx1yjk%>6u?TOCLJNPQA>zpSQUkyljuqi&me0jo@i z`a2rmu0946In)qfoa%fmmoD`KP=>0%LJ?K6G1EBPc(AKA0H{pa8Lz46Pj0eV!XR4^TJ5PW2 zy%;a$JJW4VkZrpP*rg`S09=RQY}ZETF(l%4BT?50uCBc?^ta!2XJNf@Rn=OJy4CF% z1$bW!ZFK7%Mx|W)W2jKwt;FrQnAX(cZ8Iq&Eafd^L=c?qn&F}xuR96WaLtS!4(^h> zqCOI{9Nz;Daequ@W=9M_HC$YG*Bp&5S2Xt$$a38iyAFvs_XDKM+(`Pwq{m%JO3rgM zL?dNNHoB5=g{O3epa_DqUCUjhzYw|tLg~CAq?THxK46tvW=Qptpa)}@K~S7~E}G0$ z&MFvESF#F_x`JvHkwSkkA3<=otHMRr5mFzvR#o>}r9NUv{e#qAZAhi|bv??w9P)g0o#~T`KevQY)=epRiVSogviAb$!w*b-lH&8)B&&dE8~xu1~Q( znNq}Mq;g$R+DwwP7DL(<9YwI@ZcF;a7|f4Tp;%66?qSq=iE;Bl7U!m`GglH!hw0km zo`m7*@@Qqq%ETDauYS@u3)s~6 z0Eeh{aJQ>3gR4XB2iU2;NsXf}1141c9Q{I7b?^*RA4cWE)kfeJp_Wr)sm(zdsqUk` zrm3g!j8cz5OtktmSjVVmP#{*l1&nH`Re)=&q39BI)B||NsZ)Wkt7d^dUi}V&6V%rs zte#|}8n}Aco}k*eA;G9kFZUs;O%D{7)WKYvAHYIUza{xLbvH;u)IJ#CcJ(CGbEq5f zbgCLkxzw)#hhn~>x(%}330y>56pM2W(RxBP(FKOakO;~B7jph-5;!Zp_R8U#m? zCZiA%q;P)|y_3o6Tw z*jhk^+H!vaQqo^O>q)*wkR&D1)rH(Kc0AMzwT=8)U_Iw_`CMv#BQ%Hno|67CRiPq3 zwFI&JzQUtPsTi614OQ?1MWYd*R1~KUhg$N7X8uIUfoTeN@lEu}=aOQW+1pB*U^Y?m zT-WrSMrO5;|tH|9Io>s_2f2jHwpY)gS(_5WSE#%T3rM+p-Lee_ZBrZtpN7ZU*rbnix zpx4Qb%ye;TV{}WoiNe#5QZZ4=n67U*pPIsKRVB-0n?`KH6rKS|r^fns=RGkA)R?st z?k7}O%4n=7f128bOMfgkH>;GAgux(xEZ;`^AzQ^hZ)y%T&EI66H>n#?SClWyMziOp zw$PV;>WQJXL%t~2qQy+9C;-cQc>yh&L_=Qo8%;SfwK;XVFuA5_n~c;y zxR3(7{dOS@+9Z5YU;76Yc}Js}g*YVX{l4%-_aIrH8|Fc6o4%U^7eQI}FGdMCZ0$97?uZw1gxIbklH|&P_*>L0=5=>{!E0g` z^SZm8;5AliMmrCATsWC)p2=WBfI}&9;3DIii6T>^?B+CThebpg znJDG>NxOj&N3sPK{^G`<&T6C&{n{g+&=-8YeM}5|Od**GZy?Y4BSy-509;?WSo2Pb8muBKg!4$)}!3KJ`TMsV9<8J&}CsiR4pHq~+8T8fO~>cCq5r6B@7m zfm95Q%+Q2r5+v2asV7bft>^B8lq-hjw$Q}dMCOUf(1%`3yOqj@Cfg1J70qX#&=jpZ zT0Mr&KB1|R;lw5;4;BrrA4wUS6z+;aY+I%uzL-#F0xB$r#0~-`)VAJOVe34se|Isl z0kM!OQp_e`(+5!9O?tEHlqk;2ZY=U9O7W@ssOm&{lJ2cek{9di zsuRT$8kJ5Iwu%)C<8WYotGa1aD;Qs{tx^NoD%LNo-9Zn(lo8bj*n^l1e(wYA@tacB z^-`%~9*hg9PT@mS_+ZTE)9{b=>dQ^Mbcl1R31lBPALyJLoxLG2at21YMh80Q-k8?l ztI>hZSyjt}jfF-BI_JKaZG@)-opXN-71C%Y?tCuh7+{GHbk4ApVkE-&KF|oDOu(xsj`( zizl28bk2DW8eGPK&KaKa7D?p;opZU1^cPZBuv9}R&U19Q3lUNuuu3g6q|zqW`C#l? z2#O1*1D&&+RWPKkWEG49oiie(GX#b4fzDasBI^jL4_l?`VjC)idLJ>Q(jmvW+K@_} z*7+#&jti#)ozrL3m1Z*M8rH`+&^g^H2S_R(=$s2&)ILJ$LaS8cKqsUw3RD&KcP_R{ zT@pLK#=<353okV-OoupUWE$NEgz#cR& z5IY4bc*4u{Z9mlY)|{-I>2B&W|Nl=`X!F3qiWbTL2PZ3M58DQq$a1oB_Hw^KwfT#a z732pFR$iK2|NY6zImk8@oWl5IZXQaGKgoW{v2oK99w<75>@Co5;o z$tsFYR?eD(Rn*WN?C6{|C#xtrSvhM?R#9}aa^7^Z(q~+0!Y3lF+Ew4 zUEUZK)}kqgH^2@aTvB^n_=ZT-FZ^GIWA~I#Y>{>m1-1n`wlRWeWgl!-g*dGYp0644|k2es)2?#IMzqyuD za223?91)e*CRlRcfv0_?N;EDU%~m6}?IYYnHYyxRUsR2=ua&j-P%?0D`Wvz&x=bDT zbDGzNoXDwlFxu=t%i21mqGyd7E!lsOos^KYwb*PR6+tPN=EYrz{a4wM2_BmE8t$2q z(kKB|fCG2NxgfxuF;*c*p6h9{0PQCvM>qFWvZiDs4vy}& zdy#Uuhz(zfVg>yeaBXu1Z3xkI?nQTuGgirYG0;;;U1614YL)tcRcaYYg-~M!_0EMLaVLr;lvFUJ zu4ENzme6Df5_h6lLdiNp>cdv4x>f2UhE!t(6;h2AlxiogM7>x-MO}?0l=P`tLLVWi z<`PQnBcv|0O7&W$F0$5ju~Ao+x+HdLje$!{1ABpUE;TJ|ETN&$LEMRA2_@}>)Jm(= zC#+J}S?l_wRqA>cBX1jS=eVl3&ysUb0V`*Ji|D$EK7dVLvODwC6VNB6JLt{vUxUj^sD#o3$ ztbT$FS6yRSB17rsvtKeYSV3H2buJV92jzwf zcpp{|SA>A0@IH#m&2U5^b}lZLrWIj3;O>dV2-?$nBe~ft5F18ZL)<5@&bVrY5tUtv zA>3GiV!5y}4{vRo2dL1Nv=w51oU5+ehZ`Jq6x5K^X~4_sWW1uFs0E2wgVmRzs!a_+ zZkRd(_z<-pt!C;}s2Zl~*aU>D*MNyoi=nVv{T=j?YAniXYHQF(sS^RmtNGxZpn5lf z$fI7yB}R(c2!&JCT_~KUmIGg3O-JEOH4|_{^%O)lQf~lmtbT&MP7`%LFj?v-RKKY@ z1J7pa$6%eUev4<0nh0Ud)q&vFLhXfXvzF>mJX@)D2yU&e1pO^)OE1{9QEvfJTlH%^ z+o@hWZ&g1+c6;?fFzTR=K!MxT>rkSK7` zu8xJULe&XX`m4RcbbuNIxJXUL^A7bClo+U<#j{x51?2{*&*M2*9gI>#)NN3GsM;FO zVX6x>!__8$N2nhoccdB*%2DdtIIMr8)!NW{jM@%N(K`T-QyT*wufBr<6Vxdnov3zz zsVAv-0Dq^t05p@;t59f)`T~@`OFfC_RP|{*r>VQ~oUVpJ%-!lEC^bVZL8+PQLDYDb zx*t4et1sg@M@@lR-h0%Jh~}zm!ET<~0fxF)t%K)$)d#`%sa;`-1?mA{7OGdl+N=JF z=OXnZJQu59Vr^gty&-4D%Gd(d_s*zCD*A>qcTsb4bh+0t7oC;2G#pJian*S zfN`Ey*Pz%lY7-D`RL4V!O=?|`KC9jZ!JF0kV7)~h3(BqP96YzFcY*14)r;p2H6LPj zs)O;|rD|ZkTTR7tkLm)qy=pw3RqAo%?o-dU~6=165v7Uq)SDR6hp%l4PUl!u7drI;IXM%@*-4*O$u4)t|{JUKz_t z9eR&Faf;;no1-OWrNr@)>l+tkB#xC_7eieHO_yBNyzWa%NXQ7x`-&^%Psp&XgWj%7 zHu~IX#4SK*uFF~%ln{>W?`o4gvCDUTUpo>RF3Co8t{-d(k?7D7IjErKx~knnh2BOL zTt69;V;Zz~U5lp-S_Fuzji_Be+xh_xtpXck7W~ys>#}+prkB)v(J->wAGwOU7wXyY zP9aJBhpiMu5l@i}*B=_aZEv{c|BRyIQmsj2=SnU=iw}{am{5{!N0Apf7v|1)DY7;T zmFIoG3$J*HZT~}P9hXCnPWUC=Fc2vw!iDlgk?J)uu?8m1K*T(acKbVoCDUoeE}oL}D_}g2L6|&R zPNi(z9UfyLQc5q>8?GEjqk9CRnTT+t&BHz=^;ePIgc5Xr?QlJ;q5adoBK%cZLrRL9 zEz0nF!T{yUDk{p3wyW|jWNll;g@wZ9cUA61E3~cR%0dq_|4EJ_Cbo)IUQY+Ak3-@8 zB(5F3QvDrh2zj*}as4hKgWgntd=j!1-6s96X=5qBE$L^gII%E&Jf{mO(^heGp{EMn zQGQf*?*;MnHxcI-X0)3o^qB=4 z(eD5z1`j)XcFIxIYsf58M%CRSdxeO+(q}|Bp5(nQyQwdc`%20fG(!+PBO=KTd7^G- zWQC3fwundfm8gnzV(g0N* zlPX`zcxbGkDmO&Z7E6dskn0MOy`_wl@q%iCLG^(*K-SzOE08kEjn0H`&GYXcM8zYn zha4(wJ3z{OccREOYAuQ0IY17jMU?K}q?p~HAlq=4iZ<3?XoBj1R)Gy<74|MU@T z&;(v&H|BZh2DbpF$tK+EZm|8~u5A*HrCh$j)+Z5-UZ;uSO2p*hf(ifG2tc_~!kQ#_ zUC9wsZoc4kC0BId+$QitqyJs$FPie8mzz>Uxlr38qf(ib2IEx26j^MBYffQ>p++64 z5Z5tAa+2UiSyac15#J3HYEd=mCs&RNsCBU!)bhemMjbESCiEKFqy=VR`Qq(jT%nHb zV1D^rL=>dakN>^~v0V9ifZ4gmH`Vc6JF|}bmcY3}x=EmSDw-6Kz0M8mjq1=_1m4Ua z46bdMH%=%l{WHasE;YSO9rxuZI*%&CjJPH|&A!~4j+L~sHQPS zROW3e{aFe9SO_{DE8BcY@QTfv_pO$VV^^p{qKnoDa)mmCD>Q;! zp#lzxAXlh^|M1xrL9S2%lPi??jfwjiGH_E!l7514XIxAH!Ko<+(wuUR>|I*l+=|H+ z?xPBJNKXMHOEFVYv9pnPYV=<^Vk6Ul+Z9PKvPrSYsHD8xaRX{;vDHMqJBAW*v2@Wd z?{R&NgeO+#gqspLixWF}uZ<+cJO)^k_i0^hQl1pM%!8c$%ub4>y2{VFc0dlcn?xud zu+cvaiSa>Dru?c_5zyx~L!UjVzPM1iftM)ckxtycr^)XtGo zT9*{qU$POA{I%@~Di97)MuBhK^uJiNFHk_%=AeM0y#+W#iv+z(`xcaul8p+;-`n1% z!jF-(c6_Xte{^Sup!BOKhc|bViAM%XLmW}b*KG7pUu@T?(!WH^2T{xdkMFloIlcJ; z!u@W`M}FjMsEeV_4flFtcqWY)HiqW1wgj>jsrGBWzN#FL*NT02Qam)phfi{4CO3xA z5V@1ACE3v^-KZL!Wyda97FWcLlYMWga$VjB%Xp8On=}qZe??JwsxLWAPVmyTyNql1 z*TKLQN7wE$uHBD=gBC~E?nr5rijAXdcNy32-2Uij6xXI}cNy32ccXY6zIK=KVso?u z+OUHfx9&nL-MY(ovH5xCOtAQ4Cj&z5N<{`!)9VYwYdU*xRqMw_js#zsBBvjlKOEd;7JUz5SEH zE+OFUkA%LlG-truPlDLn?SXdvE)TpXGV{Spd})fyy)sI?qngcOHZekcf*VFS%6H8unbsqO4%ocR*uZE{|M-;;@0Cl;G^cPZBKx#l} zsn;s?0jtz9Ln`?I)CXf9fS|Zo@}jHdtb!qRC943bX7PUtJEd26KX76Vzuy6)57EeP$SbekyQ4gt7~16zzM09R;f?a z)KyZ~S*!Xa359EiJHEQ!TGtJ+cR>YDEcpP`r&u5OPU+$`SB=u9uGzmJ?bmy%wz|#w`RvTr9m7ttPSQJhAi&i|X-etANbpA)}`9%#w{!G6F_+ zxTteET$91i!QB>kz&6rDO|wyjBWpbTYPy>`md5W+Yy9rC))thC#_vvRGzda8es@~q zcc(RaciQXJ_~mJhU!Kf+ihs8%hF-<{U@-D!>Ao!0o>X^r2V*7)6Njo+Qd_@^qUJ#0@=b!uLoR(rW$r0TFQ zLgSaGHGX+oV^@U6?@nv{?zDCi1Jj}LyVDxKJFQvXomL0grh!omd-&BMT0bZ#`pM9k z7b7sOOIZ1Rov2X(CNB;-3>B-r7iNeZ(ddai>f1y8oRSvku(d1+*AiLp!%Tb;D<8FSJ$w`ES+ z9wp`^9;Z7r>M7`7G=g_>!V^p01a%iDFiy#v5EdG~2JB+^PCrc3>ca4`bWac#!^@*r zilsRqEH;ev35g}gKv=CXBC|^>;W7cn)9f#?V<4=yjo#yotnmwk)pZZSf~&D#Kx4mv z#(n{f{Q?^M1vK^xXzUlz*e{^5U%;#B*w%(?>=@A4F`%(yKx4;%#*P7v9RnIW1~m2y zXzUlz*e{^5UqEBOfX03Sjr{@|`vo-i3ux>Y(AY1av0p%Azkudt$AHF;0gW948aoCw zb_{6j7|_@;psj?}ZqZuSgI_>nzktSm0ge3v8v6w__6un27tq)*ps`;-W50mLegTdB z0vh`Tv}<0}K2KxEfX0pijU59TI|ej%3~1~a(AY7cy@O41AC3J28v6w__6un27tq)* zps`;-W50mLegTdB0vh`TH1-Q<>=)3UuZ6X6u*Qx7jU59TI|ej%3~1~a(AY7cv134k zV?Y|Mv0p%AzktSm0ge3v8v6w__6un27tq)*ps`;-W50mLegTdB0vh}RUTK=fjscAw z0~$L9G=@A4F`%(yKqJS%JsSH3H1-Q<>=)43FQBnsKx4mv#(n{f{Q?^M1vK^x zXzUlz*e{@wU%=@A4F`%(yKx4mv#(n{f{Q?^M1vK^x zXzUlz*e{^5UqEBOfX03Sjr{@|`vo-i3wSkl3~1~a(AY7cv134E$AHF;0gW948aoCw z_6un27tq)*ps`;-W50mLegTdB0vh`TH1-Q<>=)43FQBnsKx4mv=4Ho##*P7v9RnIW z1~hgIXzUo!*fF57V?aBMCODw6UqEBOfX03Sjr{@|`vo-i3ux>Y&@6s|u+MERF`0N= zVP7hxuzjsbIg&5Ft{m^ByRyUyc%)8|!v5wsiy13*ycG70i!xHj;$^+i;{;8Y!m7o& z>n~gbVV7*gHHKXSVV5-p(;si6Ix+H)M05{C(-P-BKDy@&>Bn z^nK}@D8H#ee`P^>8Ktug`lI)y(@W_}^N2^Wu+rUsI{mqi(tTF}{fBgph_Nxz~Q=rUT#Q|RkoV0vG} z0h@hO>dDE&>B1R!GBED$VYbW#i{vH=JqWjbF@K|3!3y0 zvg2Td+7tDdFEvcw>bq1AhHSsp7n&$1ds)^9g&Ga_*7u=oqd!naE_B$hK>mzp1h=7p z=_gm71>44SnN;X#NHATct%LRDQ4YDT(YojbRH;U*UhzOjTqeDe! zIbeCvWK#+^v{_!?p+vbs&T-gRZtrk>_>`chf3!(IxsqmVQL4QoS(M6e_|;QBElEz! zY2pD%9fxDe2Bwzo3=|uNt|f}qad@a0z2OLHBa`5e)YDNc-ob}?TzF=ukO}HJc!I%| zb~Zb9>N(QriU2p_+0#fnkAp`Bl+Nx(=@c{Fwds^`QzbdgxCG z+oT81oN{Z2T)@?917&kE$XI{c@yF8eQLh*3SBnU>{wbjTpZ0o2t)YFJWZ4tV+RLW2 ziO}A6XEOdGoTY{esY=BiQqEoyana5#yZcGO`%FLt-G>MZU9^gLD6#mojV|>-D47_LHthglY~}5Xckt0zo)`LT;qZETSSfa zc?Gv(liSFqV@6Gv`>>3)Jv- zdtG7XVj-iDWO#`wRDOX}ZZDX0Fqj+;Fqw~uQM6TidxF74n5n(JzG#~Pjakw5_U0m8 zAcS-bRHR{r!Imz+>DLtX>TF4Bzn1*esX0ha$ztvJAJ;#>&uBbtEqe=JFogm#ZU;{Mw9-r5GP%dUwc>x z`_U$1x$=Eqb$z+L`o4$QFY;y|_BBnH>(zf2Y59*3dB34$!#G`(*kP2+-s$m8O_x31 zPmPShB3}we$);oAMhOYs50tH9msiSc|A@#PZxA&HQ8xQ)KMQfu-Vu|zl=-YdHO`JS%Q^J4r;nM({Zli5?CYC2Pre+W@`p(Oca8-BOi z*QV^}Fr#Fi~5&@wQcLUzo-EKN7sy>im(I}WHRI2|F%Hv0Mqn}*a*LP=zTtAvsni*oKbOb8-)@R6Z^=?*R&dmy($&gd( z-{Aq9y9E1_E19cgwxC?O8}`Wh)mJxDzAbqm_1Uq4@?yE5{7OVnB*Ql+Q!Y;bkcfta zIH{uj4I-m4L9{1L%m>#p<@CDL(`YGPipt7EL)?@J?{F>Im(x&g-27!ETXqH;f25Ri zo@fdM+oA`B&_6{4wvDhV&@{8Mq1+`o25jZtf;7<}Z4)3}>bufVPUt9Pj})@|1Z308 zoAk>`@qkGe!6dJYQ25xBh#>D1U(ZHzn?}z-L%F>$$oCJ3+~NRH|8&eG=mzaWlKT6$ zHHLI9$_0pvn=lXbU05ZAke%Amt@PN{f(${=PThc^sGlELXf4A}0Xo5l1AyCim8R!zTZA_9y31QKn$)a7TI#+Gclz8rb zQDje`In2!P1Et13@_MXNG!d^k}-e`1ZiH9C|6D+In4G$ zTLQ7gswlX8WaEQ3?Su~ykF#bP3tl31p!bBKYzEVgq6*;oN`U8kwt9l+#4H|?@7XeU zfDAmdyuCflqctrZycFLL>GIox>8ncxw;HB(8k&l}Z7OOoecP5{GG(4`+gb&97S{*Q z*KCpGL4C;J*@{_5BcpP1fazt0PYr*4o(HnNyk_;wUv#7Cm*fMWYY-bJAR%fZU z8*SmV;G9?@s#z4Mt=l&$TaIbSTsGR88eFnAh(dYfY)12Ev8o$wg>K&y*>aNi2z9yD zqBC4yESQ}R@Z8qewBTx6vd}YM=(*a~P)NuXJ#MwF!}lo0yBqEut8KlgchG3bYMaJF zh7mg&Elu&wa=d7V;X_|(r=I^CQTWWd7GnaX!Z|}p`ISPuHHLO01KPE2VrsWC$cifi zRutN;w6zvpH$RJ&TWRYmx^6*k)_Cf=D{XfOVuh`Ke_v>GIm7#ZTD$h(s){py_MGg^xp^lyaFY;{n}k<_$xS3C0fPh;Okfo8 z0ZC8^L?E=hxjYoxn+AO1R3hRQiV}3{s63lVq{Bo$1cpvuA(%?e~4V`|aMduXD~|RW4O2y4w|HukygQ&wDABIwiXHGqGn| z>P*Bf1@Hu2iZ2y|@C@qc%P-&);Btq?Q%kIhC0KKdm5jSd2K0aE(m_Z?sVR@GZydH{>f3)hu)V=+VcIbbV|6&Iutfafw;Aj7_W z2O{}S3d)1}FK@vlA%}*-Enu6twWMSQT1C*2FKznl$4bi_PuVw7S;;BrgcYY2D~wM& zEYKsSoA( zoNLI~%lBed;&oQw4~8TE-`TRn&qnW3+^eDZ(XpLH<+{j;28X}0$RVtX{AyL?5Jn-g zNM)IO0JMKu=m4lfhnXN*=m6luFwWqWzk!8$*>O7wC1Qsl3;l#mh2B`amU6yYsb-be zqUImlS;eCFGBzYyi>7nTmbLK?<)gngS}`ATRCdfBOCqfB?I`q+?VC#U^uz`E-sjOD zvhx&uqZ$Ytwucszit;Tvy(&BvJBsl0sMCwKuWN(S@+nf5?F>|C1zz+Rs@i(dzEs!N z);#g^Drg43#9De-RZ8ETipL8ct7njvYz9Q)H3J9_Y6cJ<)C{~ZH3J9_ZUz8Ajm%Wd zK-R!kT?1`a)#nAE)@D`2?~__ECn+7<8O}znH`%_86gA6>@`(qkSyBFRG{$yY&bgHl zQUBjpn|QmL71jk5Q8ihtYQOC^S#Z5o@ed@pOK~}KhmtYP69psR8deyUT<)^N#Ko#u zg;l*?rFw)?UGJqz8iz9nNKmBeqD2|?dixT^p;76v-mdXD2C?IbD2_J~$2#IT1qOG- zGGY%?EU#BABlZZzqTVXG2U&c=IJSbL>s8tZJf)6_%<-&}{YEs5XP1mCNBf?cg#WoK zh_u-w&8viI{jriF4@Ylc5hE&##M9&1@Vu|F1H4u~Gt^N+uwUue&L4==<5^jBC6;M} zq{$^3K!|1sFt35aX(++27~f`9v?T=eQzZTAb&77h@}TV;CHg62G=231%;;oEf0*c@ zKBQwi|6X~U5-_>QORySEttNRtklaTJYPi#DwYst053hgmsuoc+uO0#LM~k#D;*K1?Sw#*raR?jm}PI8S!;l zk6xM005P_f$4RJlg0)U!t&?8s_-i3}wUdH(oE6!&#n?H&c(9r6 ziB?;FTW@T2(iqRTt2249hv)b3;XORBhv)Y2tR5Z6!2mCiSGXVE12K8<%Y~aB9)e#% zzYljvAbEx8ik^mt_3)f1gk)k#h{zxSLj8^pgE-I#yn!qvfRd2We@z3~!X!6CKH(Nw zf`c4L1{7(=_3%PPhu2PUJk-ex_04E`!ye|fIdj{% zQ_R^&-gE^|a2IjDkXIt7MqY~ELY@y&J9q{Nk9R-k`AraVAC_7~8-c?0+4GX6ChRic zc7iu|aoe5f?t;KB-soi3g78J$u`2^W4SJ8u0N>dHmpHs|yfF7TTz&Rc7#HtOgR6fb zToUAMqP!+I!gP%tm+W)ivg|nw3^V$&)ZqWZ^CC@Pr5tLq^y%9*^Ey9xUbYYj|q;_e72hb6&9m4xR}X;s*;UXo8Tkkiw86pQqId zAo+?$X?*@$INyYJR0!MsQTh3r${*r|&YjTpxE;Ktg2yd%(N0hB8=R!a!L}ChVQv>s z>)6PBukb*G`_^#Y%@ZLQ;W@wxOgD&LH?IQEp2pL9cw&U-s;CKwo#APnh~-Nxs^Yr& z7QU!eLPzk?OB1=I-(Cg;q;DHh;QVG%zTNo&jA_Wb< zLD9>&Zhjfj%ecYxN(sMIg49zi3KWN-poCo>(9M4+H2>yIeq$HZ3pDHw?leL1?Urp9 zjylLfpA+D-y4-H=e!?@~sB_0+3>Hs?>2VJQ1Rg!mKiHs!?yckZ*O2Bp3ypQb!6`H71rWqt0SxC;%DGu z=i1peJ6V6yZ2pqvtv?jejcj6uhWfv9CVDoqU2zLnEngaI+Jui^k>zlrQ@ni-yDJ`1 z2*j?rmkne7$nq6)mn>MjV2PM_AFFev*roGUh_3tC$be=%;PYzY$bIalbRDreGB2`V z>4Ieu5xk$>I7Y+B<)V*H-fXQ~JQp&vc-bPc;eIyOQ(JLIF0o(S&+cYi=2;YPX1OVv zBOEbXvuc^RdNXVDDf-x+&Fq}($G2Rgo9(^0T)g}UoamfQc(aFRLoG?yL4Grl+}cl~ zqxKWYtwhq&PokqPk5k-Qh@@4L#8zx$Ei9@(k)TM_)qztEmL8uBh;U#N`XxsO0CelX z{6x(g--Ty*pIjIi>sSG+@4Q5!193R@n`wQcA`EhMxNCq5S9TRLU%O(t-#ihgH2ONX}B}K+|7G~$gmFV?}Rp@;so&YcVb4B~9@~m?*P0(uj zQv7*4JH+=3Q--k6aACo!<{Uc{VXLjr%w-y$&ayM z(VLXIORpxSspRi!99FodKgLET{6PZg){zt9&d1&Pd6MldUrH+#AC)`}L__bumPDn5AJWz?<@C}xzH4ZWof`f%- zJM@F%sFyjlhzq!g_tDs2esc_jhcyo4Lv%VHxCajD%@zBbB_2(-%)K8AD1o^hV-4Zv z(qcQ{>0sIVNWShIwh+C!&h-@G@&w>bpefAfN%s;(?4lwaMmX;4!W@{p#QsS5rY=RO zdzd^?@H7iX&p~t=6l~v@#D~1kDVaI5X#12HbA~4qaLk{6eSps2D55tf(HhVK?34`4 z{L82md!Jyzih4?Ct~AdgIr>coTFye5tf7OFnNu#C2{)IGw-atoBRng5ce5ZnD7j|i zCq1!j%{8QxGCKMVL}T6y_p8FwIwi!bWUzfkx}#LKLBeOZD*)zpr5i=~;1x1hD<|As zpuJMz85eE&m?>61$?}UQk@0IIUrT(<4SDwef60EOnYmC|pzx@5mL|9Lq&}Wg!mOCHpwkEs z(I3VFCC6$e+}u)%Z-_uX=AvPgaJ4!Q4{Uph5gy#b1m^oN_YiLG4SAVxbH*?ia6JCd zHBvW2C7_y0sIEYTWq%5Dk=AR($Xs;6Q(CA{MZHR}Re9DKvGOVC8ZL;HUC?Oa5|lWz z|4aiMQ=9uPhs$oap@O2#J=j%*S8h_$^uqF0gyU9bbfc1#e}iOKv52D0U2kg%H`nnu zs?L8KMVtFLo*>-Zq0vpax%uQE;pRTpqlBBQqQ@1UVVN5)zLa{2v}c$b9k@#ZGn<*H zO4M9H$ORl5nOOs45Qh$ctbK}ba|_!Ag_l{UjTv_fECm%Z zw=tyvUMN*AAqsQ3q>^y+ojlhOZmw#!5`K5PD!9>9ek%xHMLoU#JAyI(;z(I*Y{s+f zfbH)eB$xk$Wr@&p%x#fleM^spy+OB!sL`<(>>p5jQ2*3`2Mrw5_rml;R@tRqoE*UG zxqw*yb8L4)>`;sqIQGpCh*JkxS%Q9C`Pm+k)5EHBU!Y8qe~BK+AiQ;6TtKwBCc|h=+lVS%3FCa_U z()K6udkpG-o)1LM!Tw;^2cj8+Gz#iFBX%5Qlj6=m!mX2?fap8OirGgZ=T$bz|FPs} zy?%$7|0=8Ue>zuL?k8gRtE@WVonh>C2&1v4O^ z0R#yL927)wLD`ppETW>Kpn`H0mFs?80r85!PET^|W6$Bap5;aQ+q6l4{-2jO8$4iV-5EVGA*7U;QixWXFB2Ey@So*L{L?2Tboib8 z;W&K4ddYVz4xg#;Clx;A2r5>D({TmL75=k0{8b8nCJx_6;V;DD2P*uiU*#Svzx0;O^I*$Uq=4u6lrm&f53 zDtu)ezDD7z2oL?5Q{yFyFf^{fQiUHChkrofC&b}v6@GFY-d6aTF?iCitx|-!F$BVg z6}~18|B%8jkHfD~_|*hAE!_3 zQ+P8De?Z}R9R68_55(b5D10yuANocSisA_R22Fg* z_>eX#j?hIFm=K5Wq41OA@RbTbGY;QZ;pfKT2P%Axz{CHJtA{DV^0)$H6n=Faexky! zkHg=o@K49#XDIy6SUk0VwIb|~B>+EP;Sa~*7b*O)IQ%k&KN*K#rSPZY@N0n={qM6l z!egqynK=Abg})Go-=pvsRHmKpg%b3LlKa zf1>b}arj>pepD2%#$QAcW=09p;)KT}Tpou{RQRXk@W~2)I1Znx@TcSO4MK`=A&!ux z@aCz%x~`GJ2jlR03O_jxU#{e?kHE54_+xSS zmlgh`#D}88?|nr$9arF@!haTrFMUGR;7lBTn8KfaOVVlgmmrhk`B@A;N%cQLI1@ui zjwx^<2Jer-UyQ+L#NY#JheJC{7K0DQ;B^O2{jVs7U^oQ8(ipre2H!CTPqlMCNo=C|KoVXiNbs20tnW?~TDvh{5|}@RMWkDKYq&_4qN)MqQBS z))TbUm;yC1__P@O@)&%241RSCzCm60v=@@?Dm`IEFe$V{(<&Dpo~B1mR?a_SzAVZ_ z+I`OTE4W;i=p`|Gtwv9IrXo_~dSRDcUNFxLb<#96V*|UiiNEgSg8q!nwp$ezu)o<= z;yFz`SBvK%@%&6Y6PglFk$CpSbCx|>JXeb6e)0T>o-3LWv59zAisvLeXWGlfbB}nQ z7SBJ#Ggw5_Ug9}HJnzTzE_LHMA|ezL`M{kt-|Vasgybhva% zSzVWwVWy{++V8fyOJCi(u77c7rcW=k7nd~BZ|qmMsbmtU8{t%RhniOx67`3rQJ1*t+g9;IGj9D)0QOYm8&b4Hkdro{=CCW zY>oY7$3b}h*71Axuzjx69c*>o4V_mfu$A^tS9Hu>1rs_|T%4YWepZOgw;VOTP`Tu~ ziOMvf^{|KZ7^?r;qi$D^L%M$is&pg9EUL75 zIDxJUN7T)$xP}!ZTtS^_dLM{BUAd%+R2-{ZQXY7o1|WI-*30dmu6)ct3=(W9;hr0W zgb~B+O;?53V!L@|Cp{y>9$WdC{!4~!_Rddy9{~jz?OklQ>D@>Fq@z8z_xt+94)*m| zk70}KLs#$D6VmM&eP*y4`@23(ba$(|^uFzxcZjC#hgR*(jK=n$eg*aU%EtCR{g$;! z!z?oY?mb#{Dk?B_u*1C}SJRGG9HWxoHUMQcLJx=M#V^1vXha|r~r8cQ)kM8N%q114fSgh?9l^*V>VvrnDA;N zDY$Y`#l@(Fv!djuKt5V=JZjQ|rS>0Hm*=D`_&3&>B^7&?Rx!v#S1%7PdXGBcllHU$m$51KQv*6D{W;K)7sA4R-_Ko|<5$l+Vmr_oUdw~>$M1JFI@^nA~g$d6^iRcraZHXP&G8x=e~*_v2Zf7!d*)i4i(H$ zvb4ddxtjJoE#zdGw^S@Tt)L=?rE4t9A+Rjb771x*r%_8TWRvW!cjPr1g4G*VuZP0* zj`peq$}L$n$)0^jj`cG3VwH>DI&KOa-TcN~~Rb<TgEn9PEyR?~apuOfFDLq{iimxS~tg(7I4@D&%Y-15khsH)#y5_?Z>9J z^e*q?45SkK^weC|*ZyT{-eq&hgRAI?LQhj8EbZDS%K26rj9FT7n7Tx5Yq50fw!fOz zRPX(2UGnsYnXX;5H_e!;cRW&;dzYW-KVDVWc4m^HA31FInBAgz;4p?rGb~}JA^cdS z96fD-L`^S#n<9}%&)oS!-KyDHx?bI*Zs*+t^%g_QsXKt9_0fu-X)B7ky0?SN0S-?e6nx^p*$h3-@H&pU+#Mzq#L@a8Dz>+X4H& zdoI^k?6;5H(?XxIAM}O#r~B;E1qF8b{1kiB{ALLY_C+Fg&iq3A*ZJ-ArbN45f8!Z@ z$%3GM_L;hE3%2U|?{#&^HEr~HyX|*t-qSbj0%n-rcb9D~{#d_l zr+s#DN$!YoSmoZqo|kHcT3^I)Cx4&80^NO_-EPU}de?{>S-(hB{{d+ZfU%dB1Zkd&im{;|zIvGf;x`PRBumnAdb-)S%^AG}g(|MP*1 z`s~g2hs%HVeOFRX`DaPp$F-d4H$QEEzv3Sal8Wm|8q#9@vr|{~tP8Gu)s_AH2GJ?b zR4(avacpJFq{1S&eVXgc;0-GtzE|(Rp|0lPc1+J)U-!bAt93o+5!<_Ns{ZO)d+xeF z^wn$Z>PK7Yo7dP|AKj$C^{_o;{k!_bhw4f;SWG{^+V1?=gZhHib#Fg5-q63ywmWZ} zle*|}s9Ux}iM;mm_~k#Pwn=Ry2Im?A$VDACO#coV2Bbh=aD*h-J7iH(zZzC^rlF}y*UzT zxiu2G7vBT;68?Yt-Uiw_e4pG>&(jV0?mc?;vP)koWSYJErGcS6Xu=S_HTY7xRzXTT z--nTYT;;a{mcJE=^u>25zGLy7jPD$LoBTZzDaE%7zLoe6!gmzD{&yo0*E`_F_axFW z-*`6>t(@*Cmn2{eUL` zce)Vo$hjXj0kH}20$}CRNQ7f@8L$kM2TXb(5~%|G06lgxVCNN)$a26e8v+1Z0G$)7Y?wP#!RM4IBqpwl)%(MtJmvm4LUcLxXs*#`nh*a+(l;7Xh`$B9Vqz z+-GB~mjgZwI0~@U6R0_0+l`UP6M!EA9s&Fh;Fo~ypNd2hu&bDhj?@G&1)ZZ8;GDWh zgklBD_M+y1&jD@)JP&w0ghZ2P;5xvo0F$uGmL^b{ZECn2nzFh^_>P3_X zoCmlZ@KeB@fSq58gd!)ASp5$!T*d+jR$cHL`_2PnPIz84^?#@-09r^bF2 zV9a9sYkm%leaVMwQrbu!3ulh8~OT6w*5K? zdso`$0A5&STgRd0LA%BAeEs%^;GbOmwukK7k^AT&dj&w7H9%(DCyyuSm#wki17>Ezx=C@cEiCm2tFX}y`!bNo>?+pij(Bt;O6WRUeAo=p+ zk;rYB+@h>k-*3!MFh;t;9|U?mc#<|pB5AbibQ+^_zG1j@;Vlw*1U$cOu{*z&?fw$U z#H}Kk0I7kk_6@)`L9%qK{Wm0gA=zfD{VB3rl3K6or=l(t0eFn)Nx7$}BX`+h_+hLDHvIxoRcG%TORw6lR zr@anI3e~>0(|#Vw8YF+)DR`eo^5>oQC18&sxqO$Mi!OZzNn^Kt1(GHv;ndysNF zHQ-o|Hej9W7%O0^kgo-SD+T?)LHpi!bKQfGw4b#%znkrzhNS0^{W_8>k$nA-=-_*h zOnA<=-ph8MLh{k)?G{M>jHG?oz8XnCmaZ{J?1@OWMe>nX?8Qh9LbAiF_GTofA$h~A z_UlNlL^9#1eGbVzNG?2TTkq$(Pb2xzF}vjbZ1+VZJH2N2M>2pVZO?1=?MQY+GU>Rz z49THL9zJewM{*{TH7D#hkz9@B+i%+cdOtUG2+0FjsA^;DuHPSZ?nj`vIEjS`GiE`BG@azXq_=lHRIt~o~FzhoQcf4%Bn9Z?pP*HrGYgvfGi4Vr2_#p5lJ{L~d13w9| zlXY)@(wZUK*Im!B1E1BhlavZ2te0Gw3KlC^uHaP)_EFHe^K_lc-=Ls#g=w_PPf+l7 z1!pKYTfuuI3~37$qDH|b3NBUf0R?Lnv=v;XU|7M26kMa=BMLsM;06UBSMW&zCt(+^ z5StX-qTn_KcPO|^!8!%^D!5O<0}4K?;0Xo4QBdC?9PV5;aW0oQmr2y+5zVs=RX( z!nyh2+;ng*HaHg4u@gnSojzR?#R!(<#R!R!t=NVS7eITi4Uy~ezy6-(KF~zdTn0-y zMgHZ#;ps|XzPBjDHwNw2XWDbYveseQ7_6IqW)sU`v!iz|`^UxwZNOP3pqmc4O>a`~CB_zB1pQ^j!(Nt!~YCFSC}%;oX4iH^!6EzEaEY zEajLm&=cKlzTS_8mW3z6*_jY?MI^LEmNeeLog7qf(y6#!>Jk zFNe^8Cyx&z0pwm!zO1*e%KrP0=^>(f3Jp5f8-E~eS~*jY&ZKmy`K0GXWCA;p$x4G% zb9ed{bl|K7SPRU$2CGn?tZUGN%{}QsO23XunS0ZzP}W|O_Dp(v>hQ*VB6#yofRIe- zQgez)l#s7EykSmF8wu%}@52IQrn$dEI>C32%1lolgld?g?&b`>8bY~mDRh~4`PU&6 z@I6en%uJzcwn5)hWaKP&b2L(sW`xLuq`V$bluYST^FEX8mr84(6u||p(x;+k0vvh3KNvpWx@n#wW&tQdHYB!rAy6Ple{Cfu86Iw9g5YuQfW0w z_9~^7+Shzg$PV~65hbkZI*9bF7WP2vFX(xuFRv98B~!Z8yxXMqky@)`wZ){2ChhL`tn^LfWv{Jg%Tw_|WOKM#ktM!rCs;*N?L!z#a#%f(3 zTh|T#%`hS8dyv}oF=0=Umi!;&%FR?hl{BrvkT%m&DXsZ>kv-{3_}f&-FEZSB8?|1e zz$~x@eAf_LE?kG{I_R5);c5o?5|D~8M(iK{-6BLP%mRbzlGq7FnaFpU_Fm?hUG_>$h2OCCcD7!bW)-DzMyVA zLUn=rsmVr)so%`5r1|4UNnwq7b`Ir3qZA^SXHOypqgB2U&z?$+H%8?f^6Umgze(kD zxMq+Q=2+tuC{86yM&p~KHEczK$2S;^T;gO@Svg^%k0urCcTxQZf!D3=Ud&So)?mBg z#bzNfL2XKpnV>d%VkW39zL*JWYpR@}#Gu{AX--0CgLreh$OL_NLxH(NWQw%Zx8RyW zU^03j(NN2s36q)I-vFpYqx@|kHT$KD!N%`U3W3j~MDOMw5Aza@QKuv}c-CgW=2x~u zbFjDd!VjnlwUznH0NFdb7)^TZsQe$Og74~_Mu1*BH2)Tu#olx16ErubDNQTrVBh*{ zZn_Zmrd}Y0P0)g7s=fBtJpEkIe&N?(8jTpXPaj4@#;84Ao!`#>;n!Ylm)-ui{5I!; zAa2%+X?fLa%k#*A$oC=-8nuT)`NgDpi=%m{)-=;z@>_nI;M=HoAU?fzlGf}&`-R`~ z8wpc}>z9)$M(zGk(JWN-KNvEJM(}a_(r*pf89V3qJa)O=_4gp_V~_m3nC02`|DNAQ zl8NZ`6xqxOBc9kxs6>^d3wg371wd_8--5>b_Md_g4#qs9|vbxA& zuFAiGs@2@dkIFAYuVXEo{LuW%(JfgkT}(fE?F6maYFqVxysGN(#;%`q6*2kZ*k4;i(4LiydPX})4& z-lT3oU6FmuRI``o_p}%M8BC|OgMGsq&|;?7Rzdzwd*7e=teySApO>-0cJihC%Y?3{ zSVw8;(EQd^q0KDXp@w2Sv8_%X6&z!azCsNEULKVg4- zDVX{yW+iq#OQ-QcejjT4BKZ~7XccxhOOx30!tAcHe~*wr%Wp;s=Q_nI^M#msP9Bxe zT6VUlNAlBzD<*59w)akse zzG++Cy6Rn)$J(v>g%z-&;T*=Aa5pvUTb!mA645-23tqvrL8R?dwVbjeV$F>9u`x zPlN+HYn&#!%_h}r$SLoHd+RJu8t`x%#{k;7v4^je)>q{Ud)BCaGeK+BKl~61wG{>| z6I~f~6vKK!0~*#`oni_z+sLLDAs-}jE5rZNSs|Mm_8TlOCsL|EYoK}}7&Ww# zn4jZ8-$Yt$u;R@JA>h&)!&>i~NV_yT$!OkhqUi*0Dg?Q-ML?V09|WG#SYuo4yWhn+ zv6v%JqSv=w$L2*Gfl|Z~C`BBBQp6D`MI3=r#1SY(9D!2A5hz6*fl|Z~C?)0ylo&9s zhd94H0wreiKaoqPVVaneMvAlsI06N<#D>0p$eHOh(Iqy@AhuxoW#Qo-R&Y5LPHb!( z1TIaSgc9@kRcQHiIteA_rzDY_^eVJ@Vv`gia4pG92Q-$44|-Tm=3S^WOYmP0RHEVB z@XvfKeBQ$vH6#z>C=hg8Ctq^-Q?6$?{SKv9zTmPSCP13y(Hg zBQ`4>GFdLG4X;B^E~}}9#AMXgR0me(hfkQSB((yqz%ndqDWi6Mbw*`4DUmfx9Rc+I z1O&tTp%(aDy{}gyTckVZ^o7!t zDH!#f4tk#5>Fptz(?QQu*C2=u2d9IcXHWVT!qY*|vp1azaXRREo=JZZX?f7|c=LuL z;}r)z&lHm=Nwm6qrlyU-)F0B4=%D9O2fZX3gP!Th-@+U-NgQ%#@EgdIBs%DM?(&ZU z2qe)#&oeV+6>JG6(Lv8M%S}T~9rQd&c_&D#IOuuqGs%9bwMJ-FN^#DkLtlc_x;R$r z5~Y<6dY=3JYoI8QL}tx4XIT35tswdM9yDh;hv zTIulPS*5g6|Mfg5WCxPypyvszy3)kvSuN~Q2R)B3Zy#wD2R+Z-Cbf^$S{Pf7vB3B2N<=UHP?OGvG2W3{S-p47T7wyKXx zr45rrUDwCfb%TErOb8}D7~bMzS)uwPm#5H2edhoDkqeC;J#o>}`G4Wa<>_r~fRAF1 zT%JC@=cqRS!;uU6qbIHqO|}2$BbVoT<90~$iX)e281E1F$;KF-PAaq{I&yi`kt>Og zTpo4gN~I&0r~b&5N=GhF{fR4eQW>^-p86wKDjm5z^+&E$I&yjba^wn6;h0#&Am5Zu z4W@>hIxES}u*DZM#kVN|_&vuasCeg;pvqNNxwDkTo33}Yo$qxMV zVQT}J3jE?sk>trIF-GmvA^&aR=Beyp_Kj#sR@{L4H%-c!qfq25a9Q2Mf2Oj)5V2{f zXh35fn-DGgFz8ug$JD<8O*>+9>=pw|yBX1f1daNJ$-aO;lh)v+22H^A!BCXOCn?qL z_jRFed>6LU*mCxLxJf#jm_2#g6wTEzWdj%zKSC*a{&ZFQ?zT_-D>pQhX7?e$yA~&| zLfYFGkLU1BqD0c&^eB%$HjtWz$ZE-Z@Z_%h`B#9xaU@`A2BkIMU_4#REGlo}e76YD zAa2(K1_@4?27w%hH?OQ_p=rZMyV21@dM)a%?``Izv64Av%842LAY5AITT555x_5qCuFIS=V* z?3r2tv1hDW?h5m9ash2cH20OhG2~FqAPMfPjN6fOnZr%-d0? zfLd`qA&i@VT5^A&v|4iKP+BdyR4SmB+!aVim)z#a$k-~DT%w2o43^wB=&&-#i4~W_ zG#OgOihBs=$k3{11|OV=g;~Z{vE&XXyF_diOD>Hb8Rf*1OOCEza@UboXUX-zPN}sf zR_mfzt&3x|E+MT@s#e?(tpPH&iY1p!P+FG>6Y7`TbSRRsRV=yW9jSFitX4Z#>q@0n zt+-OFT5-kNCqkX+Oa(&{X^)IL&cb*$D+WWb#1KHM`E?Ei>>RUv0B#)MKX-++2Efb985tF&tt-# zP!am;OQP3O2Z{-NVil%t^#6Dj4k7Xxy9`6)|D9Es_O*Xqg_lun;#c7iBA>C#@c*w> zxEmzNz$aGW#&D)=pW*4GLKA^ctip2Ksa5zx5X>yK3JVGXpIJGnv@shcSy?X6qQECs zVad>lXQ@?K<{R=XwF=9;6ZrIuH6DiImvP|EVgS1bilhY!WCG{h2Zy#P}Ui-GF3ihxhBn$mJ+6~k1oH4$%*ldRW)Nw%Jc!9MF3 z@TXXRLs@P`KuxvYL^|7A0m(U5C<&RMbreyMJd1&xZ{3T+1=dd}+{DU9;Ua4p(#@^c zpt6NE2K+6p)7TlcvStEPY;{ESORU~_wzgVAXsLBMo@Lg*Anh`%1k&1AAHuk{)_FYJ zS%X1sZ;bL1kYa95vZ)N+N0E!)@ER?vP$r*v?}oIZE<+(YO5iheXPT%Kws;4 z8v0*9>pc|fZ+(vEHP%X~ud*iNIlwA_vVqnYP<*Ym8_EV*-y?mU^*f$}tqNdCt8DG=&jZeh?`{Hi`v{~*?8V=O~UgI zYZji9ty6g3Y1N|C6zc|*nriJuji*^|$eeDa<2l268K#8pvfcuiX)%bKWp#$5{$}~{ zoNY~o;yG3h47%Ie15CAb5JE%NQ9S2b>+zgtZNu{(>qZzf-?G57z`6}87g{ev+P&6h z;P12c;aOwl;+Xb$G6^@*r)kRgLE()*kS$ zv;GG4k6Kev`}NklFm!_z>VwQ<)@oSvxHTHZp0ErsJ!u_>bsMdlKz+)Z2*poZ-+{Wx zng-6z*1dRcvHpb6tyT&+w^<#aX1moJ&mC4WMDMg3mJnRS?f6zJ7j$X>T{Njx;}4}1OI|%&~#yb zYK+Cyk!_lv>j%Q$2N8I@fQchBj7OtMn)#KxEhe}|<2CbZlL(E*YUVeIzffwjW}Xpi zzNRN6+<`e?Hxu51d}9r4HqROdz?AF*f}7v+%dkGlm*M9#Xl9a|eDk{udU0oJ2JxBy zGOQGI=HwDoj+;O5@l@zZm~Z~5CdNgmh51u95oiG*sRnVIKO0vdowxvE)C~9^AHA!z zPQdM&)e~-KRtr#dYX{6TG=o^p-;J4IN}feJ%s=`2$f#HQmr|*?*5H=0Gc_|J)F)`E zf>C3}4$x9Mz}1ze&iGBJyx8=cxF#a^{NvFwrkkY*5-%f4JS@rOd>ha8LviBzUQAsSbr7VKg7z~NFx zYYA|YrOQCUp9HlPr74WZZ zUI5PML(8mDd!agC2)-+oL>RTpL;00t*AlTMM6@xa6)b>1SupvXYo&Z~J6XtYinecZ z+Z|&;?L>ANwa2QPjHm2CA{n)ZtMjuk7FeFI74mS;yJ&xsQaDXx1>%e(Oc1B>CStE? z)LyL4r^T8TicVqFepHPYaLBh7>$Oq)VRb(BS=L6;Kda9F1-*e?<)zj^AT*T!C3VNX zihia#e>AkSkuo2u{j$30pM%H>%(d_eedywSzIfNuDV5rr9HBLxF+@^pB+zI=$?u9z z!Up)L574VCt!cxdlKh0?+DcraMmOrTn>T9bg6pv2+A8V~*0+gGL=?v9bfgi!Zno}v zDdi3&tne0iYLdPhhf>nk>;*-?!lB7$*EMR-R|D-f=}eNo z3CS+-!|0+ONQJcKXJ7zJO{EQw6R3Cq6#B5WLE((l_OxdcFB(U*!!Abq4t+xfIgCOX z$@6o`TS^|N4C3cBIga z63u^06J&O}|A1ZGf0@XnQzqc2z#7|Seu+%b|FOvUD1*%`iDSDB(vbcI(wyz#Jq>S;WOV$ z!0=VTXuKd7JbY;o{?`m*VqY4MP=Ucvr3!rQi%@}^P-(Q)yLj*C}xT)d*=;uReiujsgVMaRV}I!-U=aNmdSCnjbZw?a_Pjj*?fC1&wN zB>Xg$Bxa|P3h{CdZ|Zyx((mz1KLtG!8)gt&(0>_8Xyi$u!tl|n;J5ao3>`zotPs%* zlAM@p5G`H4xeM}Zf%8-ACFZGNBHr8;q!58a5(zMfJF$t;lF}4v3t3jqoyas4aX0Hp z&tYU5-G=Q_F2&uf-RX42ESJJ=R$YUYSb=gW?1o)-V@gxl&Dxtzg>otEW<8VM4nT(8 zEN|X%5Yok)E^CTO6h8&Qt*L1vP*C%KSb+Ll(?qvS@Kemtnx1?;I85O#YX-j#mT*74 z>9X$f4?`y4r#D^J%#>plL_^&Xxd>){2Chbh!%r4+0uts?AZtwDIg(YiKP>m#vR*D0-{ zs*lzy4QbZ;*t%};-wYFi{s*aD9~1WA?Z$tQE4Nbl6w*X9la-cAY0Xbp8m)9CoUSxl zev#pRy3%Mh3d{sUz)x2itz6-{pr770TS2}UxT264GFHAAGNl+Lv}JLd)VbW|ILLF0 zZtFI$N7^7etOA27oKpW1&MNd#cjn^WBNz7`xw!Yp#l1)VF-j$Haqp3fdyib)d*mOY z1w$qm7azH}_{hb@M=mZta&hsIi;It3Tzupr{Kv(;M=tI?a&hmGe@b1Pi+hh;+p_sGS)M=tI?@|b&%A*;8sma0>K@zLtz+fUUI@josuK5}vKk&Eyj7xx~y zxcA84#lUoPaqp3fdyhQk-lKKBaSH^ciMCZ7O&T$c);~^2A<03rAMR<;j@EjN6IWEF;T!iPi2+wg5p5r1s$3=LKi|`zO z7-#m5Ttw%%h|X~lo#P@p$3=9Gi|8B|(K#-nb9@8^^}2Hrp5r1s$3=LKi|`y5;W;kC zb6kYyxCqa25uW2BJjX?NjvvQXyB` zMCZ7O&T$c)<03l8Ln1uKMR<;j@EjN6IWEF;T!iPi2+wg5p5r1s$3=LKi|`y5;W^$0 z9eE!Y(K#-nb6iB{xQNbi5uM{AI>$wHj;rWgD$N((PmL1HCPCBtxjsMqudWEs9mLGh zhyn)rlQi#F?$em7^2cl5uT3K4kHtN>#1|8DVK_eV7`Qh3h$Q#KJO zJV#PRc+UH?VFH&@AD;96$49-0i|`y5;W;kCb37(I=l$L20j6{jb@TqoHy{%d3xM}h zDixREId4R$PtY=m(Th{qEYLDVc+QJcSTO>G;>6-bcut<4C_Lvyc#cRsK;bzr!gGQ# zK;bzr!gF*o3I-@V=S6s~4LFMeB0T3sc&;0=r2z`hc@dr?){X%R&v_A^s{pMW)hDdm z?1Y@#q&2~9wud6ON!7?8>%0ihZAYfyC!G59B-d=z=s%0`z(@S#6_Bl623wodkgba5geM+blj9Fn(pIt-ZpAa&MrI`4EHK$ z#i2Gq@a6bvku+-0%r1O~4%N-P6h}Zj?C!#^iQZhe33BHY(w0nbnIbk>wI}BkULbmj z;=gcr;k%SCRs4tN6w*~w{j%icSZXPpS4h!3y^YvNB9u0JNV8X{uH)J12Q=|1>_~=p zOYH+UQEaU60i4G4t5eC}xS~J1=*Fdz@oovU3uvCEh&t&N`f(ggA#_gjIZMM=b!Ux3 z6kGzH9B10jsn?%kwYLCy>icT$)#4(DeGk6O7lYei}shv@e z*;@0fl)(!Xm$2c+dK<<*fU!ZJ>l_9Oed&m?32QFSE)>??s8jPJm^KG&Ev`ak*+94J z0(c%?Bnu8lnm%mp+c2ah1=t3D3_>2 z)k;Ya)e3#HxGIRUSGr3nqt})f&k3*W!J3w(HU_$j+kNRi$?lCBa8I;U7k6V>sh*W+UfV`RHUtU#|FReEb4 z@(tZ$s=`&LQW4&5=q{kJ0d6ss9-xRw&@ILoj4oZC8(!Cw<%S-k$~1Mm9|xaN`+TUC zT>wOTH=C)dp_Sc9-o50)-5b1OQSEj{8Vi@4k6L-j)lgNgSOiHfxtdWI!aeJjB7Awt z)nNyU(XTj4h55|w4pFQF4I=F~9Q%isOd5APehX7yKVfI0v{SDgtd;#iR(<0VZGL)z zH0M;*s(F|fr0>3ov+A3_SQS3li}})oHRoK)nPg1(gI+B6N}=>emvD|y+Px4;cS~1{ zx<_i8sY}S#-hg>qD%~xWQdQAlSKy}uA)#ZhqhnO*HfoS(TrS!r>$Sb51NOUA16H-V zm-@wPE;e$$6fZsUoFiapsW9%aW8BrU;l6OOEy@|Ci3O1GhD$bir`o<+*?7WilsG(h)vh2d z5a@T(9jjgKrM${w5#w6z>aKc5^9SaIYp=wdvn>eGQ(W#7a`bB*;THO^wOb&zq zAUC26y0`3LQ(R4zm}24GDXz9MUtatWzmS)vyd&W8TR7rcrNqg{% z3aNd(%PX}{&~7aIEePR5TpqGvOf{*(->Z-SO1D92@wuR2$&K^rTjJ)=s0h}Lv~D@%HQs1!M{ z-tsaJ$><_wjJsPFJ{XljkyvSH7nhZzgkVf;tHcjV#H7{Dku|FMfxE+>03Ujb#zsJj zwB|@zbc>HZY;8k~4C#x2tMOla5pWfghI(HFTeC>!w{VFKiC#M#39kimi6xTS#H89Hcg~K&eE9&$&NuDG? zbKFIUvYkmVU~*j80ME4KB*^d=wQRkxN{7pbM zJi$jq{8Z)NS~#gcYkAorWZU*Y(MXC`))X#c1Etuz@09W`NdVnVu%W=H3g6P7^=v$X zEa)p)D->(TC~I~2js7gBo76o@>h2fS{gvV?yOo6WltONsEU~AfLf#D*Uc)-J_!o7S zF47?l6w}ZsQ$Mt1OSD3lgxr4N`>tWR0jac7D(xCo`fm6+P+Pc3Wg982{T))wr%`DK zl(aSpIsL+}D%Pd(kF<*_mi+&?T{4b{@+XByRk56oj*qXSZdH;X4hM8Gyle_Nw23Uu zRO$K(-W0B@VjUZwpbF+nrYCNTSMf~P8W69dag2&<$iN1&^zliubiIn?@Q4AdusY*E&`*9Ll08@ z-!|IQoG;eUlhj0SN}=a(k;3YQreYSAhQ8?-s)W92G;@RsnQt2HqB0-DxMi;xDRl1K zr)0JhqSMIIaZ#bK7)|?yU%3`Js2Z&a1b1IQt0DKXuV!jckfA!+HX~OFDSnZs9ol8De_69M2Rf^mi+akQGxg4KI#m`!tf`Jfo6E-bvRtP zsROQ(T_dP8oQ(SONobH=W0lcZT3snstTLKQ73H%3tunfPhhk!1Bl^lJqYw2J8au`F zX@Xg0j399|c1osfcidQ;e``A`ggDqOaatY0RrJFK=3qoUT8wsNdn z7U$DtQJ+fdmKp73N3JXu#w{~?$&TzTFWyP2ml=bf3_m)UWwmNY*&5leS1FY+TYT8s z`B9ZMMw5QwF9)+`?MkSB-6l(%8YekljF$K&TH-dNh12jO^TOpr;Qdb20q!v5`3HYd zpzIlH@LQy;ZAuoVIPqa?TNXPNzQrh%vL+PM-zh?o4itT$ja1nJs=-ZCMo7shiOL8? zW!z-w&H9Bu9l|mPUnI5Tj1;5+y zv&!NGa$7WCUi_atnWr`uJ&=CANetL1g+v!D{gN<^4Ik;Fo$_WX5;W9Vb`&}s-EnF0 z5cSkdL;TH_3}tL~)YzBFSRpCXXe}j;(ppa=(J6-em765vfGGb@;19_HDMr3ht+g&E z=eiAdr7ECKB$xxQZS5#}EsS`{uwUb?)ObUE^*M7UJ=Jc_`e7ET93Ivrsj;dCJ6 z?sR>qG>r@my{9LUMjGY9>8Ew&^r6kyDcjU8Q!BlfEdN>$6o>+tMcpRFE8QlpC}}P3 zrJnSrE*j^T(Xu-AjWdF(buK7aS}KiN>+K=(-V3_>c2!`JEC)Yqixzl6&y@v+%02yI zJwsYBs#N^Zj2E5!1g-T&GI6)=J~m1U+8C9WT;>?CJ1VdE`c%@t8-JTsCm)m-f7~cM zV;F{oPWTnFkpfEA&Zw-%NtPHEiX}QMkpIiDK>jboBAQpj0{OoV3n0)!1LUv}En+(@ zGC^zKB@bpTkv?Y1ECeLQhplaW6Ok9_?kzV;)Zi#d3y&Ml3K|Egjpphi5;s^e)vs7% z!cPrn`Q;<1W6ae%s2(iG^ITo^=t`}uf~3rmQj(OEtD~y+gcC=w{E(0`M{lj9Xk~}U zr88xzLn9@7RkW154IT4|p+L69DA~zp>aC=Nq0)|-ddH~5(KHcFlM?4BiRDUS18q(X3F?-r_zR`3DMW)*_ptN1%b z`Hv|6iXw-uQC&jAl7$K^NX^b@pEF?d0v9t_N^UEzECYjr{p- zi=t z;4J*rJT|D?;8Js|%lyXW-{x|E+9*V>gh-DU1|xn{c(54y6h zaJkI+F7H8C;xw15waYzY->Li96z2Wa6)+~4SG$;zwXb>+8^&}v>BGfrc!o84>eO3q zzWugww@(Xi*uebzuHJy_-wBgujGnabi>FwgYhUIzwo&7ExBzAZc1 zR6X3Jj?LcpR2|D^;WzfMZuXterH7mDWvSsld)c-2p9j*zFYjgD!jJ4?9((+AfpEuX zSR;GUzMOsYpJBJK@Q?dgPPpNIcC%e}D1F}}``PS0qY0*DO8%s5`bWQ#L?@%mWGc>>E{8#c= zf}u6gPQMk4k!eFi%;@C*gwNF0|BrZ#j(21E_iaDITCyyK!_*``G#le~GK>uW_zG*y zPK5Jc1vnWVNZ{S@Jpfs6OWrdQXy1x5ncApR;n!bfFR;h=Ek4RZj6EKO|bS}%Za0p*184BOV!T;OAhbO+mahBmSMD9p3uCWVg=*gqrjAuayZ&a0|G{419C z6h1y?_)p+dF*P{9zHvs&4~joN^yPv7sbcb{3s^T=OM|rr;nX)-W?8YK$G0klFEj>dn*_ zbYF%RKV`0>0@PjFZBj+!gU0)mD(7cPj;f17@ zUs>6wlyh>!>@9TIGDVILE?ptWq3b~=m*hVwi#c}Qs*1(G7n`Z@@dxqy6#lQFGyGOj z;p2m~k4t>of4#)nE$k|zKQ%{9(oGEor^~;u@bT~NzY)bo|E9?C2XjA0B8iLNHs&k* zt*WDXRQ)?DeEcihE5rXh$uh$`PckzUAMKv3%G8!hSGH6QF<0T^j}I$=r(PYuY(1*@ z96<+PSyK0M-f+LC$|NFKN6h8jFG5s5e@Vu8<`qkPmiX}e6NB@C@{B>-U)Ui>i zY5;tyo~b>3QXv$`57)kpf!dD9F&7@`=(7qRe-Gs?g^v#@ex~p;k{`lPUX`Ff6(Rnw z=OiUcgW}%?Wh#995#nyh;k265&-G(IbcdTNR-Px3qW?BTxf&!;REuK0S15A)9k8&%$4AGXQ22@hslI8Fgmuyi z`WGOiE&kp1`wAZ)^Z!yV6LgiHip9V4F)WFXf18u6@bRyqauq)Qj!R30j}N1EkoYt$ z{^iVd;nDA6R7_CiVqdCIeWxpYeDL9J;AxP>H^L&qW5OtZM|#UtT_UXHoKn5`MM=ib zwMD%fXer9g?G@oL2x0=r);>^WpKP*Y>m3)vA6>0t9@aGVc zs17F=j)e2ivu+7TP{8hPq}%IXObE|8k3SXqO87Al5?_^)zMU36cb>IROuk(9)jPw@ zzhfP&>fSQ@Mw9Tw??CQ-yUceDZvr{--jyz^8iMK g+x?5Rv?@1C(pTQ_#DB5&R`D}3KY)cNe$8_KKfa0FGXMYp diff --git a/progs/minimal.onyx b/progs/minimal.onyx index b03f1a58..1356f4ba 100644 --- a/progs/minimal.onyx +++ b/progs/minimal.onyx @@ -7,10 +7,12 @@ export foo :: proc (foo i32, bar i32) -> i32 { return 10 as i32; } -export mul :: proc (a i32, b i32) -> i64 { +export diff_square :: proc (a i64, b i32) -> i64 { // Typechecked - c :: a - b; - d :: a + b; + c := a - (b as i64); // Mutable + d :: (a as i32) + b; // Constant - return (c * d) as i64; + { f :: 10 as i32; }; + + return (c * (d as i64)); } diff --git a/src/onyxparser.c b/src/onyxparser.c index 02454cef..c271c0f6 100644 --- a/src/onyxparser.c +++ b/src/onyxparser.c @@ -433,7 +433,7 @@ static OnyxAstNode* parse_return_statement(OnyxParser* parser) { if (expr == NULL || expr == &error_node) { return &error_node; } else { - return_node->next = expr; + return_node->left = expr; } } diff --git a/src/onyxutils.c b/src/onyxutils.c index e40e0cb1..aff6aba5 100644 --- a/src/onyxutils.c +++ b/src/onyxutils.c @@ -62,6 +62,10 @@ void onyx_ast_print(OnyxAstNode* node, i32 indent) { onyx_ast_print((OnyxAstNode *) block->body, indent + 1); } + if (block->next) { + onyx_ast_print(block->next, indent); + } + break; } diff --git a/src/onyxwasm.c b/src/onyxwasm.c index 0fcfa6a0..d19909e5 100644 --- a/src/onyxwasm.c +++ b/src/onyxwasm.c @@ -14,6 +14,183 @@ const WasmType WASM_TYPE_FLOAT32 = 'C'; const WasmType WASM_TYPE_FLOAT64 = 'D'; #endif +static const char* wi_string(WasmInstructionType wit) { + switch (wit) { + case WI_UNREACHABLE: return "WI_UNREACHABLE"; + case WI_NOP: return "WI_NOP"; + case WI_BLOCK_START: return "WI_BLOCK_START"; + case WI_BLOCK_END: return "WI_BLOCK_END"; + case WI_LOOP_START: return "WI_LOOP_START"; + case WI_IF_START: return "WI_IF_START"; + case WI_ELSE: return "WI_ELSE"; + case WI_JUMP: return "WI_JUMP"; + case WI_COND_JUMP: return "WI_COND_JUMP"; + case WI_JUMP_TABLE: return "WI_JUMP_TABLE"; + case WI_RETURN: return "WI_RETURN"; + case WI_CALL: return "WI_CALL"; + case WI_CALL_INDIRECT: return "WI_CALL_INDIRECT"; + case WI_DROP: return "WI_DROP"; + case WI_SELECT: return "WI_SELECT"; + case WI_LOCAL_GET: return "WI_LOCAL_GET"; + case WI_LOCAL_SET: return "WI_LOCAL_SET"; + case WI_LOCAL_TEE: return "WI_LOCAL_TEE"; + case WI_GLOBAL_GET: return "WI_GLOBAL_GET"; + case WI_GLOBAL_SET: return "WI_GLOBAL_SET"; + case WI_I32_LOAD: return "WI_I32_LOAD"; + case WI_I64_LOAD: return "WI_I64_LOAD"; + case WI_F32_LOAD: return "WI_F32_LOAD"; + case WI_F64_LOAD: return "WI_F64_LOAD"; + case WI_I32_LOAD_8_S: return "WI_I32_LOAD_8_S"; + case WI_I32_LOAD_8_U: return "WI_I32_LOAD_8_U"; + case WI_I32_LOAD_16_S: return "WI_I32_LOAD_16_S"; + case WI_I32_LOAD_16_U: return "WI_I32_LOAD_16_U"; + case WI_I64_LOAD_8_S: return "WI_I64_LOAD_8_S"; + case WI_I64_LOAD_8_U: return "WI_I64_LOAD_8_U"; + case WI_I64_LOAD_16_S: return "WI_I64_LOAD_16_S"; + case WI_I64_LOAD_16_U: return "WI_I64_LOAD_16_U"; + case WI_I64_LOAD_32_S: return "WI_I64_LOAD_32_S"; + case WI_I64_LOAD_32_U: return "WI_I64_LOAD_32_U"; + case WI_I32_STORE: return "WI_I32_STORE"; + case WI_I64_STORE: return "WI_I64_STORE"; + case WI_F32_STORE: return "WI_F32_STORE"; + case WI_F64_STORE: return "WI_F64_STORE"; + case WI_I32_STORE_8: return "WI_I32_STORE_8"; + case WI_I32_STORE_16: return "WI_I32_STORE_16"; + case WI_I64_STORE_8: return "WI_I64_STORE_8"; + case WI_I64_STORE_16: return "WI_I64_STORE_16"; + case WI_I64_STORE_32: return "WI_I64_STORE_32"; + case WI_MEMORY_SIZE: return "WI_MEMORY_SIZE"; + case WI_MEMORY_GROW: return "WI_MEMORY_GROW"; + case WI_I32_CONST: return "WI_I32_CONST"; + case WI_I64_CONST: return "WI_I64_CONST"; + case WI_F32_CONST: return "WI_F32_CONST"; + case WI_F64_CONST: return "WI_F64_CONST"; + case WI_I32_EQZ: return "WI_I32_EQZ"; + case WI_I32_EQ: return "WI_I32_EQ"; + case WI_I32_NE: return "WI_I32_NE"; + case WI_I32_LT_S: return "WI_I32_LT_S"; + case WI_I32_LT_U: return "WI_I32_LT_U"; + case WI_I32_GT_S: return "WI_I32_GT_S"; + case WI_I32_GT_U: return "WI_I32_GT_U"; + case WI_I32_LE_S: return "WI_I32_LE_S"; + case WI_I32_LE_U: return "WI_I32_LE_U"; + case WI_I32_GE_S: return "WI_I32_GE_S"; + case WI_I32_GE_U: return "WI_I32_GE_U"; + case WI_I64_EQZ: return "WI_I64_EQZ"; + case WI_I64_EQ: return "WI_I64_EQ"; + case WI_I64_NE: return "WI_I64_NE"; + case WI_I64_LT_S: return "WI_I64_LT_S"; + case WI_I64_LT_U: return "WI_I64_LT_U"; + case WI_I64_GT_S: return "WI_I64_GT_S"; + case WI_I64_GT_U: return "WI_I64_GT_U"; + case WI_I64_LE_S: return "WI_I64_LE_S"; + case WI_I64_LE_U: return "WI_I64_LE_U"; + case WI_I64_GE_S: return "WI_I64_GE_S"; + case WI_I64_GE_U: return "WI_I64_GE_U"; + case WI_F32_EQ: return "WI_F32_EQ"; + case WI_F32_NE: return "WI_F32_NE"; + case WI_F32_LT: return "WI_F32_LT"; + case WI_F32_GT: return "WI_F32_GT"; + case WI_F32_LE: return "WI_F32_LE"; + case WI_F32_GE: return "WI_F32_GE"; + case WI_F64_EQ: return "WI_F64_EQ"; + case WI_F64_NE: return "WI_F64_NE"; + case WI_F64_LT: return "WI_F64_LT"; + case WI_F64_GT: return "WI_F64_GT"; + case WI_F64_LE: return "WI_F64_LE"; + case WI_F64_GE: return "WI_F64_GE"; + case WI_I32_CLZ: return "WI_I32_CLZ"; + case WI_I32_CTZ: return "WI_I32_CTZ"; + case WI_I32_POPCNT: return "WI_I32_POPCNT"; + case WI_I32_ADD: return "WI_I32_ADD"; + case WI_I32_SUB: return "WI_I32_SUB"; + case WI_I32_MUL: return "WI_I32_MUL"; + case WI_I32_DIV_S: return "WI_I32_DIV_S"; + case WI_I32_DIV_U: return "WI_I32_DIV_U"; + case WI_I32_REM_S: return "WI_I32_REM_S"; + case WI_I32_REM_U: return "WI_I32_REM_U"; + case WI_I32_AND: return "WI_I32_AND"; + case WI_I32_OR: return "WI_I32_OR"; + case WI_I32_XOR: return "WI_I32_XOR"; + case WI_I32_SHL: return "WI_I32_SHL"; + case WI_I32_SHR_S: return "WI_I32_SHR_S"; + case WI_I32_SHR_U: return "WI_I32_SHR_U"; + case WI_I32_ROTL: return "WI_I32_ROTL"; + case WI_I32_ROTR: return "WI_I32_ROTR"; + case WI_I64_CLZ: return "WI_I64_CLZ"; + case WI_I64_CTZ: return "WI_I64_CTZ"; + case WI_I64_POPCNT: return "WI_I64_POPCNT"; + case WI_I64_ADD: return "WI_I64_ADD"; + case WI_I64_SUB: return "WI_I64_SUB"; + case WI_I64_MUL: return "WI_I64_MUL"; + case WI_I64_DIV_S: return "WI_I64_DIV_S"; + case WI_I64_DIV_U: return "WI_I64_DIV_U"; + case WI_I64_REM_S: return "WI_I64_REM_S"; + case WI_I64_REM_U: return "WI_I64_REM_U"; + case WI_I64_AND: return "WI_I64_AND"; + case WI_I64_OR: return "WI_I64_OR"; + case WI_I64_XOR: return "WI_I64_XOR"; + case WI_I64_SHL: return "WI_I64_SHL"; + case WI_I64_SHR_S: return "WI_I64_SHR_S"; + case WI_I64_SHR_U: return "WI_I64_SHR_U"; + case WI_I64_ROTL: return "WI_I64_ROTL"; + case WI_I64_ROTR: return "WI_I64_ROTR"; + case WI_F32_ABS: return "WI_F32_ABS"; + case WI_F32_NEG: return "WI_F32_NEG"; + case WI_F32_CEIL: return "WI_F32_CEIL"; + case WI_F32_FLOOR: return "WI_F32_FLOOR"; + case WI_F32_TRUNC: return "WI_F32_TRUNC"; + case WI_F32_NEAREST: return "WI_F32_NEAREST"; + case WI_F32_SQRT: return "WI_F32_SQRT"; + case WI_F32_ADD: return "WI_F32_ADD"; + case WI_F32_SUB: return "WI_F32_SUB"; + case WI_F32_MUL: return "WI_F32_MUL"; + case WI_F32_DIV: return "WI_F32_DIV"; + case WI_F32_MIN: return "WI_F32_MIN"; + case WI_F32_MAX: return "WI_F32_MAX"; + case WI_F32_COPYSIGN: return "WI_F32_COPYSIGN"; + case WI_F64_ABS: return "WI_F64_ABS"; + case WI_F64_NEG: return "WI_F64_NEG"; + case WI_F64_CEIL: return "WI_F64_CEIL"; + case WI_F64_FLOOR: return "WI_F64_FLOOR"; + case WI_F64_TRUNC: return "WI_F64_TRUNC"; + case WI_F64_NEAREST: return "WI_F64_NEAREST"; + case WI_F64_SQRT: return "WI_F64_SQRT"; + case WI_F64_ADD: return "WI_F64_ADD"; + case WI_F64_SUB: return "WI_F64_SUB"; + case WI_F64_MUL: return "WI_F64_MUL"; + case WI_F64_DIV: return "WI_F64_DIV"; + case WI_F64_MIN: return "WI_F64_MIN"; + case WI_F64_MAX: return "WI_F64_MAX"; + case WI_F64_COPYSIGN: return "WI_F64_COPYSIGN"; + case WI_I32_FROM_I64: return "WI_I32_FROM_I64"; + case WI_I32_FROM_F32_S: return "WI_I32_FROM_F32_S"; + case WI_I32_FROM_F32_U: return "WI_I32_FROM_F32_U"; + case WI_I32_FROM_F64_S: return "WI_I32_FROM_F64_S"; + case WI_I32_FROM_F64_U: return "WI_I32_FROM_F64_U"; + case WI_I64_FROM_I32_S: return "WI_I64_FROM_I32_S"; + case WI_I64_FROM_I32_U: return "WI_I64_FROM_I32_U"; + case WI_I64_FROM_F32_S: return "WI_I64_FROM_F32_S"; + case WI_I64_FROM_F32_U: return "WI_I64_FROM_F32_U"; + case WI_I64_FROM_F64_S: return "WI_I64_FROM_F64_S"; + case WI_I64_FROM_F64_U: return "WI_I64_FROM_F64_U"; + case WI_F32_FROM_I32_S: return "WI_F32_FROM_I32_S"; + case WI_F32_FROM_I32_U: return "WI_F32_FROM_I32_U"; + case WI_F32_FROM_I64_S: return "WI_F32_FROM_I64_S"; + case WI_F32_FROM_I64_U: return "WI_F32_FROM_I64_U"; + case WI_F32_FROM_F64: return "WI_F32_FROM_F64"; + case WI_F64_FROM_I32_S: return "WI_F64_FROM_I32_S"; + case WI_F64_FROM_I32_U: return "WI_F64_FROM_I32_U"; + case WI_F64_FROM_I64_S: return "WI_F64_FROM_I64_S"; + case WI_F64_FROM_I64_U: return "WI_F64_FROM_I64_U"; + case WI_F64_FROM_F32: return "WI_F64_FROM_F32"; + case WI_I32_REINTERPRET_F32: return "WI_I32_REINTERPRET_F32"; + case WI_I64_REINTERPRET_F64: return "WI_I64_REINTERPRET_F64"; + case WI_F32_REINTERPRET_I32: return "WI_F32_REINTERPRET_I32"; + case WI_F64_REINTERPRET_I64: return "WI_F64_REINTERPRET_I64"; + } +} + static WasmType onyx_type_to_wasm_type(OnyxTypeInfo* type) { if (type->is_bool) return WASM_TYPE_INT32; else if (type->is_int) { @@ -29,6 +206,202 @@ static WasmType onyx_type_to_wasm_type(OnyxTypeInfo* type) { return WASM_TYPE_INT32; } +static void process_block(OnyxWasmModule* mod, WasmFunc* func, OnyxAstNodeBlock* block, b32 top_level); +static void process_statement(OnyxWasmModule* mod, WasmFunc* func, OnyxAstNode* stmt); +static void process_assign_lval(OnyxWasmModule* mod, WasmFunc* func, OnyxAstNode* lval); +static void process_assignment(OnyxWasmModule* mod, WasmFunc* func, OnyxAstNode* assign); +static void process_expression(OnyxWasmModule* mod, WasmFunc* func, OnyxAstNode* expr); +static void process_cast(OnyxWasmModule* mod, WasmFunc* func, OnyxAstNode* cast); +static void process_return(OnyxWasmModule* mod, WasmFunc* func, OnyxAstNode* ret); + +static void process_block(OnyxWasmModule* mod, WasmFunc* func, OnyxAstNodeBlock* block, b32 top_level) { + if (!top_level) { + bh_arr_push(func->code, ((WasmInstruction){ WI_BLOCK_START, 0x40 })); + } + + forll (OnyxAstNode, stmt, block->body, next) { + process_statement(mod, func, stmt); + } + + if (!top_level) { + bh_arr_push(func->code, ((WasmInstruction){ WI_BLOCK_END, 0x00 })); + } +} + +static void process_statement(OnyxWasmModule* mod, WasmFunc* func, OnyxAstNode* stmt) { + switch (stmt->kind) { + case ONYX_AST_NODE_KIND_SCOPE: break; + case ONYX_AST_NODE_KIND_RETURN: process_return(mod, func, stmt); break; + case ONYX_AST_NODE_KIND_ASSIGNMENT: process_assignment(mod, func, stmt); break; + default: process_expression(mod, func, stmt); + } +} + +static void process_assign_lval(OnyxWasmModule* mod, WasmFunc* func, OnyxAstNode* lval) { + if (lval->kind == ONYX_AST_NODE_KIND_LOCAL || lval->kind == ONYX_AST_NODE_KIND_PARAM) { + onyx_token_null_toggle(*lval->token); + i32 localidx = bh_hash_get(i32, mod->local_map, lval->token->token); + onyx_token_null_toggle(*lval->token); + + bh_arr_push(func->code, ((WasmInstruction){ WI_LOCAL_SET, localidx })); + } else { + assert(("Invalid lval", 0)); + } +} + +static void process_assignment(OnyxWasmModule* mod, WasmFunc* func, OnyxAstNode* assign) { + process_expression(mod, func, assign->right); + process_assign_lval(mod, func, assign->left); +} + +#define BIN_OP_PROCESS(ast_binop, wasm_binop) \ + case ONYX_AST_NODE_KIND_##ast_binop: \ + { \ + WasmInstructionType instr_type; \ + switch (expr->type->kind) { \ + case ONYX_TYPE_INFO_KIND_INT32: instr_type = WI_I32_##wasm_binop; break; \ + case ONYX_TYPE_INFO_KIND_INT64: instr_type = WI_I64_##wasm_binop; break; \ + case ONYX_TYPE_INFO_KIND_FLOAT32: instr_type = WI_F32_##wasm_binop; break; \ + case ONYX_TYPE_INFO_KIND_FLOAT64: instr_type = WI_F64_##wasm_binop; break; \ + default: assert(("Invalid type", 0)); \ + } \ + \ + process_expression(mod, func, expr->left); \ + process_expression(mod, func, expr->right); \ + bh_arr_push(func->code, ((WasmInstruction){ instr_type, 0x00 })); \ + break; \ + } + +static void process_expression(OnyxWasmModule* mod, WasmFunc* func, OnyxAstNode* expr) { + switch (expr->kind) { + BIN_OP_PROCESS(ADD, ADD); + BIN_OP_PROCESS(MINUS, SUB); + BIN_OP_PROCESS(MULTIPLY, MUL); + + case ONYX_AST_NODE_KIND_DIVIDE: + { + WasmInstructionType instr_type; + switch (expr->type->kind) { + case ONYX_TYPE_INFO_KIND_INT32: + if (expr->type->is_unsigned) instr_type = WI_I32_DIV_U; + else instr_type = WI_I32_DIV_S; + break; + case ONYX_TYPE_INFO_KIND_INT64: + if (expr->type->is_unsigned) instr_type = WI_I64_DIV_U; + else instr_type = WI_I64_DIV_S; + break; + case ONYX_TYPE_INFO_KIND_FLOAT32: instr_type = WI_F32_DIV; break; + case ONYX_TYPE_INFO_KIND_FLOAT64: instr_type = WI_F64_DIV; break; + default: assert(("Invalid type", 0)); + } + + process_expression(mod, func, expr->left); + process_expression(mod, func, expr->right); + bh_arr_push(func->code, ((WasmInstruction){ instr_type, 0x00 })); + break; + } + + case ONYX_AST_NODE_KIND_MODULUS: + { + WasmInstructionType instr_type; + switch (expr->type->kind) { + case ONYX_TYPE_INFO_KIND_INT32: + if (expr->type->is_unsigned) instr_type = WI_I32_REM_U; + else instr_type = WI_I32_REM_S; + break; + case ONYX_TYPE_INFO_KIND_INT64: + if (expr->type->is_unsigned) instr_type = WI_I64_REM_U; + else instr_type = WI_I64_REM_S; + break; + default: assert(("Invalid type", 0)); + } + + process_expression(mod, func, expr->left); + process_expression(mod, func, expr->right); + bh_arr_push(func->code, ((WasmInstruction){ instr_type, 0x00 })); + break; + } + + case ONYX_AST_NODE_KIND_LOCAL: + case ONYX_AST_NODE_KIND_PARAM: + { + onyx_token_null_toggle(*expr->token); + i32 localidx = bh_hash_get(i32, mod->local_map, expr->token->token); + onyx_token_null_toggle(*expr->token); + + bh_arr_push(func->code, ((WasmInstruction){ WI_LOCAL_GET, localidx })); + break; + } + + case ONYX_AST_NODE_KIND_CAST: process_cast(mod, func, expr); break; + case ONYX_AST_NODE_KIND_LITERAL: + { + // TODO: Implement proper literal type detection and parsing + i64 value = 0; + + bh_arr_push(func->code, ((WasmInstruction){ WI_I64_CONST, value })); + break; + } + + case ONYX_AST_NODE_KIND_BLOCK: process_block(mod, func, (OnyxAstNodeBlock *) expr, 0); break; + + default: + bh_printf("Unhandled case: %d\n", expr->kind); + assert(0); + } +} + +static const WasmInstructionType cast_map[][6] = { + // I32 U32 I64 U64 F32 F64 + /* I32 */ { WI_NOP, WI_NOP, WI_I64_FROM_I32_S, WI_I64_FROM_I32_S, WI_F32_FROM_I32_S, WI_F64_FROM_I32_S }, + /* U32 */ { WI_NOP, WI_NOP, WI_I64_FROM_I32_U, WI_I64_FROM_I32_U, WI_F32_FROM_I32_U, WI_F64_FROM_I32_U }, + /* I64 */ { WI_I32_FROM_I64, WI_I32_FROM_I64, WI_NOP, WI_NOP, WI_F32_FROM_I64_S, WI_F64_FROM_I64_S }, + /* U64 */ { WI_I32_FROM_I64, WI_I32_FROM_I64, WI_NOP, WI_NOP, WI_F32_FROM_I64_U, WI_F64_FROM_I64_U }, + /* F32 */ { WI_I32_FROM_F32_S, WI_I32_FROM_F32_U, WI_I64_FROM_F32_S, WI_I64_FROM_F32_U, WI_NOP, WI_F64_FROM_F32 }, + /* F64 */ { WI_I32_FROM_F64_S, WI_I32_FROM_F64_U, WI_I64_FROM_F64_S, WI_I64_FROM_F64_U, WI_F32_FROM_F64, WI_NOP, }, +}; + +static void process_cast(OnyxWasmModule* mod, WasmFunc* func, OnyxAstNode* cast) { + process_expression(mod, func, cast->left); + + OnyxTypeInfo* from = cast->left->type; + OnyxTypeInfo* to = cast->type; + + i32 fromidx = 0, toidx = 0; + if (from->is_int) { + if (from->size == 4 && !from->is_unsigned) fromidx = 0; + else if (from->size == 4 && from->is_unsigned) fromidx = 1; + else if (from->size == 8 && !from->is_unsigned) fromidx = 2; + else if (from->size == 8 && from->is_unsigned) fromidx = 3; + } else if (from->is_float) { + if (from->size == 4) fromidx = 4; + else if (from->size == 8) fromidx = 5; + } + + if (to->is_int) { + if (to->size == 4 && !to->is_unsigned) toidx = 0; + else if (to->size == 4 && to->is_unsigned) toidx = 1; + else if (to->size == 8 && !to->is_unsigned) toidx = 2; + else if (to->size == 8 && to->is_unsigned) toidx = 3; + } else if (to->is_float) { + if (to->size == 4) toidx = 4; + else if (to->size == 8) toidx = 5; + } + + WasmInstructionType cast_op = cast_map[fromidx][toidx]; + if (cast_op != WI_NOP) { + bh_arr_push(func->code, ((WasmInstruction){ cast_op, 0x00 })); + } +} + +static void process_return(OnyxWasmModule* mod, WasmFunc* func, OnyxAstNode* ret) { + if (ret->left) { + process_expression(mod, func, ret->left); + } + + bh_arr_push(func->code, ((WasmInstruction){ WI_RETURN, 0x00 })); +} + static void process_function_definition(OnyxWasmModule* mod, OnyxAstNodeFuncDef* fd) { static char type_repr_buf[128]; @@ -110,6 +483,12 @@ static void process_function_definition(OnyxWasmModule* mod, OnyxAstNodeFuncDef* bh_hash_each_end; // Generate code + process_block(mod, &wasm_func, fd->body, 1); + + bh_printf("Code for function:\n"); + bh_arr_each(WasmInstruction, instr, wasm_func.code) { + bh_printf("\t%s\t%xd\n", wi_string(instr->type), instr->data.i1); + } // NOTE: Clear the local map on exit of generating this function bh_hash_clear(mod->local_map); -- 2.25.1