From 44ea3f2dd2d04c060e5d9732adffb19afd28b11d Mon Sep 17 00:00:00 2001 From: Brendan Hansen Date: Thu, 16 Jul 2020 13:13:38 -0500 Subject: [PATCH] Started working on an IR; decided it's not needed Leaving the code for it in the tree though --- docs/thoughts | 5 +- include/onyxastnodes.h | 5 +- include/onyxir.h | 58 +++++++++++++ include/onyxsempass.h | 6 +- include/onyxwasm.h | 5 +- onyx | Bin 232280 -> 233568 bytes progs/basic.onyx | 3 +- progs/test.onyx | 10 ++- src/onyx.c | 17 ++-- src/onyxchecker.c | 31 +++---- src/onyxir.c | 190 +++++++++++++++++++++++++++++++++++++++++ src/onyxsempass.c | 118 ++++++++++++------------- src/onyxsymres.c | 2 +- src/onyxutils.c | 1 - src/onyxwasm.c | 24 +++--- 15 files changed, 356 insertions(+), 119 deletions(-) create mode 100644 include/onyxir.h create mode 100644 src/onyxir.c diff --git a/docs/thoughts b/docs/thoughts index b9402481..188e314d 100644 --- a/docs/thoughts +++ b/docs/thoughts @@ -57,9 +57,6 @@ Treating top level declarations differently: global :: 5 - This would replace all instances of 'global' with the integer constant 5. This would not make a global in WASM. - global := 5 - This would work as expected but will make generating the WASM more difficult. - This feature may wait to come back. - global :: i32 - This would work as a type alias. 'global' would have the type node as it's 'node' print :: proc #foriegn "host" "print" (...) --- @@ -102,3 +99,5 @@ Explicit overriden functions: min(2, 5); min(4.5, 10.4); + + diff --git a/include/onyxastnodes.h b/include/onyxastnodes.h index ba6fe398..081d20f1 100644 --- a/include/onyxastnodes.h +++ b/include/onyxastnodes.h @@ -228,12 +228,13 @@ typedef enum OnyxIntrinsic { // same position as AstNodeCall struct AstIntrinsicCall { AstTyped base; AstArgument *arguments; OnyxIntrinsic intrinsic; }; -typedef struct OnyxProgram { +// NOTE: Simple data structure for storing what comes out of the parser +typedef struct ParserOutput { bh_arr(AstBinding *) top_level_bindings; bh_arr(AstNode *) nodes_to_process; bh_arr(AstFunction *) functions; -} OnyxProgram; +} ParserOutput; diff --git a/include/onyxir.h b/include/onyxir.h new file mode 100644 index 00000000..97e0a3cb --- /dev/null +++ b/include/onyxir.h @@ -0,0 +1,58 @@ +#ifndef ONYXIR_H +#define ONYXIR_H + +#include "bh.h" +#include "onyxastnodes.h" +#include "onyxtypes.h" +#include "onyxmsgs.h" + +typedef struct IrFunction { + AstFunction* ast_func; + Type* type; + bh_arr(AstLocal *) locals; + AstLocal* first_param; + AstNode* body; + + // NOTE: A function can either be either be: + // Normal + // Intrinsic + // Exported + // Foreign + union { + // NOTE: Set if the function is exported + char* exported_name; + + // NOTE: Set if the function is a foreign + struct { + char* foreign_module; + char* foreign_name; + }; + + // NOTE: Set if the function is intrinsic + OnyxIntrinsic intrinsic; + }; + + u32 is_exported : 1; + u32 is_foreign : 1; + u32 is_intrinsic : 1; + +} IrFunction; + +typedef struct IrContext { + // NOTE: Properties used after ir generation is done + bh_allocator allocator; + + bh_arr(IrFunction *) functions; + + // NOTE: Properties used while ir is generating + IrFunction* curr_function; + + OnyxMessages* msgs; +} IrContext; + + +IrContext ir_context_create(bh_allocator allocator); +void ir_context_free(IrContext* context); +void ir_generate(IrContext* context, ParserOutput parse_output); + +#endif // #ifndef ONYXIR_H diff --git a/include/onyxsempass.h b/include/onyxsempass.h index 138ef8e0..c2d1a529 100644 --- a/include/onyxsempass.h +++ b/include/onyxsempass.h @@ -29,13 +29,13 @@ typedef struct OnyxSemPassState { } OnyxSemPassState; // NOTE: Resolving all symbols in the tree -void onyx_resolve_symbols(OnyxSemPassState* state, OnyxProgram* program); +void onyx_resolve_symbols(OnyxSemPassState* state, ParserOutput* program); // NOTE: Inferring and checking types in the tree -void onyx_type_check(OnyxSemPassState* state, OnyxProgram* program); +void onyx_type_check(OnyxSemPassState* state, ParserOutput* program); // NOTE: Full semantic pass OnyxSemPassState onyx_sempass_create(bh_allocator alloc, bh_allocator node_alloc, OnyxMessages* msgs); -void onyx_sempass(OnyxSemPassState* state, OnyxProgram* program); +void onyx_sempass(OnyxSemPassState* state, ParserOutput* program); #endif diff --git a/include/onyxwasm.h b/include/onyxwasm.h index fe0e32c3..24b951c1 100644 --- a/include/onyxwasm.h +++ b/include/onyxwasm.h @@ -5,6 +5,7 @@ #include "onyxastnodes.h" #include "onyxmsgs.h" +#include "onyxir.h" typedef u8 WasmType; @@ -301,14 +302,12 @@ typedef struct OnyxWasmModule { u16 next_type_idx; u16 next_func_idx; - u16 next_import_func_idx; u16 next_global_idx; - u16 next_import_global_idx; u16 export_count; } OnyxWasmModule; OnyxWasmModule onyx_wasm_module_create(bh_allocator alloc, OnyxMessages* msgs); -void onyx_wasm_module_compile(OnyxWasmModule* module, OnyxProgram* program); +void onyx_wasm_module_compile(OnyxWasmModule* module, ParserOutput* program); void onyx_wasm_module_free(OnyxWasmModule* module); void onyx_wasm_module_write_to_file(OnyxWasmModule* module, bh_file file); diff --git a/onyx b/onyx index 9fb8a4b9ebbe69027e5cec4721d2b8fd8a5fc919..791a5a192ba0d7047a7baf0f5a01f8c9578418b2 100755 GIT binary patch delta 58968 zcmeFacU)9Q_dkATma<%6L7FsavItnPcN7#AjT&Ot*kW(7w-|Npiim;S=(P}gjWv=8 z_7c0s-eNQ{#wfPLJki7?%6{KxW_MZgJkRI%`+k1^{&>9(=RN0~Idi7ZoqN%ni%oY| znR4R!s=2v|8$7xMD&nV0?l(#5q9i5~i;^@yR>fmebE(^;wPZ;ig&r~$tW9TgqpOaV zrvK#O?$Rn;OW<1q;%EKVroogq%kIv(d98nm2bbMB`1!HIdV-=W*;7>r)M==lAe`f^x3WW96X$P0->bEF{P;awfw7z zix_`+MH^aa0v~=Q|9+**jOSm~3agak*Z<7FQDp$*!(VBQtB&EOzw*DRdWP`>-Lz@d zxALdw@~hN1;Nq3hQBl%o9*aV~cIW?5XB*?kPiv{2%JHI~wd3^`@W<`)+t<%vjRsE^ z6&M1RTIhm?-b1aOp7}?5=82*wPXV)<6{gQVJhqGgGmC=Lvoeh7S;`aFqWLGa9~#8+ z4Nvpk8|HC-;+VF+Q8fSQQU0k$Kf3UomigP7t}vM18;KI?HG4JA1F>|-@7kh0=N~oA z-`;Wu=ijB|_iFvX;PG&vh@xnq);1%I4?e36%^1uFHq5`C@tSdcrwDxSHSM={Cwby_ zZGZc1#;^KPj=*Eus1D8e%PU%8hgg2$iuPTHSmWj^BI1RqVKkKYdR-+Hnd` z+$J2gxvcf>l*y-U6{)qC^3~4A84uj7UFvepIH0G9WT3XaYY6u|y7qKe7Sb0Zjyf4^ zPjX4?JiM&k>o!oE)Sz6(P8y-<*&TPLXVqHPU05#%`}Y3xr;AGvEt z&kk@;&q|F?&*YE3z%UYaSr|vnZUWxSQf9si^_krg^O=$m-vtLDHpDzDo0`u#Kv71D zZ<^-O$@E_XP1}H6)LIDCtM6HIF-}CNzn99w;-vdbZYwEXlyu7QkCOh!rr5CFsf6Qa z{!xO3N)T19Exn?ys8GFT7spNz)ufcH;@APD1ewhaKkzwMo@bo|GZazg_{Zw|SC?L#d_Q(HM1zcY1RKTyN{!u{vQ=+aYU=);QH`^~rzK%Oc&1VM&nY@+oxxDaB`Y z?>AO!dUms&dr(DXFLmcZxf-7=nkWXJoWel}PR_y*<*%i%un!HajlOXwP^~`sc3@p-Yao`rYX8 zQAbb)$`vb0ig7P3Z0VU7XurwOzI(Th@yGL2#@Kjmc#jaaSgX^$0*ldlb#KYD4r^_C zl;gt=Yr}eku_EoK?p4`PEvQF=Y1{=-{#`1o=#a2FeMnf1(&qJO&ifzIF7}8Cyd_p& zT9r^CEI+WWa!7OU*)DYdFKF;i6iIfi!#@*Cz64e@Yo9iz=VaDMd)~7S>#D`~O5pbn z2*>la5xpYVDs5q}I)VGdFzWa!J(Jp9_paO%>2sW$z9=e@Z7Rz5@Bg;Ja-|7F^e2nD z{cdZ+>{@qiq825hXEssI6475aQFMvOy{YtNDiHJ3Dk@ zwG;QPRxFc4MT^^4TC`1*2Z%KDE1NjjK5{EQ(DqMC&^{eDr`m%bDW}iu1JvJQB&JlQ zR_*iCf6V#TPg;lfC-6ykwXfgb$De(lKYw^24sX+$@XU>l;JwM^1Gxp->X%F=y-Q3?Wb#!hlNd5d z-l+Wr@9u;{H)`d^guDOpE$|;3w3IR7ZLSi&y1`MBAGxVh%1t4ed|qPWPbLASOg<%( zg&VZZ@IHg^&<)x-;DLnGH)y}0q}GJZC2q=+n|X5owAHCPneY;mU^3}n$|RUfzF)6( z85{2Y<`(e&_1cHPKN4QLURwcthVc0H+L5v0Z9XU5e!Zi95#(~W+~91bE+dnwB_^R{ zf+q~8E}ljv-s`o*apCU$2|r$^wE=EL_~bfm!C2O^nNdwCCgJ@>aLB4<r%aoGNK!(QH9WUp#>@#76FChzfA)wIYDr*MyJ+KLZb@o%nak3Xzx z^2gJieJyvtmLESklJPlLw3bsk@{B9mswwY<2EbzPSZe$1T7O+8mh6gWmZICswXmu4 zdH5A=GIJgYt9UyrAUB=$Vtb&fm3)0Fqz@%&x|ZT8$)=Bs@+_Xh8ft6lmvK-1?{@O+9# zg+dG$rD%4E8{Km|4ejBTo6Uj3!#b{4KSsnaP<8@9|Z~^vs{qXFkPoYRaq3 zaWC+&{}XKY)}is6UF$eK9b_k;2P=BEP*byFEz7T#RQV&|bav5t7mujxVDsn(R#IRp z?$KF^*APA=@p{7f5^o^9QQ}R6mpkE)Bo;nrO1z3}Cb(Nf0jnu7R4UdI?j^C1x0m=+ zlDCjp1kpg^6(moRIFE37C;PHaHl7l%Bpa)ntz4A<=r@@V1wVAc-#Xz7PWUS)Tp+P% zp)C?`p#oM)ypymd@t1_>O1y{ghrkvz?*U4Tkcy*(`$~M0aA%3n5q?YJON1Lse3@_! ziLVf@An{egVG>^>>?83_!Ul-VI1BJq!eznAzS;VTk9CVW!jXN31j z{4?Pl68}PYt;Ej>i|6xf*Ix-|Ims;oTUzY}(s_z9Kuw}p-X*{+W$@r%Tw#y>jY8&3GF6F%gG^PTWUC%oJVf8>N`O8k?B z3Z5VnqS=Q^`~%5*Ni4diy~KA&-a_JU2{(}V8^TEv-ymFGV$t_yB^KkuQ(`fOtOmtG zwZA|aext)ewkxd-j~+_=HQ{e17B&~0Y{W4p+f~>UNVyoKTb%N)bh6hZ7JlYReDN&G zfApb~VuZxPXlSdmo8~9|K{FtpEB`(mVN(=#G*DoN-SFChQuQCS&2mr4oNHu&X@QU zRc52aBJXmEMc$7j7I|kfx&Dj91Sg}RPMLd2ECx<{C)`3}QGo^$i=gSA-rkkvB^Cvj zl~|PJDe>vEwEkPg<|s$-f1%oMk@zLy zl@k9=Sd*AxTYoecnAU%HB%VwK@Fg$~AcVj$fEWUO0q6qqNjCsG5IlJYpaFq&fHVS) z0oo9#4bX`|Wq@7;VgUva2m=^Pzz<*s0grT-Y}cG~`7zpZ#$OK9qSr*T0PTlQ+VM5B zH1=6zZS0~9{__Cs@Vaum%mVHEbrm$P#SQt80c6QDv$WLR)wPw2r}9PpMcyy8RDBSy zGy{19^AGE;j6druOuaH;8m)OQZIIxDGuGZ{(f+k2(0y8V@+`0-eVWx;G#bC?=H=bg z?mhG){wz=%wlP9mvoy?<0vr3$tmbL$?9xA6{Vi7OX|3_1YTB!1RosUyQIyPPx3#vL z8}L@|X=ScN^TBhp?VF>u?aQ06HQKMsQ~9*sLcVggkWb8uin@afrM+!rH0Bc`nq6Q; z&88rbtd4iJTs@e(PN52EhjkC_dEQuK+g@Zh?y#1-IgGzQOB;SJT6?~&jJEI7o_uLf zYAm)tzut;aX6)6&$#UuphvjE0i;Pj-opg<-J9Lj$Me%bJHP6)(c-41Bo!XJb<+}_(4IPj zrEA+Zx8v7GpowqrTknX{|HOG4BP(f3H=ZCR=~8lcO9wtRLrXm#gO^fdlC`xP|N3o_ z>FHP@X}E1TH%dtbDPh~&^1f|_&5SX^X2bSgd|MkKIX7BJy6F{xXeM zladT6xe3YQ=48XZ)KYd&;D0w0iBKeJXr_WR-dhN`Wr*;w8It2^!sNbIrf>pJl!=x| z)X=^!Ov9TgQR4PN!hX`8H2$KAkoZeU;NCReRZ1of6gE2{IhZPJ?hFu;xAvv+@>0@7 zN*+KmFGbjF>@RGl?@wdTwD%6ga4#tcKaj@S3Bjm-!lK|n8ZT%h@?7sLB<&8S@o*_= zASKTrnVu|cR`n4!^A4r)2MtNWT(#$iCh)gJf)9C5s1F`a<2xG&^#$$7ks4apBWXNP z3Ti@tYp(jj-O^sd{-dL5{QG)BQruHW62D60X;RWxN{&OaxvsD|)kE0yK98bb2Ci;&bkoyKbm3G1k>Iz53euP)SkI}7#jGih9rl1L#j zZ@~8Sgyyl9hk4vroEK_s(ZxKjz7+HLY+I{UOWGLDv)YRFao~kGZSL79)5lQSm+Co7 zwJ*=MV_BNbo8ZN4@#V~;9M ziplMvh}5!f`Dt6ucYiB%vHelFYbsfJZ^J&YcdLwcJ+@oyFDh(`j<*sk`eEFItila- z4qfLsU;58(rH#BCm_P7B6V7jI+LlXgjC&JBxff}nXWwYym)r4yEnu~ht<`+5#PFkS zv5!>M`dx`JzTI4GTvfF)tNqo&^h~^g%XYneN855`b(MO!syv8eHy-p)7OlkfI<8&f zP<$coQ8IAV9pbESuT8pI5skCqYBhB`?gMc-P&B@o_QTbVd~yYG3$aq`bS>TV5GN9c z(`)%#ubCPD!K|ITQ;xZ4zg}O;hGDi-_PYj1tqAY@yr2!AJ{EOZM0WoK>Wx7DlfXzd(-VX62FOX5dv8GrRu z&2W1rtEA1n9l_q#Hr&oIe%}xUWcPnA3NCYJ58kJoy%WJa^B>XKzW5?V@2Z2P7W$&8#rrPXHwUj$wBozvn68EYP>F5TTK*6f z>?Q5J!JOZ}=V;S^2(a80uYO#A0CQIMYer=R9+ld!h-GJs7-k;9%Tc_wI!Xhq>D$6= zxirfwWriVRHw%|$W2KpR+hp_RGxG@E9oX$&w$;ktJMUY1eqFDf@AczHjCIP-yWfTJ zr!}Fip?MOvK-^>$~y|!|9fl3Z$@kCtJ)qZbc)FeOx>fk zd=(jb?R}&$EwbaOS({zlE9Q81tt0PiGhXfC>!Y;fKkx7d@8^gAZ-#T>F)zT;{oUE=j?4tCAFoO)g0xq^gb-qK!r3$p}aACWnrKXWdJZaPwlbqYY5R z!;%z=zg3b#XkVA45cc7cl>0o_d`e}zuHURLGO{L#J?Z&@dOPW4vlloXlP<$93xf=s z7s;CT(wPU_Wm?*^WT0mE)Q@xWxmW1QCzGa4`Vk?{@6C`Io(?qYzb#4T=*}q3dTgU4TjJbFNxQ$4pbTg>-7DM+Zo(p_CfJSetm zcP#;WW(}6@a^@#wM=wR|hikA9hqYKcbx%#%Iz#X4H)^qp z>U>+e_I=%}HfyEUv!(C-sQ0eTs;F+Z^k+X7EUC>*jMu-XZ>qy)^3m1x%5_=oGSi-; z_Sv(0(>8@x*MHT=)@AWLpt`=IE=#M_DFE`U*`MMWK(q`0Lj&CTg-qlU@ z*b-i@n!c$X23c{{g753G7#3t1kC3xmr-7wrVgbB_6VNwF1!WtsDF${zU(|?|=ked_ zdmFL(9t*HU!!~=g{-zO&^!3GL!N%D`N_&phD>Y^jaXGH3K#taW67uW00nqLFiqRJ-hE_O`xLR#lmZ%w7 z28-b}v$xa@lDa6Vid*~y0qFDMXJ$E4M9VKw{t8wj%wTm;L?zAX~9 z)<6}71JPRWmYJ_8sF0t@&!Q-d1u>}i)YX4z&LY^l#VuH*Y13d4x*YEDdgT@@m@U?u zw_x2P?&7Hbq%}sGuNX$+^AJ2$NYgX=;T9~)vzJ3KM1RtPg}JqazoIp|S2~Mou3e&q zyT_~3Uk#|@6FCdbrYJs<%5Odqf2DSAot=CZ+h}U1mYLU6JGRVxnc5*W^L5Ac?8^Hg zZr?iL4c?j>iw<4XN2IeOyE9l-7fVenYl}fkZM-$OJLo(XL6ZL`8sQ`l2adu}uMg@` zR&v7sFDc5(VO(U(I0;+_eE~WTLgn-$!wvog_c|~)Lz4*=t=6ZNtk$2v8-jlf9s(*( zlycJjlMdVLbHKY-)Dyd~#7_UJf;uMs@9B;$ev$ z4QM-PFX#m5GUz+dW6lnAN~Y65BtqH#R{G#WG&G#|7Wv<9>tv=?*&bQ$z5=sxHf=y#A6WW+!& z0}2I|2UP;q0yP4)sNrI@X4KHv3}&@^j;>?1uKWK$S;$NDthUv93FHB61~me8sZ&sU z2n%JF#RII?ifs@v=)Ja9>uZqyHUiDCTE7MjddF%tv_n^b>b198uYyK&K(lwWTGxY8 zI-!=J@tsktE>`PSP>Zf;PSBKYR%`IPSY1GSd!qHaTdj{kvwB#qkw|y!Wvys^-V0G; z%a41{YOUPQYCQtpy^q!U2k7IzSe78`+aG=1U;k?;3vE7TF!~KtfWXHLlz2I?1w``y zL`gVHkUi-ZfYuMzyA5MUE#4nltwb&hOUN$!Puy;2*HPMz{}WHssG@Vidg>nr)xRt;Ui)Rii4klex6og0 z-NSbKd|R@&b8-72<@ z1pn#VVrvfghTFx~o#1KT7h5la_XK|qp7BGmHNew?GZ;WkPepnA$6{+2@NVD}!9T$h z>MHQocy2um9{;e|dLMiPxQmyfTmz2>4}4T?Z4JKf7ZeO$84nCO;I)56!QkJ3Uj$$J zFBA-Z4BXcn<^6`hEdcugGQhuh0SDmk;u$>$d=K~+;8DL9Td#u80e=O)`j293xJgm0 z;0?iRdYv93tin5~u9DvWq<5U;$lL=PqWbkC18CHS+fi3-@*yGycny9S z+;@uAdKY}tR1_SfC>N%|0l0A{9DqNc1qa~o%z*>&!Sj$G{MSt62lvfFe(?DVkRRVS zAIL_2@TcG@;IUY&dV{wBp9XH32CxcX9r$7JtKfIRt6*tWf-yV5qrhK*r+}yDzybKj z;M2e#g0BKk&P9`hcL2W+?(#8K$q+?p3my-C1Uw!5Tkt{PpDeBjB$Pez9hy37ypCW%4S`xex z_;v8s;BUZ(fgfCf{9%~?j{vqp&~halfQPJt1MuPCUg3&z4!jb01+3Mr!DoXH1HTKt z06cIF@`HB(KL@UXKLvjZ?p01v+}B~YfER*y0DlQS7X0h=7;_eY#0?lc;2fXQUj^?4 z{sO$wCQO$IMOh496MXn)H~`-OJ{El4XP7PEb+=&9f`@Iz-~%5A{tCS6cFdMYtbEu^ z>Vnt6e$WMcCHO?}d*GHO08_q%18|SsZ~$Hf{1vzbJU9x|vH%XiKPiL*@JHYi!SnYZ z0Pqfbkso~dKFk{MclTrTgL@vZTEn9iW#%C~wt;s(j57*&<0F`^;G2(HE!I4MFTTRy z18;T=gAaW5ajR8{K|m+0)+q3r;3?qICo%ZIe*>QeUhWhIANUgR!{B93BR_a1xC@@9 zYn;R218)bO4!-DX3_kF*E9g4#$=AzUtvdnQ-$K)a?*@MXe)l$N9*a%l4hq!Y`+!vl z@!eExO;Yfa=8mNdGYM1^v_xMGH9M`J{(wdD{hM{ubQbEG2Tif=F^NU8L_J{=E6;lA zZHP6|N0Bg9&n4DY|D4!t{SvW#`me;!>SaCz`$ezzAu_zHccj!=eH^7m>q{whUEf2g zjrtu*{jR?u)?Y6-8El)LOstaLV=_$U>eDIpvA!BCnqMro(${B7s>yc_Z|d!47{I*T zjS7aVGS;9dZS)_=`e&U@0UM@A6C0qXPJySIdVfky)@M`d7kx9OZt16|p!QGoUnw<9 zFEbUohI*~3NG;PlQfj^a0hr|o_Tde<4R;jXVu4|%i(#1?%BSKx;Bu)cw%*ae4jcYH zMJL09ei8H@rNVb{g#QWjQ|}jB*Otn^!k*u#d;tUYQ?c%&u@LvGNUTQUP&Ny(yg*_r zcKfVSS?AcZDgg+)EKULMm(mY%=xajX5BgW7^uIau9iVTB)56A5`ZYoyr6_MHV`1t(acpC7Y$NG7~tALL@(SIg<7&zvs7~*bs zf%`qxt6;dhDd?o+XL?)0QNRnI>BFb9h{QDD);Je^!V!ag%%Nh2`P>osAlU5xRo@MJ zw*|oG|E1p|KU;y1|EB*%_#E)a7kcOn*gOXw@J4S0Yze?YaFG?~Drf(OC&GCYimVBJ ze~$IpdC*Y#Ys9z_4ci4a&kQ&k!`=}iKPKX%wwnn3Vi!Dem(n*Qy+!s63=YF!e<_0k zhXeZO6S}+NF}hTcnIcFk;3o8E+;J=A9HfDZ2&15X1^wqnJV`t2#q80$&19-uI8L({ zJoF(m(NGP6w|naI33mrx>!p82crtK(Z~YA6Jm6a1dd~&G`+)~|>*_4v+ra(3^+dw2 zfya33tq6zX&^sbfA40exaAJ@?e-=8TH*nLk`gY(}vw#79rQH^;2={f zKp#hd$DofNh;u|Ky#~ESZcF!JuxgOiTEV$T4Wcu}>~q0`$wnN*>y^^ibj+?;=noIW z15Bv`eslzo2K~I@xWy@@@6Nm|Xaj1(elR$V^L=os0{k5X%!2+1&i(UBIhg4vU>)=c zV{mm-N+0UbAA>%AEG{ui>Blh(wIKy?9|kkVS*|&8W z7W#G2*LCiqF`|crJ`MW)(Bs@wGDdoe`pZGq4+e)|P|w+5Y>9(e(BFifjzo?@)~iIn z4*J{BS9R78Ezuu?{weg`ob_A}&1I_PK6G(-ike?aH(O+;#&N-8VGi^u&U&oy<6$8t z0Q5Vd&v4fBw;cJ?puY=!t5SNgx>Mu0EB#=gPShh7vY@t6Fq(yQnkUXA!b@0Nwtwi58D z5A@A>(!oGO6?J-qu0abw)PL=lbP&{v{zJhG%x%jF@KS($SIBJ^y9pRn8Tc+v7gf9X| zOxGi_fu94j8B*?xXWy|i^qwTI3Or+mK9z6=aOMns1>upvi8J+sgmZvv&D6gmyc2lb zOud-!MPTzRYWz_5=fK@&;g)q83vu(sGxCyIdQVbR1-@ceWFS#ywotf@1a3WBKL{hY z9N_n6>%|LM1fMor|BhrAAzL|HkN61qIq=QddZUl%RDlQR3v;a2&(UCx@l0L3v80RZ z!lwINt2No#W@3rH3-ljAf74mduLuJgmlL6{HV?OWrSx4$Z#z}MU^oo^n}b5=<1+uF z12L;_Lf;qq?@JYM%MrjU=ws$%H!h`b4}EJn>w__RyTRbU1yC1yKU_D|b#`D|R-z#5 z0)1kZz99!=buzHa0{u)5S~?GS;sX6K;r+l3vUN2V_%`skY(0_iYhd4x^j3t!gON8^ zA40ex@Rd*GnCuQ5xk&$vz0bS)lqOXctD$nS!?jUU#Ed1r|QehS-X zrEH5FwrSAsS%;T0rSxAr^!=b8ihGPiXMKO67K3mW^y8ra&{@xEZ5CtfEoB`HF2dl0 zQU-EwiGu7H^a&eq-QcXJsW@B~LN-OPnX*Bzy@*y%%q_!ad7iBV%s1EZjrSCRQCv5n z-wS;?=YvD~Ouf!x=I!&Rq26lCiKKg=9EY@pdJG##Za?ce1t6{jn2YV(@~X&(U&C(wVbybw3ml6le#L*}h%t(Lg)*Tyn;T7i^h3K@OL+Atz;}tP zvhH8VdV!58WZ!_b*~3CuAAR5+d`wkYUyf8*pE|gqnr@=2bzjqBY~daYP4|!pHZ{^O z>|sZFOsuZ$MTjr;D|^{(u$}u@4IUq<|Fn-SBR+jU8v}1I_oF_I^x6mTsbhR(!IcB- z1h>2h{1eYW;cwv~z~iOFFX7zdcZsWExApi#;_EmgdAyPs?^G0zKPCQ*V){$s@+ALT z;?6iwdc2nS2R!I`ypgy%*%V7`8AJ-JNJMNwBpwPA3GY^PUR71!9w^mxq#jO3UVafY z#7z@$?Vy^1Na1Vx0voF86FLCa!6pMls$bdBNJJ@a#=c0p8QfhheAfUkr?ziei|j$;0scb2(|E=99z=65m}m$zqatLsHc)Swj*NBpG(ec9Qr& zGSV*DOA=p5a!6u9J4BrzQ5lGK+Kn!g#1E2-cFA`n@rUHOUGkVD0g(98ADWV%-$@b( zNmaXqqv9+Gk_@}VM3S~ z>S@3p2Bp0$Ep|;uQL1uDrWG??Td}nUKN{dXw+nUI9h4Th6Lyq0s0o0oxQ_&m)0ch4 zLM>kc%Cc4%%FD6_Dba&*a$|E0UX;72y(~qymBRAMVI;@Y#b|*^B^pSE+`Cg_sKX&> zLSw;@`+RDQCk8VF?^53za&JyGiz>}E_>xyc?lg-My|*tS#fO&et0_WTL4#y@3d@`B zC}@fyjtb(r88JhWM3!m^h==F4j%f#PaM8FJjmUG;&EqhR*i?fjx#YQnlnVOdW7tC? zP$gN>wuU-XQA2K_C4TQavanvZGQUNMW?u@togst|-t z_HL-44?K>@&1h*E`CZd9$W!mmNyPxTX;?BE8QGO&9Ix>s-0o}lR_=9r+b^rqo-M+J>5n2++IgnN`>j^iCEvitk`^ zWZS2e32>7*y#EA+E#T$IC(lJI9ag=m^Ol zCv6$h0G?=X215d}4CFqP1-=u94OG}59#Ban2bpQ(!x!N`w45V8^L}tPmW!Q`MtB8p zn(*a$8LS+7jZ@6uGRRR%d0yF3?}4;X#oBwOwb_%>X1kvZrNTSZ+`inO9uqD#m!Yqe z46R908M-g8Eko~O-cCiA;l89q=;pnY){mcJWmpCM#wm3CJ0bRLpRyzwOVQMX(f!9N z>{FIXb)p4GcI`?ghLIt6o+bX*R9SLOtQ_={i)RQkZTmQ1gi?RgB4pl-a@lqkCMQlt z?8zq5x`VC7&6ZE1V6lfqQ5cCmcLo71F^Ly{>ssbt~i zDhnq!wD_1~aQ(t=vQU{X#hgbq|CZTT5heD%aDyG{hCP-Ow73!Q1%54xLgV%hxy1R>tc?NL^_w* z$E$e^4S9|EkTY7e-Hf#{r7ASWa?JE!&)}8MCs-_P!=5EL2Bh#i*zPyo+zkPgF6c@fYi6OOHRPhjFH>_Q$gssws816q(O!=X zvshp%+6{JE%x_TxRc0pH@#`$+ebmBL>@A#9@eMUqtv-ykvQ;Uzy141UBfo9s z7F|mFeSBd}**Z;ajl}T46e(u&49Ad;|J!D?&}LMdj5blPWeFo{jmSRKJlW-_RCJmW zZ^^7B&2?L@cPUpKb<=X2RfZBDRaG2=eilIqfOk56s((ZFZ$9`5r`h3?GS>#KMA~wvs78Wd;$4cc# zv?HYZ)86iG55Q*3@*3fz2N^(moGpMVuV`we*FA@Z=ecQ-d(nX{SxejDpo>!VOX|^7 z@2{#!FSeByyUT|TXQ{E$*&yjGwYGHDPpPKoTwvvzZX-)kPW_5fHB71Af?BGEce2fI zCr6OqI{elUgP-bELw|mOg#^pkD?7x>6^sKHrA9&YMf{l>9u&`C7LTM=uCU`3b{O5! z2qv0h?mNmiqz774WegMd9hIK}yO_ezdG0&((5oyobf=O2B_&fuw4VFU@+Z(3ib*^Q z@6_9p{&V99hyHV$p6;66KQEYZl{KIz?}OJ^HL&Nz>gqAq*@cP&QAZc$7J@XgZI~ur zLFis@I4ZeOkkx+Sr>A_5_;&{KJ^Gf<@K<$VH`z%KdU$k=Wq#N7Ra;oy@O$WGpVf#h z*!2$c9RY{F!s0u!hu7-J^rMGZyu!@ za}P2MR{ZFQe+pPBGjT+Lep3gUWbO?_~3Zz>Fw}xdZK;^3#$kHv@Py;D9 zBbj^bz(kToxx2X)>8anccl{I5eX=X#1LndAU8(>2kX5N(goJ@UVRKIkYyu;1!d2Z{ z7)LsCq??vg=Lg-vZzJ-(gAJW8chx^CWKkCPWCK~2jdD+MJxf`{5J+*Q0u__!VyOs5 zc(oxkRHedFTsHy-N4d9hwE~3XU>du(_MluL<0ZZXtQZooPZ-^UJuwEn2?ra;8`~fu zDr1~r@m`18%7JN|=phFt%|YV_zSB`PT)Wi4?@6ZTFhgs7jnQm0hIA!&gyW4A5lTn zK1My3>Y$k3!p>pTYjVt_c*Rhjg7Xh~NqGpz8&?<;VIlLZC{Hb=nCL8GTv44W6l}80 zjHgr!BRrtgPG~w~Ku~RD@+Mr>xXMT$*-8(qy`={_g&5cPycQnl2x8pm9zYIEbWSjC z^rr;kiJ*2244FmV2*(>&8uvK7t)zG?@Gab}tRdZr=vFp0$#@o1NkI|E$phhd*wezEbBEmnUJcKihdyF?6dG?xQ4~hEh z_o4d4o9Lm{c)*8Zt7`JYZ{uN4+T-h*{Hdbmuf!-xF-;)VF_B1DJgURFoR7xxrga|r zfe?PQtg)qm3iJ3Hm9i<@U|8uXt~}HdKqcU=W&(05JYX}86&K7O>OMEofNo+ExQVgr zCOXAU46k6Lah+>zyi_wc(F1NqYDYI?rjSr$8_1{enV}&h9x;x3d3c(lJoUzR z*%ZriXhLb9k7pic-w`kov&JJXFbY@^E1O3Jv9igD>k%J9R#7Hu0gnWA91`&;v=X@A zr;yDC2&3iJsu;+zN1}mr-i;)? z;!ShOEJQ3WRZTld6CODYW_3~AO%&l~oP(5`(GR~3RGeDQ5CI%c|E!;2iGqfV*G+6L_7Zs1-Sy)+8(g`;Dp)KD7THNpx_1p}D zNLLzhbb^h3Wi$BLZZMPzj0vWO!Ermfpu5aS|6>IGM2X9VxUw|b@z@Y^$);~f|5_gX z9KfuK5>HwQ!8ASaz^6oq_LNHcPZ;PYDw0ZR5K4ob4*AjbYz70QUWuZGiq(jusVdIB zLhfdyV$1(XnO*&;mF!2A6sCj-6P6btE+buQP^ZwNNJI_&^Ls3)8TC6o<41|scMGEI z^b~*(2+(LQ$|ah{@*va{0y+rw=p)0Ki{_-Cc0r{NLQfrUICQ+>sNJgMaB~EMTpoXL zxS^BLe>>ceAr3cmM7{`UKim}L|HM9|b6e6wb_7Q+oF?dP1`Y>D!|0g!&)qm%?#6nR zN34c4_{RooH<{PZdaJ$in_63eGEpUkLaoABL?CYDJ^9zf!*w(MAZ8 zMPhs@F})%&{w^`SA~F6UF})%&zLJ<;kr@A!m|l?>|B{$qkr@A$m|l?>UrS7{NQ`d+ z>xshX9f`46Dh83lDsULRA~E8&o{UPbuG}P7*C_}y+_Ad8gFx-8E2q(6UtQ^>=vZCJ z%CWk3MuJvX6S!Di>HJ-;3G$Y#uB3CUuA7jsudeq>t*)eTtgc@mL96R_a5rNu3?erp zxwfyaV}Kp2>(5BoSJx!bU$)hi6tudYpq#eVm2k=G+8u3bUtPtBwy&;~aICImZ(8zv6dFIWah?4$Tu^JC>9OI^61@4 zq?pLbtTH9&@l>p%$*jq1k%4TPa_s zEP@VX-b>z>8R-FsepucaNB%&2{w|SXkq%@{&x>d>VmG}{M?w797HefAaz(EVhJzp$ zkZP}0M_Y7QAH1Y48E(T6?k zN}UgFonoFtRXFdRWXoK~k$Jo$^Lg6{9we`^&o?HO41mt|=3Kb6uoK>w2FuL0y%Lo; zmIhjdp8=He!?7W>WNiXcH;(z zN4mDNunkQ~N834$sPJY!OEq2LoniA~-?~{|TZfMoRUA>#xno5WQb`vbfZUAq1ZUns z!7TQEG*AX(W2oK+hoi-oigr&mE0J{r(oy|fv2rurWFIqbMtbREUPCT(y|Zk-N?PoZ z!)30m+q=YxOaI(Pq>{1GjEX-*)tg$T7V!N6w)wYFMu^awqD^EwO?8YtdPZea8&eMS zUPXFI+a6{fh9djx1HW}}Kr*rJdn)eaCf-EB4xmx4Jnb(_c;zVQv@8hoj}5R-tc0;c zha;Izn>r$n6K@~~bdqh59#h%Y74{cSiI=H>p~1Awip9-5gap03Ew<8Zivg+?h@+LP zR<8#32Cqxivh>Oz9ksad);qxN&CN)gruj8lb@YDGPez{QsK6A5%Z~ODC7LE1a=cNu zHBC$)Nmd)2ZtRFBB7LRkzDhJtQ54G$}P4LNaW_ zLB<$v^V>V7qAj*cw%8KI@UP%6w-K7mzhKC@DAO^qZ0BM35T&d*5Z|}$n{?$)KmEe~ z+kx2mlONjwwu-*37`Kn|ic9~qm>v3$N7=d<)bu^i73+UF%GwMTMRS~F7d7DYrOqNN zKk8kCsEoeRMl9OiMf!QhsyQ}K3cxPvRoJ_#Yw?)krj~=;UF`t5QJn{S50(CCQ&lIx##8+R*h}?+ z)>~Z&iAlW#8y|HBB);lccqpSDvLNB7(whW-bs^jZsH0#MsJ?(YNIeKiSv3ndSltVG zh`Jt*Le;LoVd~q^hO6W7yPSF&HW6wPw2|s__>5AcVH2(X4Q-5?2yJ<_Ikd5=3nXSW z2sln{5|V+}Txt)fZvg^%JSFfbEg$9sdGa`sPKoqgfO_L6)|M?w94mvkE43QE zs7J93wr)ljv{3W`G(3xR=VBlEeZI^q{wN8Mitw6W$~lHPBURSXr8nbf8Hc4 z%{czZ;7+s3GPo`g;z)X$rOFR$G9oA1vT=KG;xu}O1!SP9#3mDciUQgrOW8VCma?B1 z78V4QC5q8ao;t8QQsXB|tV#QsYl*i;7-Vdx^w!5_-bz}-*#+rrtS66(y^leO zFA7ENmd=qTryZ95I2T2P>V>fEvWt99la|kBNfYt6W`HcOv#@L+Oe)&jp-^T?CZ#+q z^uh`e9YST+ke=R5*QV|K&AoWH*uA7ONY!Up#_6X$p3>-tIZ+&SZ=K`6FX`eAw3VHg{#dwcULmOKjLnvZOp6!Rd=Ja*l$lW6&L^UvhwriUwf z#*n+;68XUd>BEJVFZ`IRVbNeqeRN>@g5ggZ4a>^X5=M71G@$mmW7@YN`THWA{&11>u+9Owo1~ezuR5e(1kDpdXe;uUMs< zt`+QV#1Xn{t@)xpy_NE@6mN=fFmViWQ6tuNcv$c7kYewp*q+n`DaoXgoivv!G=QXK zgdh7xCjPQf1oG73rc9Epvtz|kx=bpmq#HlDQ9eyXL%Jw=w06n+qCXL!H@2#h}0(dg{eXBo`YSLYN(#qQeamF0}%Kl z2X^s#DDWbPjb1w(81G+vA_|`P@QU=|ZP_xsSw-=#%^mOB?qIwH(#@zluA}g8X(L7N z+T8K3Z6HeW4b0Q$mf_{tH~RWA{7>BWtn|a?+DG5xCstX5KYy=Q21;V?0ePsKhaqaW zZ2#~NN!rQHoJ&#SA2yH-9c#iWS?-9w)SuVzK0rq8T(giz&DFp0=Vp(xXbjfGt$mK} z9>8mqX+Rcf9%Ep^bGt`R&(Yrs;E^7QWL3?((MS520A9ULGqS2_w+a&{#9HDV0ft-H zTGH0HB?l>yLns~ThL4+X2XHeg#RGX#yHs)+>rD-e8`7!LNrL|}^eJuwr(*C=rQV}= z_%6zqSjKIAJPP@!kH_0;+QwE>C0_J#0bY(;Sc9&xGP-`{`zzd=@{n*nrV^$}RgQ`z z1J~mQx}5ah3LNkHlW#M02tM~5QkK_bTMJf}<&)^1vGm*e%F88`v{t$T&@Joctwb2uNu*aJNvg1>_aG9ZHE z%XEEj1n&wK5XtMXR(k75p3t{@6uPJ`_jm^p`}(bo7Ab#91^CfFOW<0MdrU_vSn+8^ zruDfY2d5HW$D8en=nOxaZLXMY&1tsz+23q86F&3wn~}U+nEe&@zmVJKo64}C%Dsif z-@0!U5A&t(CtRoV&=%CYiqGGAgD4(~Z`?aY@f8>%1uvtyif`Q)m*;dj+`Bw?Tn^Vm zIW8vKtJ+CuZaOn1$KohlSsxWE=5`jbM*8|#ae&qbn>l^zzS+!o+Yiz^v9sYIJuFTf zq_sG4kUj}UC+632@*usWf;dQf#mj^AjCejK!7mO4?oOq0qfFZ>QKC~#OeMS*w4Jfv z!{UiEwjPndgW0o!ItjetKTg#2{`mhtQ9GTe3(^M<}(#){ESJaPG zDmhU7mhn(!BGt4L@jHe3oVaxRS=5!&_fM1HKu2#@%r5=ysY^eA~UG2h{;p6 zRDe@;Uo5<-Z4r&9Itl~QOI@jlC-J1F7h>r7<|WFEQ8z+SUj3~i4k0T2+bQwtXy63( z3ph$t&mfSB>O9CRsUIO%W%U^5e--tbzA%ZGt@|TNsG*L+0#s9-f#0>%bqKGvS_KuY zqpC2itLm_+r{kgx^*c#C-ZB;uH&s{ScbeK9nr7-~6xUomjgVTX_fcrN z`Zs>JRL7t`t<*)3zoq_!z*?)5A#bBrhP55M15d%#16+7Q3rQ6D3UcIra}++NK@ zbvmf@Um$c;E8}-3)eVx)s-G8F7j-N$bVbADROJcD;mGlxIuqseQGbAXYU2dItVd!SkywHl1e7pYJ%;v~q86g&Q`J-Y@M^r=dxxQ(rOrm~+3HN>o})fS7<1J>@Oz$G4!<+i z;|OEE`Xwy0)TxMmfqET9XRCi9*Fv>7Tz{nYg(OEEgHF#?pQC_})kz3dQ>W`sQH=Qv z5=+$|Q2sLY0NQQ28i#Co>J0q;RE{QF+_vh+X zM7K+wjZpH{Ezo|U9>DJ})oG~TZuJH77O2OA!3x!RFx{ipLY4QbFHyC9YG?g+bzaVL z*AR>e;!ZOFuWEmE9SsmPxSFEg_ok&ExH@ndu?;98M)jTtJyAtw;8)l%MSb8we^eGW zKv5rhE+y1YQH#9j(I;%AqCOJan_~D9&8|K+kZ*4e?5jTYy@Q0Qkp;I|>a!3kUNL#s zK;q{RD!`~1$WZ;o@Fiv1iW<47zxr0h6M*S`R8swyI0Y%DHmJS&n@BLzL^QSfLL|6p zJtbbs!;)ek59;rRN93&r9QdlQe1`?&3BYs?J)r*if7<#I_$Z3>?e6O7$z&$UbTUJ3 za!rm&2st1?5adP^;9G?$3iN(8qMBZ9Cfih{0g6pzKlYh7H$Rgqn9 zkz-d>L|sMD?|G}LJJA2H{mG=>darux?CPhh)o4OEo#5#x+3}^EK+uA}v4XzA7skh7&=>Un}`N-%ZiY*c3ioPL-} zBOoDC>6EgxFzLZT_eN)^v3^FdHwV*oYawop#F8bLp{pf}fJwb7t+YodG&y?m z3qH7!W`9WW%$3QSv~A>Qo^FZHKBsjd)|eh4oegQrdrZQlle|EwF!%GTE_VUE1?TSOlm{Kk^F#@OvQ<%v zCZh%GNfu3}iN-cXja-c8+7T^JY;p(1zlN5O0ZQyRLZbgsFY1_MlSrRyQ5IZ6WP&4N z3K3IF7(ya8imyM(iYOZrGo(bgFXE>c`jXdx9HNl4;E$xope%|0LJTf6pqL)DJ&CmA z#e?`eHU)vP^_VY}auSUbN@r{fc~|U^PbzY8HT4JE^zZqVe8q$*UBKGD8}=7UauP&# z7fJ~5`@woa7*IKNBtj}^79=6M7OrD7H z%r+CLv6IK~!^(K0^g)Y>y|VeHNsU~BS4xjiJzOT8Ej%L`#fc)q*;TkxEfG?enMG2{ zarQE^v+L|0@?`}1hVmm6(z$Vtb32uDSDoYAY-P*!tt$ppeXMEH=qPr45I_b-$6Tx$w7>e0j z|3W%Z@IUElCrV1tA=z9G`x0#`iqYI+$NHl;=tq32 z0d24=8kFwU(u773$Fga7JL#y;B=9jJ7QasMT%mZ%rcYih7>iA^Ch+oEm~V(} z-m;Z^6YzuHz6x60xMOHEpf%#|zrTL%ORP9ZTrV38aU< z1AejU5Mx%{cO}J&`XYuX1gG3}Qw~`bu3Kf(G`%C`BL0Xa7A23tC4XQE{_OI9Y={m*g%dEhkBxzp z$?WDn6$h2v{mRZvWW+9^(dApiEWln5JuIx4{~wwCC&jhS<@(X#YSiLo%I8UnOX~U6 z;h0K=tc1$Sf&%D&%CN1?Xl?_KNOp179sbl?B3M+E2qf-PMi*K))8={!-BUnlDBV-g z?t4ru|DHCYqy%was+G4d1Iv0NdCwP8C4G>bF1_U)QYi%18y)3@^ssH0lt_WTlugr3 zN7`XNh6EPqvt;kB_*5xNlWA=evSa%Tp!E-innRzr<$%1wh|*mEhDmG&eJM<9mJ*AN zBwG&}X|!!+G(QIso5H-UO$OmfNXF9nc}S8IV(A>#5iV;vsaT5EpCfW#l@pOmidmu^~AOV|LDCPr`Ic|`@(5w z`4c~-)*CyM4wLC-q0x*bXEv+G2HbJbygf$Szno){nSV;$^f%xgAerfLo$6lXU6JK)?>tlDM znd}oL_NV9(ctwjcd55&9RX{;(9|nIM)swscr8b(MLL-=eQ06;qlI5Qci+nczzW~be z2n__&n4a>Eln@7v;!nNhs!AN4B@2W6^9ut)e?DmtE1co1k;Gs%6JtoCvCJ8)9#uMN z2%+mFIh#=c<=3-zG=tHNs#bB$KSi$Quw_C^EQ6Z=GKY=cP>#LJza51AOxj!)b#ycS z&~IhgatwROmg~0LSRrkc(Xb~6FLFw>lQb;>WkMysmWYBEk#rH$ceP6E6EJYorMDEI zamaEbTbBD7Rf!7#alClzGs6@VFFw05p3VNc^sG<=+(aPT&%sSXa z7XGB;1StGn{zU<-MwmYC&%y!cARKt|HnOEB$Uff_5YBf51Y&PXxD|%o@fkK zH3{$Q(SpRxNI9Z1leL6Y{9S%W0mL`rrCn8`)v{oy%+<)25k)qYh&9_dCj@my{8S=@ zrbHk$kS1<&M+`*wIpt}D?bWbd-i0Q^rMmv+LsEY~zx>r(QW0@!2HEEa4g@!F;%JII zP>8=Ra<*e>aQwwb`KuSR>e}^NrRwhPL~GSLCPp|WaQcHN2?+gp=_RZ%+Zh-ty8lti zUm$<9ExhRxmj1gHiriC?UxObp0eYXLC(|=l>cJKBx1TS3!sVLja1GYtFKp+pz@{Cc zfe=Tr*;}MkJGVLg!*vi->YRR5NlT|FC2yegOz#I7tgjSh@_@>{nSZW7Y z1aiX}8INz`?|?jr$fE2SS^_y${R>U&XZ8QxCtY6XR_AWy)`+FvS+_Q8Maj>i;5~=2 z{GcrO;CR#heDW|>*foRV_>I12qttbwTl^{jF{G|qL*K03N}RapOQdAkqd#H3vPi1>K8KJ#EJqO5r;PJLr*v z4Q#7T&@D5bqoMSP1l=Mic91r5=>JeZA(JGaTYhaMNXZ1<@=NGeGC{ZG-@asmZuzyx zAP`6<=$8CjK(}CFQs(!_@ds#1H_jH|2~%dI0e`ptd>I?7_b8}$o;m3cryN18S{H+& zYY~Au()Zyz!gy#-s3ZO5ApK3c&cGdG4FCNImYFk+vffUkcMi2^V|OGDBvQT=P3A9+ zVArGwM3Vlcb(j=Q<6SRjb)AW(A2S{VDSaoxC7*iXfQ6KF1kUQ+1InzwQY*LaK>K1^ z#!i0!l19Y;0AHSUCwJQJ(+zX&n#{;Q}(3Ww8=U&13 z_p{qd+FnojjqFr)BRlh9LAS=EheMLM^g`V@g#63^{EOpz71jt7D5aP9mMhpz0QTgM z6!@OSBL%+aiIEE5gEJ-*={DQS7Fz@LEJCShHsO18;Cm=4nOers0wjU&A;e#%!1w4t z)4hUJHsO18;Cn|jx5WnuEp5?j5?S-a0@ z>d6*6mO%JWDxhWj!Z(i+2%qOhNrcbXF{pS42u%kExGx&+K{F3TC-S$(3fM;0m25At zJ^#8=K!Gk8#~$yxFt8~JWuixnp+(6XF*a+_jtE)k`ovvu(-$RpP-wAr6J|zeLVQCv zq-^JTSK&7Crhp%rQg-RNvi7;M%g&Wup0XV#tSFtS75aV3P9!p;)S*Lng>vCYfhLY^ z2qkBwL3KnN+YsV`3&;)~BoN}obh+`5$_Xp^perff7rC>kQgzm2= znapT_UOx`q|GOu7&+#l1hqas~ei6xCv2!B1tD}r0J!1{+;!DP}?A)gVwJDDBr&W;% zxgC1C^LGBkc$RKAgq{uD>+ z`~ix*Kah$XzX*UhuOM{7p!4w~L-9{MDQHbbc9eQfQj!{l7QxS?lyT{lV@2uI(WG!T zSiIt{&g8X>& zAyhs+SAxzMQPJ3IT9fU3ZiuGKyrGNnpxbA(!m4CS)zN? zMCssxWDUDy;p#8SOTAA z34E6ITro75mH=p30-$9*z>iF1)mI9DmL&jMmH=p30-$9HfR-fyTGmsrQ(*~!mL&jM zmH=p30-$BRhheYn$6AhmYpsFsrIYmqpEHTI&lb=uOF*-%wJ7TamVjnifMz{3 z$$@5B55VOCmVjni0-9wBXqF|QS(boiSpu46322rjpjnoHW?2H7WeI4OC7@ZBfM!_& znq?iuj4;9y&@4+pvn&D4vII2ClF%$mK(i2%u~$3LEK5MMtk2-_BuhZEECJ231T@PM z&@4+pvn&D4vII2C8o~EMg@k5V0-9xwlu`Msr5RqpA4vx zfM!_&nq>)SmL;HBmVjni0-9wBXqF|QS(boiSpu46322tph~nO5322rjpjp%HW!;OvAG8F9%MutaOJKMxf#I?QhRdpl;fF1O;j#pV%MutaOJKMx zf#I@x7NL_oZV3>Vm5MgE+Y%ryOMtj60phX*h|3ZnE=z#8ECJ%OUa0_v%MutaOJKMx zf#I@7p-9hLAEJ~mSpO`=x9qGx!0Er>h!=Pr{?wq^Fh3Cf!d!+PWw!&YD||SaCK|0B zU|r$EsbbR63IgHJ6I;O&8;^gAXK3Lgi64Ngc#0N28j502D85Bd9ElQ}a@Yh+b1oa9?SXcNPV;>0#SXcO@)g9~V zD8ahI-vwxV(V_(F3ZD`QJxZ{y@b@CYq6F&-{~!{Egmr~~H2z201gtCklXU}W+mAX4 z|E$I&n#RNS=_uLpMd`jN{7ZXcqu0C0V*%?5pD_l477?(n@UPZB(nITx@NZ%`)3OQH zg*z(gRyM)9!hm&2MHwU(2CVB2h@}%!ORjIjKy``F7}x^VWeHf9C172agmq;Qa~QC$ zw;`D+U|nIry6Q5qtfQ4e7_ctVpk)!PD-2i{Eirvs2C;?#>q-P?rhs*Y0qa`h$^q4N zj+_lxmk`XN8@DiEU1GhKO-l}>(kW$W8KftSRdiocDqvkO3azWN(bQ<-XGLn_KSa#2h)`1cDSzTxR+>OunbFSt z<7-(q7KpIFwAN{6tTN>>P^=kHqFG18wD}#3Giy8UjtpxIJoH(^;E1UiB*r=$gsW@6 z2TXf)*2S8K<{X_#w^CiR=JAo!S$=MFH>B!|CmINUw0Auc-GzG_qW+$|c{=N4e{%td zJ+sNPPsRF#^-9~126e3Lldj0=otA;t5zx!tCcZw=$5H449U;6H0tT68eT`@FcYF-F zWa#D+xPRml#1U6}j5l=YEx*FI@+1nJp{Edw(Y$|2d0rQcsi0)PBq)2ARHPD1NY51N zn?GGrkw)c7(j$wZ01pmttYG9wrk+m0GMYbJqIF22y89)0r7}8+EaK8zI$%qua?(6x z*3h5ygw-D)MIBF5*)EEUGlr2at)_Ge2!&w$)v2Zd-y@_c%+16Mt21@_5PA2tA_ z#U0Ak!BtrliXE3ztzsvydhH-7l`4O@m_-I(=`Fc-p}*3l zx1?iHC@tLBQ!W;4@<4bQ1aUU_LF%qBz^BLr1Ff zX~~n6RK5rdh2|lW649R4Sw?%R*6~LQX8#;&htKwq1|D%+a|MK}>iK1}S#_G|a066> z-ECKo=*jP%&B{jhRZ`cxcE&=gycy%1eo3G`C8*kP)-J}zPFZkH?;r5Leu1>L*p;G1 zmz3%s$Q#SUbMPwH7+yAq6%4R?La08FN?Qh(D#0bLU~z#XSRW`=<~oZ#hx$NI62WeH z#Tb4&G*xcw0ZnxQ^IKStDNR_ih)Zvo>T0SBWRK+sAu;%}?$XhBT&@pXuChSRdG^Wz zwaQ+(*ySh-TqM(jVZZlvtg_(hda3P%t8HeX<9$k?a4f(5I!0e5ee^mON9o_a4tt0u z`J5Q=cUQ7lM2Smpx!;vd4CG2rrfQv5qq*rU;6Kn!+M4R}f8_Erm%m&f7FeK~=1O|x zQWxn2`9ldJMhm*?n7wd~le*A~3Nd4Lrd`HE2_5Kfj5b}zq9f?X67<||eDhqE9Y5Sf zvNyY?mw>bUqjq3>Godpj(ACSw@z3Y7s`5j1k~`$uIN);cODL4wgR76!@$U0jS@~>* zr&U;BxU?NJoK(Ikp@`UNM;_X5oyYpJ{C0f*JT~m2FUiLj67&(unil_@3VL&bc?NcG z=_HLGb3N{XsaYz$IU!H^0G&MA7`kHt8^gNS@S_V@S(DtJHg3u?G^um-m(abj&iZn*FK?8wF&87 z`-FO_Z*aNT`)i-jpVlCFR#tsQ75`)*D~qqHljbFcrwU2+%L2BFLI=8UQ(RSR?HX7PqfHriRk09Go z0}D-n@wHS(|Mn+52I(xN=?z!Y8L*Yt^TO*{LH4);!P!mv@swTh4JKOsLqEO+aOL%^ z&VIQ<`f-IT-3JRbS*m~fvt+48OR4uE<#;d!GpGKdUv#9P(y_Tpe22^37elbLIhD9K-@xMW z1nRCM{r)t?eV@xsH>;9+q`%-%{_PE{zHuILH~9T;l}g?HUG4)ecLTU(d9+UX#6QIE zpQQL_xcr4Ey3{_zS_V}3eYpfL1LJ;UO2@e7MX-|V>H1D#t+7}el6vb2vrV25UWcgD+5TS3> zYU9OH)nvsr%H_&)xJGNWcPp+Lf~yzaK6BY({?zA$vIeczC^=u*7I1Z$r|ISX2(4<+ zS+(k!CA{J$);H3K^)Ov@n@yMAvW_pkiFGL!F1}?BBo_(d)@9;?DR}5&2G?Qkpydn> zHsS|wVuJwe$zRGcB7e-2n#c{Q=~6yqDeHolaqXonGjy)pgG*Vj%!`$P6F$9V7xoRx zbNEk7*-#wrF7;vKv5YlDHmO{6199msEBRZ?SWa)Lx>2fL${%Y)SpVRq`)hzMR!pd__y8MP|ZbKyW#$a$i7Qyo{%fhnPnG&%XO zgXAoxhlfdfrI|+0&bld?CtR7wNT!~jT*(UcgFLc|b*#;8Cl#wYM=OhBnvlzSUkg25?~V-P9syZY&f^!G}a>tUDcv@eI6AXXO@_rg8>7oXUPBLqSG-&9fG`$U;XDIMco9cNq} z-$Mt#ay80)M!{6uEcHR_mnHbxS2UdOTFr_JHYu()UF%)0V?OkQQ>*cw{vL|Vr@kaw z;}201SGd*__yxDHn0^x}@`v-ix3IqBh(;^R zE^{Yih& zF1NCJyOG-DHmTRIB(S^?m)=qVx20p-d?m7uri8fmeZ!cn zbS!msZ1R<|0*>*8i4{i?J|kr-`ccEU(w9h^do%_FHz4Cm5Cxne zL96?a!avYw62q=!k{X9Msa^kGR+b0)vID~MIB9vHuTWYZEiGT<3lnRi@#%S%2YW2P z%NuUTWatxy00wgH%;Y!RjzimN*U_DyDt%$P0mtcqj?QCLnrc^P#YU?r@x_N>u{Y}s*N*~thzNOotOj-I3N$PNGxqd)K%a35~j5h=_ zeOWYbQ{2-qN+Mk-J#CPs&vHE7d!DDcZJr8G+B=?Hqs5O={T(xOx)G~XcY!n7-W6=Y z?SDCK&O1D0`w)NP4%R1|p6(NwT%w(vid}gi95+&1c<4@6VW%l|*=}^-CvAf3GozYR z(~#BaRf^sr!~ar{s{Pzkef*e7B>y3!Nb=(*+n`{*ZTJT${+nF=Q(XSHjiM|mFuGjg zP>gzcN7bkNDgNf2tTLWVuo_(IRvlrk>E#sm0T~dwVZxU>e$V>J!h$Rd3#9i87=iW8 zM!1IG^m_naH!5xOlrt4K(pJE3qp&NKQj5pPL|dfzHV*!+dxpZk!AK#WP6ebRZE>1I zj)={H4Mqp@O2lasElO@R{MRb}Ta_ujWpA&m9f4boJSi|*9%*@-ktIE7tPls{-tMFk z$YYod^cxNT%L&qf?XJQCOn}mX8(n?n)A*vhSWOoiqx4=fKp|5~K8s?|rME2T;|!N!(XSwhQckn^p?uL%1XH_rp51}hz4bBR;h8bZGYge z5RsipvB=JJw3+omXySLXj#V?2P=+)EJDonJDgF%eXQ-@^ZdN{Dc{iS`o}hmC6BBzW ze`PWnZIkYD{>t5KSmb(@(N=(e^0IZTcO&{MLH(9=6e_G`oj}M0#iS z%)+D7I?YJAAk-s7B$laZ1$Ek>h$K+5ke}Si()sRtSweT5D^4xDhD2TK>`wmcx_pW9cT@?acKptQ~)SJA112 z;C*a8<9j!<3=@SnQh4DXS$e3=#~9!H7(!rgVkSS!*%y4*{j8CH@BoWg=a!V>$txaa z?fK>hSx%RHZ?FnN`V|>uyYO5oid>NsxfoB{!LpK6B#E~~xF0K3%G_d=sdBn;i&Fuk zy!}oVs-*b2oD|UWD!2m?oJy;tIArM^TXVLsr}GoWVsJOK_c^|IZ~;$!iM`^l3%qsM z%-~6_EVEE!KA)d;iJB>ah?za#EbM6}jW$bHnU(X+%%NuDDvs}k7UhM(7x1&oB4*VX zGh?WkyU?_zn3>IHe5Dy(!PkDwiWALpKl@$ONlrGi{cJ=!l4f@ZL&vhlqR3I{dKtW*PmgFzd&fl`G87E6pA&%*vr=_DZvQg_(V`nem*N zKgP_QVrDf9??R=1HY{r9yM$B_MhHTWW;1t%*2gl%^&#MSJB|My~?KQXtS@e_t@b%t%qM@e-GqWvbsoM z0sgzV?LSiw)R-65m}a25_0zZ6D4q4bv$gv>tSbvThr}5*eDS;NJGQU6b>@3)uhB6E zJ@93U85{He`>6(Tz8O4L#yN zZ2qpb=xbKuXL@Gqknh<5ongSa>j#$7j&BSa$Mk1fSB8u)+f^-UnlXLyTy6HO#n(@m zH+klqrg`(US+lR6JfUgEjMCkK2VtUU2^GITMiCG-Dob zDKthUH8jngH+k-`1@q@Dn9si}G&=GQMMf+=L6|-`$#esj(7=C2Gl<_q#JM@Y-QUhW!Rs z7nJRMAVn>;w0|r5lu2^P-l~S~2_!&CU&2BXv-r_#4yBN@gkzG;f?J&%5YqI_rhja2Z-bjmq{OrrKB0&n}nc_!hNB*KkD_hqxl$RW1~? z35xDL9d@dsdk^uwUeYht&Oeq`(^e^gowo>k?yGTY72SKP?tO~>h|QlIZj?4XqS7Z; zN%@`1!B$20o;&=eqI=I!{!r0>REsdRn%9nsxar^V%SIR(S-&c-UUx}rYD-OP$Co3! zwh;H-x|X3iCv1Koxio^cq7P_m)rmo2MXwQJb`OYA<$GU;7^vvpH!sF1y7vu_xr$!4 zS?V9HVzElm|979HJ8zfJ2c%%v*1T`ZJc11J*LiORs{?WERf@bXpT4E&-dDjsS9I@- zRVNf(zSCuEn)6cEFDk?PjwXHXj3Q)jk&Za8I~9RWjykU>MU|uVite1ZzBaf}(Y-Imu2gjI8;)xg-TMyaL!jGK0_WvP=bq&SWDwnX z#T2VBanT1#iSC>WwN}wTR0h0nF@G)iGqpZyGh>f=-!wAoi@K&z58S-J%g2g=MXBN^D^03mEjyiUh1Ie-qWbMDSDr?GR8Nkem|7gj>edO8M1Y}8sqF|IW;j>(VZPR zhdxQso!vjDB4#MMvmc41xCnqxf%WcH-!A#lyq;AKDGTeBBF%Z8r0DlM^h4+KZx{3o zZ9}W1BPp)k_=604aX*6^C~VsISAJkL1lTF(eaZDxfKJ_xVMhs}y*5-EUEJ z=N$Lnl-LG-66)+HRJIpw@S>u70U!TRbT4${V@1clvIwQKt^Bp3dvOQ`Y6VqL@qeC< zrXV8~!>e-;p;O8{{=_)cc$JjXyjwyS@z0QLk5$>;hlFz!-HThIPj*sEaNd=yRxM$j zqIXwgavDj&HdNK7OpSy{8ABRdg@pCn<@V zc!q{M8)Z%YL_jCsy*tz~MfdLV(KnnB*|C~)TBDH%`?u`)STO^Kn(qY>|Qb_>**Kj=B{n1)b_+#9GPNs`$I} z1C408m#A#-^U^UQd&qpDHLN*@YdTR_t;DYAQX+1@92`xM>sJRd%w z=-#LKpD4N)8S}L)6n!U>>drap)A2f$>rJ>PFXAuJPZwT`AA10pDM0QMAjLgi(Y;%= zGlcR?%{jH-nSWO(elHfNS<%<2UhLeWJS6BEf33+#wO>_CUW~*6MfYyqA5rvYYh-nH zRJHn}qI+?LK8(*)NbeqbI_T)deAGlEwKk@hyboo%f{r$)6{y81rdM(G<4;UP97l?u zy6H;V`%vO$MfaZ3bsy;bvmr)gqV|Yl@jhtZqv+m;G_NbV_j5lVfS$@SwAVee(3iqP z`zOk#KC8Nj(`OSuDw6eE{;RqFZVVovirjtFROyFJR%Q zqI;1nzEsKo{ursCntpQee^h1Mqh_iqnXkoo;bip1PL7;HyZoxMFI03d3VVp6d!KAv zq3GU++%w^?g@9uZ8zGfVRZg$x zsZ%h*KB&~q@yrxY@V>~_pBK|_?E!F+XWr@bBc=SD&o2x0Cxuv(nI;46eIq2O=w2vI zhN53kES(&K*`2OZMW+wI()GEDPY>RF4R%NxRJIpRIziFBnC}_931V3{sBAA#=oX>X zz8BdP=x;rddDsyj6H47O zMfW}`T|;^>CVCszddZ)rd9gd&dEaS9hVKRBi{ZJGc2KGIK8XAesfLTYJ@xl9-vSMG z1lu}PGVePVMT+jlH&-kAu@SOJT(!Y|itfeh4_9oO1`<(TDMfV~Ao>z2e=6y+EmJ;w{wU)F#G2M8Xg*^{jTIbI) zR;9CJA%1$5QI*(;)}2IZ3D0#zlHHU%c9=PIc~;o!?yk zERh=)%SPb*j&A*VwPEY}r+o1mqdL)P)SLMeYmDA_x^j|!p5(Q+8oh&e?~t-@e$8*V z)#w_Wut6?~D>C^WO5eI$rtfa#r;$#~NyV-`u3X;zHltf&w@YQRkvDJE^ZDkjx{tTq sW<=Xp`l@NREvDCgqQG4wMp+p4ftGtxhO3|t{ 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�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 diff --git a/progs/basic.onyx b/progs/basic.onyx index e7a0c5f0..fdba0aec 100644 --- a/progs/basic.onyx +++ b/progs/basic.onyx @@ -37,8 +37,7 @@ main :: proc #export { b := 1 + foo(2); print(b); - if b == 13 - --- + if b == 13 {} else { print(1024); } diff --git a/progs/test.onyx b/progs/test.onyx index 6214b278..1522bf3b 100644 --- a/progs/test.onyx +++ b/progs/test.onyx @@ -24,11 +24,11 @@ local_brute :: proc { c := 123.0; { - a := 5.0f; - b := 12.3; + d := 5.0f; + e := 12.3; - print_f32(a); - print_f64(b); + print_f32(d); + print_f64(e); } print_i32(a); @@ -91,6 +91,8 @@ main2 :: proc #export { // } main :: proc #export { + local_brute(); + print_i32(clz_i32(16)); print_f32(sqrt_f32(2.0f)); diff --git a/src/onyx.c b/src/onyx.c index b7c24e29..93824ca0 100644 --- a/src/onyx.c +++ b/src/onyx.c @@ -60,7 +60,7 @@ typedef struct CompilerState { bh_arr(const char *) queued_files; OnyxMessages msgs; - OnyxProgram program; + ParserOutput parse_output; OnyxWasmModule wasm_mod; } CompilerState; @@ -154,10 +154,10 @@ static CompilerProgress process_source_file(CompilerState* compiler_state, char* } bh_arr_each(AstBinding *, binding_node, results.bindings) - bh_arr_push(compiler_state->program.top_level_bindings, *binding_node); + bh_arr_push(compiler_state->parse_output.top_level_bindings, *binding_node); bh_arr_each(AstNode *, node, results.nodes_to_process) - bh_arr_push(compiler_state->program.nodes_to_process, *node); + bh_arr_push(compiler_state->parse_output.nodes_to_process, *node); if (onyx_message_has_errors(&compiler_state->msgs)) { return ONYX_COMPILER_PROGRESS_FAILED_PARSE; @@ -169,8 +169,9 @@ static CompilerProgress process_source_file(CompilerState* compiler_state, char* static void compiler_state_init(CompilerState* compiler_state, OnyxCompileOptions* opts) { compiler_state->options = opts; - bh_arr_new(global_heap_allocator, compiler_state->program.top_level_bindings, 4); - bh_arr_new(global_heap_allocator, compiler_state->program.functions, 4); + bh_arr_new(global_heap_allocator, compiler_state->parse_output.top_level_bindings, 4); + bh_arr_new(global_heap_allocator, compiler_state->parse_output.nodes_to_process, 4); + bh_arr_new(global_heap_allocator, compiler_state->parse_output.functions, 4); bh_arena_init(&compiler_state->msg_arena, opts->allocator, 4096); compiler_state->msg_alloc = bh_arena_allocator(&compiler_state->msg_arena); @@ -214,7 +215,7 @@ static i32 onyx_compile(CompilerState* compiler_state) { bh_printf("[Checking semantics]\n"); OnyxSemPassState sp_state = onyx_sempass_create(compiler_state->sp_alloc, compiler_state->ast_alloc, &compiler_state->msgs); - onyx_sempass(&sp_state, &compiler_state->program); + onyx_sempass(&sp_state, &compiler_state->parse_output); if (onyx_message_has_errors(&compiler_state->msgs)) { return ONYX_COMPILER_PROGRESS_FAILED_SEMPASS; @@ -226,7 +227,7 @@ static i32 onyx_compile(CompilerState* compiler_state) { bh_printf("[Generating WASM]\n"); compiler_state->wasm_mod = onyx_wasm_module_create(compiler_state->options->allocator, &compiler_state->msgs); - onyx_wasm_module_compile(&compiler_state->wasm_mod, &compiler_state->program); + onyx_wasm_module_compile(&compiler_state->wasm_mod, &compiler_state->parse_output); if (onyx_message_has_errors(&compiler_state->msgs)) { return ONYX_COMPILER_PROGRESS_FAILED_BINARY_GEN; @@ -265,7 +266,7 @@ int main(int argc, char *argv[]) { OnyxCompileOptions compile_opts = compile_opts_parse(global_heap_allocator, argc, argv); CompilerState compile_state = { - .program = { + .parse_output = { .top_level_bindings = NULL, .nodes_to_process = NULL, diff --git a/src/onyxchecker.c b/src/onyxchecker.c index 365a11c9..64e6836d 100644 --- a/src/onyxchecker.c +++ b/src/onyxchecker.c @@ -518,30 +518,19 @@ static b32 check_function(OnyxSemPassState* state, AstFunction* func) { static b32 check_node(OnyxSemPassState* state, AstNode* node) { switch (node->kind) { - case Ast_Kind_Function: return check_function(state, (AstFunction *) node); - case Ast_Kind_Block: return check_block(state, (AstBlock *) node); - case Ast_Kind_Assignment: return check_assignment(state, (AstAssign *) node); - case Ast_Kind_Return: return check_return(state, (AstReturn *) node); - case Ast_Kind_If: return check_if(state, (AstIf *) node); - case Ast_Kind_While: return check_while(state, (AstWhile *) node); - case Ast_Kind_Call: return check_call(state, (AstCall *) node); - case Ast_Kind_Binary_Op: return check_binaryop(state, (AstBinaryOp *) node); - default: return check_expression(state, (AstTyped *) node); + case Ast_Kind_Function: return check_function(state, (AstFunction *) node); + case Ast_Kind_Block: return check_block(state, (AstBlock *) node); + case Ast_Kind_Assignment: return check_assignment(state, (AstAssign *) node); + case Ast_Kind_Return: return check_return(state, (AstReturn *) node); + case Ast_Kind_If: return check_if(state, (AstIf *) node); + case Ast_Kind_While: return check_while(state, (AstWhile *) node); + case Ast_Kind_Call: return check_call(state, (AstCall *) node); + case Ast_Kind_Binary_Op: return check_binaryop(state, (AstBinaryOp *) node); + default: return check_expression(state, (AstTyped *) node); } } -void onyx_type_check(OnyxSemPassState* state, OnyxProgram* program) { - - // bh_arr_each(AstForeign *, foreign, program->foreigns) - // if ((*foreign)->import->kind == Ast_Kind_Function) - // check_function(state, (AstFunction *) (*foreign)->import); - - // bh_arr_each(AstGlobal *, global, program->globals) - // check_global(state, *global); - - // bh_arr_each(AstFunction *, function, program->functions) - // check_function(state, *function); - +void onyx_type_check(OnyxSemPassState* state, ParserOutput* program) { bh_arr_each(AstNode *, node, program->nodes_to_process) { check_node(state, *node); diff --git a/src/onyxir.c b/src/onyxir.c new file mode 100644 index 00000000..1002249b --- /dev/null +++ b/src/onyxir.c @@ -0,0 +1,190 @@ +#include "onyxir.h" + +#define IR_FUNC(kind, ...) static void ir_ ## kind (IrContext* c, __VA_ARGS__) + +IR_FUNC(function, AstFunction* ast_func); +IR_FUNC(function_body, AstFunction* fd); +IR_FUNC(block, AstBlock* block); +IR_FUNC(statement, AstNode* stmt); +IR_FUNC(assign_lval, AstTyped* lval); +IR_FUNC(assignment, AstAssign* assign); +IR_FUNC(if, AstIf* if_node); +IR_FUNC(while, AstWhile* while_node); +IR_FUNC(binop, AstBinaryOp* binop); +IR_FUNC(unaryop, AstUnaryOp* unop); +IR_FUNC(call, AstCall* call); +IR_FUNC(intrinsic_call, AstIntrinsicCall* call); +IR_FUNC(expression, AstTyped* expr); +IR_FUNC(cast, AstUnaryOp* cast); +IR_FUNC(return, AstReturn* ret); + +static OnyxIntrinsic intrinsic_lookup(char* name) { + if (!strcmp("memory_size", name)) return ONYX_INTRINSIC_MEMORY_SIZE; + else if (!strcmp("memory_grow", name)) return ONYX_INTRINSIC_MEMORY_GROW; + + else if (!strcmp("clz_i32", name)) return ONYX_INTRINSIC_I32_CLZ; + else if (!strcmp("ctz_i32", name)) return ONYX_INTRINSIC_I32_CTZ; + else if (!strcmp("popcnt_i32", name)) return ONYX_INTRINSIC_I32_POPCNT; + else if (!strcmp("and_i32", name)) return ONYX_INTRINSIC_I32_AND; + else if (!strcmp("or_i32", name)) return ONYX_INTRINSIC_I32_OR; + else if (!strcmp("xor_i32", name)) return ONYX_INTRINSIC_I32_XOR; + else if (!strcmp("shl_i32", name)) return ONYX_INTRINSIC_I32_SHL; + else if (!strcmp("slr_i32", name)) return ONYX_INTRINSIC_I32_SLR; + else if (!strcmp("sar_i32", name)) return ONYX_INTRINSIC_I32_SAR; + else if (!strcmp("rotl_i32", name)) return ONYX_INTRINSIC_I32_ROTL; + else if (!strcmp("rotr_i32", name)) return ONYX_INTRINSIC_I32_ROTR; + + else if (!strcmp("clz_i64", name)) return ONYX_INTRINSIC_I64_CLZ; + else if (!strcmp("ctz_i64", name)) return ONYX_INTRINSIC_I64_CTZ; + else if (!strcmp("popcnt_i64", name)) return ONYX_INTRINSIC_I64_POPCNT; + else if (!strcmp("and_i64", name)) return ONYX_INTRINSIC_I64_AND; + else if (!strcmp("or_i64", name)) return ONYX_INTRINSIC_I64_OR; + else if (!strcmp("xor_i64", name)) return ONYX_INTRINSIC_I64_XOR; + else if (!strcmp("shl_i64", name)) return ONYX_INTRINSIC_I64_SHL; + else if (!strcmp("slr_i64", name)) return ONYX_INTRINSIC_I64_SLR; + else if (!strcmp("sar_i64", name)) return ONYX_INTRINSIC_I64_SAR; + else if (!strcmp("rotl_i64", name)) return ONYX_INTRINSIC_I64_ROTL; + else if (!strcmp("rotr_i64", name)) return ONYX_INTRINSIC_I64_ROTR; + + else if (!strcmp("abs_f32", name)) return ONYX_INTRINSIC_F32_ABS; + else if (!strcmp("ceil_f32", name)) return ONYX_INTRINSIC_F32_CEIL; + else if (!strcmp("floor_f32", name)) return ONYX_INTRINSIC_F32_FLOOR; + else if (!strcmp("trunc_f32", name)) return ONYX_INTRINSIC_F32_TRUNC; + else if (!strcmp("nearest_f32", name)) return ONYX_INTRINSIC_F32_NEAREST; + else if (!strcmp("sqrt_f32", name)) return ONYX_INTRINSIC_F32_SQRT; + else if (!strcmp("min_f32", name)) return ONYX_INTRINSIC_F32_MIN; + else if (!strcmp("max_f32", name)) return ONYX_INTRINSIC_F32_MAX; + else if (!strcmp("copysign_f32", name)) return ONYX_INTRINSIC_F32_COPYSIGN; + + else if (!strcmp("abs_f64", name)) return ONYX_INTRINSIC_F64_ABS; + else if (!strcmp("ceil_f64", name)) return ONYX_INTRINSIC_F64_CEIL; + else if (!strcmp("floor_f64", name)) return ONYX_INTRINSIC_F64_FLOOR; + else if (!strcmp("trunc_f64", name)) return ONYX_INTRINSIC_F64_TRUNC; + else if (!strcmp("nearest_f64", name)) return ONYX_INTRINSIC_F64_NEAREST; + else if (!strcmp("sqrt_f64", name)) return ONYX_INTRINSIC_F64_SQRT; + else if (!strcmp("min_f64", name)) return ONYX_INTRINSIC_F64_MIN; + else if (!strcmp("max_f64", name)) return ONYX_INTRINSIC_F64_MAX; + else if (!strcmp("copysign_f64", name)) return ONYX_INTRINSIC_F64_COPYSIGN; + else return ONYX_INTRINSIC_UNDEFINED; +} + +static void ir_add_local(IrContext* c, AstLocal* local) { + bh_arr_push(c->curr_function->locals, local); +} + +IR_FUNC(ir_function, AstFunction* ast_func) { + IrFunction* func = bh_alloc_item(c->allocator, IrFunction); + + func->ast_func = ast_func; + func->body = ast_func->body->body; + func->first_param = ast_func->params; + + // NOTE: This is actually the return type (for now) + func->type = ast_func->base.type; + + func->locals = NULL; + bh_arr_new(c->allocator, func->locals, 4); + + func->is_exported = (ast_func->base.flags & Ast_Flag_Exported) != 0; + func->is_foreign = (ast_func->base.flags & Ast_Flag_Foreign) != 0; + func->is_intrinsic = (ast_func->base.flags & Ast_Flag_Intrinsic) != 0; + + if (func->is_intrinsic) { + onyx_token_null_toggle(ast_func->base.token); + func->intrinsic = intrinsic_lookup(ast_func->base.token->text); + onyx_token_null_toggle(ast_func->base.token); + } + + else if (func->is_exported) { + onyx_token_null_toggle(ast_func->base.token); + func->exported_name = bh_aprintf(c->allocator, "%s", ast_func->base.token->text); + onyx_token_null_toggle(ast_func->base.token); + } + + else if (func->is_foreign) { + onyx_token_null_toggle(ast_func->foreign_module); + func->foreign_module = bh_aprintf(c->allocator, "%s", ast_func->foreign_module); + onyx_token_null_toggle(ast_func->foreign_module); + + onyx_token_null_toggle(ast_func->foreign_name); + func->foreign_module = bh_aprintf(c->allocator, "%s", ast_func->foreign_name); + onyx_token_null_toggle(ast_func->foreign_name); + } + + if (func->body != NULL) { + c->curr_function = func; + } +} + +IR_FUNC(function_body, AstFunction* fd) { + if (fd->body == NULL) return; + ir_block(c, fd->body); +} + +IR_FUNC(block, AstBlock* block) { + forll (AstLocal, local, block->locals->last_local, prev_local) { + ir_add_local(c, local); + } + + forll (AstNode, stmt, block->body, next) { + ir_statement(c, stmt); + } +} + +IR_FUNC(statement, AstNode* stmt) { + switch (stmt->kind) { + case Ast_Kind_Return: return ir_return(c, (AstReturn *) stmt); + case Ast_Kind_Assignment: return ir_assignment(c, (AstAssign *) stmt); + case Ast_Kind_If: return ir_if(c, (AstIf *) stmt); + case Ast_Kind_While: return ir_while(c, (AstWhile *) stmt); + case Ast_Kind_Block: return ir_block(c, (AstBlock *) stmt); + + default: break; + } +} + +IR_FUNC(if, AstIf* if_node) { + if (if_node->true_block.as_if->base.kind == Ast_Kind_Block) { + ir_block(c, if_node->true_block.as_block); + } + + if (if_node->false_block.as_if->base.kind == Ast_Kind_Block) { + ir_block(c, if_node->false_block.as_block); + } +} + +IR_FUNC(while, AstWhile* while_node) { + ir_block(c, while_node->body); +} + +// NOTE: Currently, these functions don't have anything to +// do so they are empty and not called. When I have a reason +// to use them, I will populate their bodies +IR_FUNC(assign_lval, AstTyped* lval) {} +IR_FUNC(assignment, AstAssign* assign) {} +IR_FUNC(binop, AstBinaryOp* binop) {} +IR_FUNC(unaryop, AstUnaryOp* unop) {} +IR_FUNC(expression, AstTyped* expr) {} +IR_FUNC(cast, AstUnaryOp* cast) {} +IR_FUNC(return, AstReturn* ret) {} + +IrContext ir_context_create(bh_allocator allocator) { + IrContext context = { + .allocator = allocator, + .functions = NULL, + + .curr_function = NULL, + }; + + bh_arr_new(allocator, context.functions, 4); + + return context; +} + +void ir_context_free(IrContext* context) { + bh_arr_free(context.functions); +} + +void ir_generate(IrContext* context, ParserOutput parse_output) { + +} diff --git a/src/onyxsempass.c b/src/onyxsempass.c index 9c8d225c..68ea2e2d 100644 --- a/src/onyxsempass.c +++ b/src/onyxsempass.c @@ -23,68 +23,70 @@ OnyxSemPassState onyx_sempass_create(bh_allocator alloc, bh_allocator node_alloc // WASM, this function may not be needed. It brings all of the locals // defined in sub-scopes up to the function-block level. This is a // requirement of WASM, but not of other targets. -// static void collapse_scopes(OnyxProgram* program) { -// bh_arr(AstBlock*) traversal_queue = NULL; -// bh_arr_new(global_scratch_allocator, traversal_queue, 4); -// bh_arr_set_length(traversal_queue, 0); -// -// bh_arr_each(AstFunction *, func, program->functions) { -// AstLocalGroup* top_locals = (*func)->body->locals; -// -// bh_arr_push(traversal_queue, (*func)->body); -// while (!bh_arr_is_empty(traversal_queue)) { -// AstBlock* block = traversal_queue[0]; -// -// if (block->base.kind == Ast_Kind_If) { -// AstIf* if_node = (AstIf *) block; -// if (if_node->true_block.as_block != NULL) -// bh_arr_push(traversal_queue, if_node->true_block.as_block); -// -// if (if_node->false_block.as_block != NULL) -// bh_arr_push(traversal_queue, if_node->false_block.as_block); -// -// } else { -// -// if (block->locals != top_locals && block->locals->last_local != NULL) { -// AstLocal* last_local = block->locals->last_local; -// while (last_local && last_local->prev_local != NULL) last_local = last_local->prev_local; -// -// last_local->prev_local = top_locals->last_local; -// top_locals->last_local = block->locals->last_local; -// block->locals->last_local = NULL; -// } -// -// AstNode* walker = block->body; -// while (walker) { -// if (walker->kind == Ast_Kind_Block) { -// bh_arr_push(traversal_queue, (AstBlock *) walker); -// -// } else if (walker->kind == Ast_Kind_While) { -// bh_arr_push(traversal_queue, ((AstWhile *) walker)->body); -// -// } else if (walker->kind == Ast_Kind_If) { -// if (((AstIf *) walker)->true_block.as_block != NULL) -// bh_arr_push(traversal_queue, ((AstIf *) walker)->true_block.as_block); -// -// if (((AstIf *) walker)->false_block.as_block != NULL) -// bh_arr_push(traversal_queue, ((AstIf *) walker)->false_block.as_block); -// } -// -// walker = walker->next; -// } -// } -// -// bh_arr_deleten(traversal_queue, 0, 1); -// } -// } -// } - -void onyx_sempass(OnyxSemPassState* state, OnyxProgram* program) { +static void collapse_scopes(ParserOutput* program) { + bh_arr(AstBlock*) traversal_queue = NULL; + bh_arr_new(global_scratch_allocator, traversal_queue, 4); + bh_arr_set_length(traversal_queue, 0); + + bh_arr_each(AstFunction *, func, program->functions) { + if ((*func)->base.flags & Ast_Flag_Intrinsic) continue; + + AstLocalGroup* top_locals = (*func)->body->locals; + + bh_arr_push(traversal_queue, (*func)->body); + while (!bh_arr_is_empty(traversal_queue)) { + AstBlock* block = traversal_queue[0]; + + if (block->base.kind == Ast_Kind_If) { + AstIf* if_node = (AstIf *) block; + if (if_node->true_block.as_block != NULL) + bh_arr_push(traversal_queue, if_node->true_block.as_block); + + if (if_node->false_block.as_block != NULL) + bh_arr_push(traversal_queue, if_node->false_block.as_block); + + } else { + + if (block->locals != top_locals && block->locals->last_local != NULL) { + AstLocal* last_local = block->locals->last_local; + while (last_local && last_local->prev_local != NULL) last_local = last_local->prev_local; + + last_local->prev_local = top_locals->last_local; + top_locals->last_local = block->locals->last_local; + block->locals->last_local = NULL; + } + + AstNode* walker = block->body; + while (walker) { + if (walker->kind == Ast_Kind_Block) { + bh_arr_push(traversal_queue, (AstBlock *) walker); + + } else if (walker->kind == Ast_Kind_While) { + bh_arr_push(traversal_queue, ((AstWhile *) walker)->body); + + } else if (walker->kind == Ast_Kind_If) { + if (((AstIf *) walker)->true_block.as_block != NULL) + bh_arr_push(traversal_queue, ((AstIf *) walker)->true_block.as_block); + + if (((AstIf *) walker)->false_block.as_block != NULL) + bh_arr_push(traversal_queue, ((AstIf *) walker)->false_block.as_block); + } + + walker = walker->next; + } + } + + bh_arr_deleten(traversal_queue, 0, 1); + } + } +} + +void onyx_sempass(OnyxSemPassState* state, ParserOutput* program) { onyx_resolve_symbols(state, program); if (onyx_message_has_errors(state->msgs)) return; onyx_type_check(state, program); if (onyx_message_has_errors(state->msgs)) return; - // collapse_scopes(program); + collapse_scopes(program); } diff --git a/src/onyxsymres.c b/src/onyxsymres.c index c363c396..02774125 100644 --- a/src/onyxsymres.c +++ b/src/onyxsymres.c @@ -314,7 +314,7 @@ static void symres_top_node(OnyxSemPassState* state, AstNode** node) { } } -void onyx_resolve_symbols(OnyxSemPassState* state, OnyxProgram* program) { +void onyx_resolve_symbols(OnyxSemPassState* state, ParserOutput* program) { // NOTE: Add types to global scope symbol_basic_type_introduce(state, &basic_type_void); diff --git a/src/onyxutils.c b/src/onyxutils.c index 26a384f3..09881374 100644 --- a/src/onyxutils.c +++ b/src/onyxutils.c @@ -35,7 +35,6 @@ static const char* ast_node_names[] = { "PARAM", "ARGUMENT", "CALL", - "INTRINSIC_CALL", "ASSIGN", "RETURN", diff --git a/src/onyxwasm.c b/src/onyxwasm.c index b67b091e..8dc425b4 100644 --- a/src/onyxwasm.c +++ b/src/onyxwasm.c @@ -209,7 +209,7 @@ static WasmType onyx_type_to_wasm_type(Type* type) { } if (basic->flags & Basic_Flag_Float) { if (basic->size <= 4) return WASM_TYPE_FLOAT32; - if (basic->size == 8) return WASM_TYPE_FLOAT64;; + if (basic->size == 8) return WASM_TYPE_FLOAT64; } if (basic->size == 0) return WASM_TYPE_VOID; } @@ -296,13 +296,13 @@ COMPILE_FUNC(statement, AstNode* stmt) { bh_arr(WasmInstruction) code = *pcode; switch (stmt->kind) { - case Ast_Kind_Return: compile_return(mod, &code, (AstReturn *) stmt); break; + case Ast_Kind_Return: compile_return(mod, &code, (AstReturn *) stmt); break; case Ast_Kind_Assignment: compile_assignment(mod, &code, (AstAssign *) stmt); break; - case Ast_Kind_If: compile_if(mod, &code, (AstIf *) stmt); break; - case Ast_Kind_While: compile_while(mod, &code, (AstWhile *) stmt); break; - case Ast_Kind_Break: compile_structured_jump(mod, &code, 0); break; - case Ast_Kind_Continue: compile_structured_jump(mod, &code, 1); break; - case Ast_Kind_Block: compile_block(mod, &code, (AstBlock *) stmt); break; + case Ast_Kind_If: compile_if(mod, &code, (AstIf *) stmt); break; + case Ast_Kind_While: compile_while(mod, &code, (AstWhile *) stmt); break; + case Ast_Kind_Break: compile_structured_jump(mod, &code, 0); break; + case Ast_Kind_Continue: compile_structured_jump(mod, &code, 1); break; + case Ast_Kind_Block: compile_block(mod, &code, (AstBlock *) stmt); break; case Ast_Kind_Call: case Ast_Kind_Intrinsic_Call: @@ -453,8 +453,8 @@ COMPILE_FUNC(binop, AstBinaryOp* binop) { WasmType operator_type = onyx_type_to_wasm_type(binop->left->type); i32 optype = 0; - if (operator_type == WASM_TYPE_INT32) optype = 0; - else if (operator_type == WASM_TYPE_INT64) optype = 1; + if (operator_type == WASM_TYPE_INT32) optype = 0; + else if (operator_type == WASM_TYPE_INT64) optype = 1; else if (operator_type == WASM_TYPE_FLOAT32) optype = 2; else if (operator_type == WASM_TYPE_FLOAT64) optype = 3; @@ -961,8 +961,6 @@ OnyxWasmModule onyx_wasm_module_create(bh_allocator alloc, OnyxMessages* msgs) { .export_count = 0, .imports = NULL, - .next_import_func_idx = 0, - .next_import_global_idx = 0, .globals = NULL, .next_global_idx = 0, @@ -989,7 +987,7 @@ OnyxWasmModule onyx_wasm_module_create(bh_allocator alloc, OnyxMessages* msgs) { return module; } -void onyx_wasm_module_compile(OnyxWasmModule* module, OnyxProgram* program) { +void onyx_wasm_module_compile(OnyxWasmModule* module, ParserOutput* program) { // NOTE: First, introduce all indicies for globals and functions // bh_arr_each(AstForeign *, foreign, program->foreigns) { @@ -1015,7 +1013,7 @@ void onyx_wasm_module_compile(OnyxWasmModule* module, OnyxProgram* program) { bh_arr_each(AstFunction *, function, program->functions) { if ((*function)->base.flags & Ast_Flag_Foreign) continue; - + if (((*function)->base.flags & Ast_Flag_Intrinsic) == 0) bh_imap_put(&module->func_map, (u64) *function, module->next_func_idx++); } -- 2.25.1