From 334622ed8766396049366050abb2976024cd4100 Mon Sep 17 00:00:00 2001 From: Brendan Hansen Date: Sun, 23 Aug 2020 21:17:54 -0500 Subject: [PATCH] added initializer to if and while; added else on while --- core/string.onyx | 12 +- docs/plan | 14 +- include/bh.h | 2 + include/onyxastnodes.h | 40 +++-- onyx | Bin 170368 -> 170368 bytes progs/wasi_test.onyx | 388 +++++++++++++++++++++-------------------- src/onyxbuiltins.c | 26 +-- src/onyxchecker.c | 25 ++- src/onyxparser.c | 62 +++++-- src/onyxsymres.c | 44 +++-- src/onyxwasm.c | 85 ++++++--- 11 files changed, 415 insertions(+), 283 deletions(-) diff --git a/core/string.onyx b/core/string.onyx index e414f022..c3b41433 100644 --- a/core/string.onyx +++ b/core/string.onyx @@ -18,7 +18,6 @@ string_make_from_cstring :: proc (s: cstring) -> string { return string.{ len = len, data = s }; } - string_length :: proc #overloaded { proc (s: ^u8) -> u32 { len := 0; @@ -82,21 +81,18 @@ string_split :: proc (a: Allocator, str: string, delim: u8) -> StringSplitResult StringBuilder :: struct { - // FIX(nested-structs): This should not be a pointer eventually. - // Currently nested structures cannot be passed as arguments. - // When this issue is fixed, change this to Allocator. - alloc : ^Allocator; + alloc : Allocator; data : ^u8 = null; len : u32 = 0; cap : u32 = 0; } -string_builder_make :: proc (a: ^Allocator, initial_cap: u32) -> StringBuilder { +string_builder_make :: proc (a: Allocator, initial_cap: u32) -> StringBuilder { data: ^u8 = null; if initial_cap > 0 { - data = cast(^u8) alloc(*a, initial_cap); + data = cast(^u8) alloc(a, initial_cap); } return StringBuilder.{ @@ -118,7 +114,7 @@ string_builder_add_string :: proc (use sb: ^StringBuilder, str: string) -> ^Stri new_cap := cap; while new_cap < len_total do new_cap <<= 1; - new_data := cast(^u8) resize(*alloc, data, new_cap); + new_data := cast(^u8) resize(alloc, data, new_cap); if new_data == null do return sb; data = new_data; diff --git a/docs/plan b/docs/plan index 0cc1c40c..0a230bab 100644 --- a/docs/plan +++ b/docs/plan @@ -187,6 +187,18 @@ HOW: [X] returning structs - This will put forward a lot of the work that will be done for multiple return values + [X] intializers in if / while + if err := some_function(...); err != 0 { + print(err); + } + + [X] else on while + while ... { + + } else { + // Loop never run + } + [ ] 'use' enums and packages at an arbitrary scope [ ] convert to using an 'atom' like table @@ -201,7 +213,7 @@ HOW: - struct member names - array length - [ ] Make the lexer much faster + [X] Make the lexer much faster - Technically it isn't slow right now - But, profiling says we are spending 50% of the program execution time in the lexer - That is awful diff --git a/include/bh.h b/include/bh.h index b0633fc4..d1930ca8 100644 --- a/include/bh.h +++ b/include/bh.h @@ -162,6 +162,8 @@ u8* double_to_ieee754(f64 f, b32 reverse); #define bh_align_of(Type) bh_offset_of(struct { char c; Type member; }, member) #define bh_swap(Type, a, b) do { Type tmp = (a); (a) = (b); (b) = tmp; } while(0) +#define bh_align(x, a) if ((x) % (a) != 0) (x) += (a) - ((x) % (a)); + #define bh_pointer_add(ptr, amm) ((void *)((u8 *) ptr + amm)) #define BH_BIT(x) (1 << (x)) #define BH_MASK_SET(var, set, mask) ((set) ? (var) |= (mask) : (var) &= ~(mask)) diff --git a/include/onyxastnodes.h b/include/onyxastnodes.h index aefd7c78..c9814df0 100644 --- a/include/onyxastnodes.h +++ b/include/onyxastnodes.h @@ -30,9 +30,8 @@ typedef struct AstBreak AstBreak; typedef struct AstContinue AstContinue; typedef struct AstBlock AstBlock; -typedef struct AstIf AstIf; +typedef struct AstIfWhile AstIfWhile; typedef struct AstFor AstFor; -typedef struct AstWhile AstWhile; typedef struct AstDefer AstDefer; typedef struct AstType AstType; @@ -248,14 +247,12 @@ typedef enum CallingConvention { // Base Nodes -#define AstNode_members { \ +#define AstNode_base \ AstKind kind; \ u32 flags; \ OnyxToken *token; \ - AstNode *next; \ -}; -#define AstNode_base struct AstNode_members; -struct AstNode AstNode_members; + AstNode *next; +struct AstNode { AstNode_base }; // NOTE: 'type_node' is filled out by the parser. // For a type such as '^^i32', the tree would look something like @@ -268,13 +265,11 @@ struct AstNode AstNode_members; // // 'type' is filled out afterwards. If it is NULL, the Type* is built // using the type_node. This can then be used to typecheck this node. -#define AstTyped_members { \ - AstNode_base; \ - AstType *type_node; \ - Type *type; \ -} -#define AstTyped_base struct AstTyped_members; -struct AstTyped AstTyped_members; +#define AstTyped_base \ + AstNode_base; \ + AstType *type_node; \ + Type *type; +struct AstTyped { AstTyped_base }; // Expression Nodes struct AstBinOp { AstTyped_base; BinaryOp operation; AstTyped *left, *right; }; @@ -308,7 +303,6 @@ struct AstContinue { AstNode_base; u64 count; }; // Structure Nodes struct AstBlock { AstNode_base; AstNode *body; Scope *scope; bh_arr(AstLocal *) locals; }; -struct AstWhile { AstNode_base; AstTyped *cond; AstBlock *stmt; }; struct AstDefer { AstNode_base; AstNode *stmt; }; struct AstFor { AstNode_base; @@ -323,8 +317,13 @@ struct AstFor { AstBlock *stmt; }; -struct AstIf { +struct AstIfWhile { AstNode_base; + + Scope *scope; + AstLocal *local; + AstBinaryOp *assignment; + AstTyped *cond; AstBlock *true_stmt; @@ -336,9 +335,12 @@ struct AstIf { // without the 'next' member. This is because types // can't be in expressions so a 'next' thing // doesn't make sense. -#define AstType_members { AstKind kind; u32 flags; OnyxToken* token; char* name; } -#define AstType_base struct AstType_members; -struct AstType AstType_members; +#define AstType_base \ + AstKind kind; \ + u32 flags; \ + OnyxToken* token; \ + char* name; +struct AstType { AstType_base }; struct AstBasicType { AstType_base; Type* type; }; struct AstPointerType { AstType_base; AstType* elem; }; diff --git a/onyx b/onyx index 0acd7e5597013097b9412cf2746d829cd57e7b50..4775a53ced31956564e0e8af7153bb33f6b3f45d 100755 GIT binary patch delta 47422 zcma&P34Bh+_dov3NGcILAuEwZ5)oS@2(g4jf+xgMv2V3ksXajvk4S>Y#KKI^ikI(n@`{(sa?!D)nIdkUBnKNh3%)ObJQ*LHX zxh*cN+?{Wkfqw3MD=M>yatlYQPlkmfMSHft^1?D)eJ;L=s(iPn=l7@PZ@=`*j6rdY zk9p;_+u%F^J3IU9NdPlUcIDkL6 zBfhRUfF%l7V|~8-u4rbAV6ox@<7MU};@y3!ME|LYG^MXrxr-)}p@SF?Y=0d)*8%G; zR=fKoP1LcUI$-DM@Kp}*6*_!_13X5sNSBD2Vz+dQm;vC?=YV@@YCI`fAolzGDxSQBo*~gr(V+T55U+VA?4)C%MwdRd; zfS=OgQykzPI(()BJWPX&b{>_gG}UPqI?zOj@g6=^TI<+V4p@^|4Qw|ZyTt+9N1XSl zZyuy$k2_%B*Wu?J;A3?76$ki19e&dRZr0(71ALwaHya*1Af#U4r2~AO4mb2KZ8ckT zxQhdPuMT&2fFIN0zAD^oFcc2$^Ex8Pp}SRFgg0c#SKynW2wbnHwA>>wRJ*8x68 zhc9%1Ptf6?I>4vu@Kp}*Obu=}Y;Zs<(hF>HfUnZwJ00L_b@%}X_*XjoxC8tf9ez%Q zwt$nf>4viz>rsV@hY zw#rzs)%PpRD7~ww)62XnRA5(?_o#H$ssq3)XKGbUN0^pA^BeU}(2K8`A-+eF<@tU? zoWT&^J-%Ca%YQ$(qyJM(Hvd|wqDF8EADSwr2G@4I@+mWzY|ig~ExrkE!TN|lgPVA{ zr7^=U5+&L4XR@Ur*>YETnJOBG)UNkqDyXeXLO+Fo$wN+?Y_V6bF+;M=`6u<_bqN>K zkk&7gZT@Gj<=8^%G4{RK6B@xM{wDH6Yw~6bg=dW(RR(`XZ1#r6lriACEi{gH9rq% zIb&qU#<1L&S9O}IhHoFO_ywhsyeCVu90r-J%vWlc6OeNOD&4My<0bHtX0A!1L1T0t?p z42J9j#;l|8Jb8(sp_o?2#!xW>cz&zUOOsm2L>Or~&elGJhH zWM;7Ezbq(7vRqHHJhIRF2U@hnULOF3Jy&hmewIL)hkOA(S_0hgRRJvfAwlz0?e>~3 z);9?Y{Z@ObH3N*l{hRt^Tj)a4k}YeA|1G;C)82{ri)cg z8@oPVLQ1b-UXpX8>1oCnrsjOx{2=EQrss@rS&i`peRCGH`m#K4wOAbM6p)jW99V{L zUY(QLIiB$!R^{Y&S;csb5u$h3e*E%Ck=ykI`#dKjr7h#z+vJ?+Hi7Z@L=oGgGg~NZ zJ>vPd3F2H28xKqn@AdqEZ)+`1_PoS@ixH39>T8=6cq;4 z5P7}Lym6c`^;ybSwh}k`M3wun6*CMsK02_!p%~ZKUo`1kpL@3wBl>pYJ;KD!zENBZ zP)oY^3*;SJil}~B?nA|9f8e-Ck?UmHFwR#fSq!rf!VnEp-qPc6j8{)5?gvATDd zm@==tXgMIHoL>vQR0DCoo1d6H;8Q-JxnQF`MWgq|^UKY|SMTNc9%=@I->DjnWNH8O^UW7VC#}_en*G>F2>=pmGp?ExeIe*eM$M*gK&g(~t&Ldm$1(7)mMm}Tw zvj~y(;WVCJ4^5fQ3+f8<=xxj{8jab?We0I@Oei1UK~xw!l)H5h6UVORBWerpae_~* zEjEp-&bQQ3`|H-YDLlBA=r=xvkFF)Qj`!nR!o`{KTls%AMaG0q{F`>-{DhPI_qO7T ziOu-BFck6@k0#FN_HiOT^?ep2?xfb`ZehYBEoq>&XQZ{+@Qi{6%s6L1hPN>{FZLa% zbW+uNWpT-TS!Z$ttkiWdjCF`phKU_7xS9E~-sEYSFM}p|ns%dzf!BkQjcX4XXI;fp zo2WlB3!0}*ecq-QON$eo##9%vlLHg_CR=XykM9@XKYqYrV_+7Q1NQ-`6Ej~D1 z#;Dc1XS{MH5wo|wV=#2I+#McKr~|bf*@xZ~6o|-FPtkI6O|vQw*X03Yhy>pMQ=A}( z6si3DKox+LWQ9!0mQiZ`P9{r&T78mbK%BKm1P&3BEWg>iKp{ms2tpH;kAq1EW{mH0 znw~Uev0WS!9)kR%~7ZD;`tRbH=PxJW~;0 zy&w9bz<#6N59#1nBm=b@4K*t+svM6F{I9-1WmJ3dD5lO!kas}fP2kxDvA zW9=TPc11=r7qt^YA%dp&>zLV0w$|YpQ^UC`QulCEGfSIDWAvi5+ex<7%f*6O=~`Xvm{Pw=#xEt>MB=InQ_5ARfoQIvs}k}DDQ!TC-tyhw zOl=iRD8YryCrGJ7OwgFa`OsEf4NH8&l}b8hBQS+6i_C0R*ODSLE_9ufhexQvz+VoN<-prdU>wq!4 z7ZhWi8csEuEYKdR$|xXh8ME8cU#L*ro9Z7_i4?d$$&wuEYyTBMncoTNeK~Km<+;G}otk zEswO0TKtcu4qtmC$XPf}O_>Lo{ar99bTITRF>FniL-y19H5K^GsqhWi*(kc7yb>w+ z+|NXISTng?Rma^UNn^uJ#xaMiUB%vMjlxF&p7|=)nDrhJpj4g5B*)PrMUg2f&;5n( z^m=Y#L|lM+9=#M@rdQ!>{l%#1gQ~|VsE7vPmk5NDENw9Q(+#_QNgr@@N_BtnV0xHm zZNyWhx!$WLYNpqzJyk807#as(-M7$LCtGf3ywb*vHwvl-R+oI0*{4Vqhr%Q*k>>km8 zF+)oUE=o^=6b{EY($O71J$Q(vh8Oxz8gO}rN&w}>g?r*s=s^@Oji);Jtf&Mxk;^U$H)QI|N_E5WJqF&|yy8#=)L2rO2|EB~fC4boeKl#l? z4d|iqEZu|d%~gZa|kJ{`BJiQUGH z{U@!@B9+~Hw6dm5QErA`E$0u&w$dXh$WrF&I53<6hQo_zx#0^%ml>XZ;Z?PsiQfqy zYS@Lj3cY~xvBtZ?Jj2_q;0~j12~r+56{}`M@PG^A+>8+Z!C&I<87(UBIZxhFwM>K% z24&NEkziiOQ=f@H&4K*(IpH?5A@AfX;%2t-EBgngA8WJ=F3RgBSP7Na$6}{*V%1Df zKDvw8F|&T%7v~BJFkZ5I(wMVF$6%?3&QWfv;IzE})z?9%&xuMIP575*Mf;3~p<~ZN zxw_M)Y4<%m7j>d)5f8k@>I^@(E8Q3@*C|xFr-;0ajL4zCW62OkUQLfvY|*zmX_bBi z9@z)dx}(y|I%xP=F=bX1PdFns%?j`cIfF_gwRWJdO-ki6;`*$SA;WJnL&hr~Vw(LL z<8D9QQZsC)Ar-D|?uidFV|c!&SerSV-~Lg!WkvCEH$=-U-&&15|5ul&VN+~XFeW2| zB7JTOb5?-yQA4P5nl>tw)<25PSpodeZ{o+SI(%tE@lVzizQ;pM%{VLGlmbGdnmu=OnD{L-MD22{EV$>-l=`{YssghM)u9EF3VUUS%<8 zc5t~9?KRcCdrH`52ZkCzXFmi>-5;Wh7y)jDZkYNh;G{S=yE<<^P&}L6wd}F}u#Uwi zMe>{g@8Ih&*o8$R22m{)D~XwNs`ARW#piQ^`5AX{U{2kRh7;71*k#v|W3c=Q)kxf_ zGe-%lR;Hq#w8$^>RY+Q6gmC*CC~CMGrW7@~189nyd`xMc zhbDW9%c&Itd-bQm+D09$R(A+y%xVJ$_V@8eX>JtHEMYw5uJD`Jm^Y8WLM}>V&GR#^ zz&x%f6?C79Ja>O@V@0S(cRxXj-!XAlD-NcvkLt4~00uHsbPA500cmiOb{kmwnRubRJnwGhL|=mWA<7C7kP+Atx0P)l#Qq@**Y!Kax~uRW6V7iD-svf3z>EhZ7-t^ z`5Q@)eiWWf*5)SbM1694*+(Ue^uslyVAT}**%~#eGj~31@>r<1|k|G}W^%4QXO?k!A5op z#=f%A$)Tr{0WBPPiq%Q1U9z69-6J|Iomw_8xTJ_~;{H;9etWlY`=qV^^4+Ay6ht#^ zf~?&B1txtpf<`~YT@qtH8Bl!%@(uX#>tj$q3+5?m_)J_cctvKABt7@9-sXjf|;F=Saizhv|_MU;tJ?Cc8*+3!xy(IY%()3T2k zS29J|@_=enYB588Bh42jS=(fjlE{9rS&?(>!Wc!p^EMF>x+ zDMo!!)2}_2%_MGRU0hX!WXn^fQmFXmi(u|wQ=I=|a1#rd6;|IrMy-B0E=tBs@b8B| zC1RI_rtE^$Mo_A6Q!#Qy61T^Q?JGv{Ph&*z%Gx~cAJJ*$7XIbQcP~RjZPlM1H>WdWsD!*4F427E3Xd3`+jJb)S-taY3@Su%K%OR8M zLx=l_@YPFr-Ns`7>Nbzofj_2Ai#%C=RExxSFLp{aF zFY8wh@h5|M2OM6StW#VRkELSMmz{XSzr^b=zvK^|iq-4V_$0b`iF)h(dF!Vld3`Is zHA>jlSLKZ&#m4m^ZGvbXv>Zg!p6|n*HTnfEQ3v|k-$yE@(8F2HF3M!;Fq_xEmWD=<-;GAK-w=|=iS4A}1@FA~OO|02agV(4gPHd>g^U`weZTOgZ7bFt% z|KhtPS^ny7viwBbDnq^z*025ejySR5>uP*%qB!<-2p^It^1t>o<2-;tc{fh&4maGZ z>Ux)Q2NvfGJMoO_-4G#%Ym2JGltMLS-bdr2{Xia7V5~$b6<7%^)eHrxp}vK`%1Nw2 zD7eo50p8Ic)VtNN(-u9a9vItVZ@$aS2BpnJ@=mBxWo?N~qgt)84{^~PyRnw@Ry@qC z@IC%AlO?*ZN)dgDE*7uubg_BOR-Y<##zhOxYdLqoJqmZzF8y(_e~PKJ(4TgPyQyvY z&t!=W0ZLhcl^S*id|J}RL28-)hZoXpzo8*P``ZmI#h5MLX5*Z1X)M^hQm6?-oMxHW zxq_RT>o8@ehZ|B&kp25yYJ%5A^%A`q7iBD|I5P$UxADcSYs{KKVY{_^5USs#(oJwt z=EW25^l&9ZwW#z+Wdjx)2<&2L96Kw0%xaXLYVioQ8D4&`CUpKV2|ET`*>? zz`QPQed{6q+v4gPftUkzKH4FSTSH?H?x3eG5DRpnptH6|xv5IBZA6^OI^l7mEuN{J zf~ZrugajRm+SD?!Gj@n^TdQ|ZfO^mg27~>D78YjVURMS!a4=YY0|Ls4QQB$EjzI`= zoM5DZWZSTCW7aM_s-{FOe*B;KZEK*}3K%`+Vcx(J<#LkMDb$oX#T`Wkx~J{6k5bFb zRBOvj_XX45#MB0r96?J^afd>##T`6yJGH^fs$Qap;-b`q-IVHJS}B>VX0?ZhsD$X@ z)~)nLHHA2+BvKiOO29bAkm{2VNbmqrt(l*f&I6aEx=oml%eRf2Mw1h?^| ztVhnEgaoO*$-K<4ue&NOYClRcl6~DL*{Js0+D(jdRh2e9PFVy^*xRXf#Sx9KvH&p% z)X-Li>HT7LUPMeSW%HM-7KV;i-nU~%SM5YKto+&j6H1shlY=FMEA1Q!D4(jEq}4fI zV`x7Gbz?E(9Hl=`MD+_(;7~DCUaNVT03M@2ioG0PAugMA$v-2q2AExD58P)7e zwqEXOUxQ{yQJMTx>WtwP4~WU)Zm)~czfkd09Msty;Nr9d%&!vBTVrp1PnYQ1xG3w% znfXkOGqdihW(G7S<$fY#$64R|-@;*6hdR}46tx2Y<>$*{L~e(6c7)+k z1qI`R3dZ>sjB|&3o)blVk6p2fFbmCgv=OaNNf|0V)mpMlig=a#0k8E~4BJ_w(jlZc z)V??pq)O3REZ<{GX%m!(T4*k{cN4Yt zM0!j_6koc9zl#s|^baXBj7Ga5zGr+7^^`;kCS6}x&8V+Q|L&OgJ`(r$bnvQ2&z1__ zxMaR8KY0XZ+HZqI^4|9TJ2p~f(_BE_#XXf~h`j`{VpS0Ry~x>Xs`!EWjOiOIxEdRU z>%K;VUu>Z80m~B0A?4z2b%_#04IG?gorGq^mPHW?N$)j)aXxSB9F)2x$vPuQxrZ$j zT1TveZ%(qdbUn0}597KIl4T|6$DPp^Bc0V5WKWRg^Gh6~M&cii2?bE_rEd z>}P=Q!mVL<5dJ{QMF1#SY6dM020xG#XR?fQF_pJE&sM8N6=~wi4^7x;;eH^%Evyje z6)Bn?Na3rhiH{G|Fl}825iL#ZX)r&y3NoSCF91`vkiAjQ(TDPK~1V}HSA7p0tbQ!>hwdDKNYc3Mn17|^QiR8==Gsh6-Q0_|S4 z2u0ZAT&VwwhL6&$J~b3^H0)MYnCn#W)4@9CZfc1s?n(+2YR|x!DD>p2@NIxrdSS?* zyMjn5X@(_66gsc;D83d(jldA~qPon`LVTf_ zok!NW^dS1Kkl2ppWuahRTi2?JnWbK$GjUPcVuQ+LO-8R<;=}FUV2#EW@~!k1-=2kh z#hXKm*@t4$;r3O|S7nAGeMMoaj7NZvRc3GT*Wrd?&TFX7=yz~Y?AO5_`aq(Hk_SrJ z%$H%4eK08{i;hSB3vT_B8lvo19h!AYkP@YiK-jA0FoSQ4506%7KZuWyZs9He5OK%4 zSNdwDIv`QQI@~EPF=G9(I3D(gP>yxxZGI6=^J41dgAJ+w7YdxL(_EB3snkp)d9cEB zr!L1sI65~->2gb~$P3~Dsp3GMPnGT~u)d3W0Ol#UQyTw5;^!$JUlEVnFCRc1q6lpencmy=B^=A#k_ zcpn$#?9Za}$yNM|v*O7~?+V$!QpL?F!8P?);dv^$aTyF2)r2~#+elD=wvw6VRiX#& zX(|$9K|}Ts=2O-96HoEQsX%`2y4ZgzIQT<NjD!qK*h5~Sm3GSQfRPdHb?IqA5}BHRkXVex`Q@4H&t z-Y>$hAsiNjn1XbiM-i?I;V6r&Own;KFePY$ zwji95aQ$@LwL+XZHk^>|gpAXXKNKQkeF#T8d`hT}qdcm{)QNDF3Fo5Y<`m)X!F2a{ z5biz>MbIc8RfM}pINB~$&H-m8WalE}4}|n04Ew z_Zr?#6Eur(lm}1->bM(4xbbE}Rv~1fjyzn1>`yq@G(t}uhpAp?+MaOL2v=UmS&MKn zgu_@gD33d9tsh&23nLuOj>;t!XEtV~6d}C{S(T7G^@2@`aAgP=NVv~+oL>>{ktc9L zgqx}3XfdL-{u<$`6K<%EyIq9)(G#hTJ;8)D>Bzhyuc~n z1gEVDWr+s&(ctX?S26&~e95X@%e-CN(mw{Lag~4%D3{wUG{}C5+@a<_qmXhzCLvT@ zyWm%`u~5Br6I_(4XN1$mP&QxGx)>4B22@2Z(r$iSP|#JKG;Gl+r7**QQA{HH;vaG1 zGBrBQn?j>Vb@p0>!wO{O%ix;`8lyr-sdUDy!x+KE&|yD|jhC9RH1YeTs+e8=y%e2v zO`U&XCNTE+%;}-wI9Rr!6f28fK?IG3vP3AR_4*5TuSoL%JCTn!y*N_CjzVj$5PYex; zf1ViXD>ZyK+AwLCXjk+q z02Hx9Y`XG0a}l;*{5@`+p_Ri?s!!{f^Jm1qUxE<=-~6STXP2^$(OOHRaKBoOD`iE* z)v6wej-?x(5q+-)v$JBxRX?B0Fo(B;L(HgG8~KfZS61iuJD9>twl=SUizt-ZH-NbvpHj1~;#nL~{9cGv9O1RRze*n{Vbi z9{>P(A!OXJo}XD^i@5Y_m>J7AwdhV<4SMM~B17(tGJnCKRTDO@cT}Ulh{2($b_6!c z$>!t8RP;=tt8xfI7skeBK#-LyFlHryfwEbJ8kZh0?l@p~2Sm>&DP}r;N}{V(7bh7q zIy)IKVeKcWOt$HvF3Kxfv=tIAG-aA8WA>ApF+-C+{6iHcy8(%-uCSsv&Y|WawA`{s z!|f(wYwRMxmCvymOpCE{+G;FFnSVkY`YpnIQcby)RKP0|kTO=kYr$;xS1KD_2`zrq zlmNd}q=X8}F|E1T(^XPk5gvFbt%#c-D@?3We$jl}tVv26%qDC9AhZOdHU;a&IA5eV zQ=M@*5ZOBHfYH*}H8aM?n1!7ubl@~vEA~-^pdx7XZ5$q;?s=g40A1WOI?$+5YHn(m z4(!Ja?`e%dwVAB~5T6GbvtWb(>g8MQ)|k@4G)=g1B&5bCSVuNik?C=EYTrV&tmcqc zbJ6i;aF;XcIxLYmV6Q?$HRUC|aQ?}{g;NoJP??f=WUAg=A zlhU0SY@eu0Dy^w23}V&ot`%QpsEvA!i}Ksv#eXcs!e`MR{=qA@Yw}D+*PxU(k}Yuh z*u|vn_8Eu8xj(viCTqnz;*w;!OL>=hS4E>cjXE~!LFKS2Y!SMjVstILfz7ezztZl7 zii&eFX75#dSbotwp9L z>fWo*5B?|m-wS8HV)nfTp^d;TNzJ!pAAxZuS-X>A1Zd0xi5cG|uHW-(@%Pmt!kXxQ zo$yAwTI)?*l*2m##!A~>R>c=BkcRv#8Y*qQLsDR!Jzi1KBGj%oVu2FQH@^|Plz_19 zO?0zD{`>=CY>6I8mptdOxX=$$a0A7E%G|1X)75&9J>PKYqM@=@e-RMhrQhY9waCJ5ZK3#uO_wpjJsgE+Z_N%K)|DQ$1gF5B| zn~B{$IW(-rt7TV9|(rmWX6w1@4YYy=K(nI&6?B6I?lwvwV7Vts8H1`D7vyGe{> z3-HQ^C<(<5n}V>A+5*uB;ofBNrAdz3k{3rZ;N;e@^K_Vg7!tWfJd_Bnc+C>ULvWvL z38FLfC5v}M=_E^kB&~`|KgOZ~mD?v5SAItU_yxQqWo}P{P3`P z-T7Lv>=MN?a1WWOMv}Ww=I_sm@{bbAb-YZ?eWava7QG)e4-QAS!1*O2(kRyP#d9hR zm?*xN#g0cQIE7vAu|J~i@W){_$6Qd0G^1P;yo}Z@Rn#Iu@q1w_sQr-=F47(k^SK4# z!5*_9(du1jLxSgV7vB7=NO;nWw>mG(Pa^oE^WwWFwb&8y%M*XLUc7ix&t*yyI@acV zUetYB!@mPP(CH@h;3Jw>;QFhgBJ#KO#h9nHy@#e^c1v?tK70-=r8^8YV{lI8w0qkCMqv8Qu;5%Sk*Uj8%j^sl=7%qtP}_xO-}ZIZ~M z7lh-j9mC@hPKRH78Et?$KNz(3OARSW4i zd@r8AtnSf9hmR?Qr+zPL|5M$gk`5nP$S3Z5G2ow?9+$Uj^?p@I|IYW~Q^3E_;r-Rg z2Xg+nRa^jkhz=iJ2w%Kalz&y-qrMKGTnHbqRm8mt@%U$p#{VN^>s9%~w~9%xLOl-Y z@Z3WBCtJifpr5b9j}^lAY!SD?zn2boErie6B79y~_XySDYYO2hTSSM~o%rj&#PZkY zSgo87|EZLBM2-SF6hJ3xt0`6tB2hbSZe3U)vwI3S{&y1CDbn_D^G=+9!t!9djQkyC*H!U5=npR!= z2y5Y3&D(Q?yzusJxG1j!m*%h=>@z7CTV3VlP-d9hmYJ-3W?}%T0Zcpw;rIixBWG3I z-uaZA$5Tugd*yh}e3_8*IIF{Rb7d}Pb;~B9xUyuQ{FAfDYL)Sza!{rmpp}!=puec4 zT#>SI8P?j^Z3h-!%@ZegMZ9D4YAffIVF7i&T85F^E!0V!NscK~wn5e*)5^o2D)URD z`frox%dn5ayOsuD%)ze5c#J|VM#eZ!aEU5FVL8Exg;ibxG;JS0)!|2$$*%z)*iVO} zGE66_p-%Q8G?Lf(k)x^*@fXxbNh-8`O}?tWuW?b<1Fgs6+N|pTHwde1gdb^yi(i5; zT}C>y!4)U;!>nOUe2m#iS@D@%<;?u~g0=DoXI78T+$JA7vyb_?HFCx~>>Llskywzo z;=g_`7nNlV`P^0VSXtJAzg{doT-Yprd8?EzY#bl9Rl2&exqR9pDO}m4s$~|zLG09= zwfY9*2QUg8O3hy=L&~w%tfm}}i`&p%G?(BI`JMwZryS~^|DC*5j>Ylz-^qvyEJ!B0 zv3fqsk<=>147sHO#aYgEV@>&{ALL=Wj{8==abqbB_k3KMIDerM?y2f;JZx?E3dgW$kmdBa{?`iEN{YwL7lpc(5oOM0l~O&c8MDPFI+XU4F!xrNix+9$|F zsXetHJP@0@7+TCojW(%IW$;8Nc?~Vnv5l>Q=tBZg7g|g=?IiNDcrq?IWP&}}JiD5P zT%e6QTeqb+_ zqu0vcy)h6@Wy%mAz@My<{e9Q~zG#iy=L7hoS+c-~RrS3%tF*P+DHo*dnBa@G-wlNkj{Q?9z?EL00t-DT?l_|8X{n)#|J%Ybsa!Gavc5A#;wYV^Q?eT6+);sfiRNr4;-Y;L3sj-V_v_MKM|aru0fL zleMC?!BCUcsYW=IKULxD3XlK0=80~B8{O5dv(nKwPZ^)`jC4`kvF8EPhAfLw!_9Hz12UsQUen}a9 zTl8q4;544#qKyCdO~Jxs>kvql9EumtQbQwgP$V@_RT6D;gkv{E#)Yy#^8;Tv{FpMv z>_2dmY#rf}WNU||9V|LNGu_~1%<>9U7evaEX=;v#!ku4m8+E~QFwt`J#S>%|--%~G z#@D(8AzHP>;@4(&S3X&EKN#oMpANf2qA_ zXqn=Y7grwj8n6-K$&FdfP?-s5{lo1qR706bIFro`nSN8QucKy<3c^}SZ!kx%sCrlH zp6`!7(hlUwsdZU-cfEI3EYYdtf*Pz^UOVjGe@EwFi)RYe}E!P*xV zbybT(9$77n`PF)$4t>mqR7|O7Bh_5ok^PP6UMA3)k<04Dxq6nD-6OFVXTrd zt%whiuax`4n75xMEsf-sf@(mm$gG6Zfo1u)9D9iy0lnCn)aAs)K1pCX@A z)EcrO8C{b_FjqOWCX0Ue67n$C(1r1t{~}@-2qVvao?0;;C+k`K^Va2^5{+$cs(qep zxvGBY=DD&JPKr8T?ehX2^~ea>da z3%Kv!!JtUMWZO_`RSJyyt`ex#6clxWav#{)n*npOZ}?Zf!2m@ zU@hj?^tftK+8|d4IGrlChpMfMBTK}9`%T%qnld9eGJ_$nn%*XFIlgYOzp*W(9bzKx(g)SPPSn-4c6~yRX z;zM+E#o8>as!2Ozf}`6wbxiW8qc_}s<)!RYn+3MI;jWHY^$-pcz+^r8A)KFP5C-RT z_JRZj8_}%jU8oJURUNC!>ha9u{Z!r0QEvEM1kt5zlZLj*Iw`z(cw;O#Vi@B{vS~(& zqiV+NAXU<-O3_hmceU|Pl>$WCS`Tcgf&idp9ah;$JG<2D>TtT@DSv=7FJC-BR(xDy zM6IgB{MiDzzYg>Dm?X*GgNi$5yQkVQh2z;rt&7HU#k#C!3m+qt{3jAI!_hfod!cJ7 z=QMr=WrK`au9YB|2HFo0+-Wi23L4+S31)#!?QprJE_3xB1%@;Y!_nr;Z@zR?GsW{f>N9 zkGZ>6Rw-zni<`u%nn$7s?N6~+r&ezw%Z6hrsvI6fNyf&0VZFyeX>W?S=Km(&2MMZPqxYA(n3-?%D{;{`Y zQOv7EnRiN+kxlEf3NBh*&3zqdznfQ*zg$>Md;KlGy-L&GE2jPREm~HZwq<0I3@yAI zW%wGaKD9ks8`G$b8{j31+ql5Tu}n&-GV*>g|88&b|95Ul{+`*y|CKs&3;V!L4r<7} zOQ>*NsUq^TC|04Yrov8+q@7BUdc9BFlS^^G_Lf91=9H93ni>?b@8ZaQRcX?d#iZ$u zq)DYny*?*N+QI1*>v2nEM?F5BT}qOU4U77z{##NnFGcGGr)jV+qY++Y%d_9&pIEX? zP2CJ*D>;hs0G(381lAMle0@l3dT;qwnNLcUksBKoiT>g(F^?v71tR*Kdum6{j>cTlXo4sVHlJF}E5{Tdg^{mSUbe|{-i zPdpjy^PZLDzg3=(DP`r+rHaUMO^Vom`4;=%urMxGi&q@6zy7o&d-+zA=aecVcNX(s z_!j@j(zM2yB3YKb#rKztlCpSyK(bs$j-ptVsg6yZRjP>G2lo1aKJ7?arxdB@B;sDH z6!!qfB9~?s3iNJMR#Rtu){!c`h>BKJUgL@JG-Lyc#ZIi?*sEcs%E&6siqvxAE!wl@ zLMhZ0+qh!dhvgmlPAN^BS4?~AExy%D(*`szlHt?0_@10mQU zip69>Ys8W-qE)gB*?_)UuNnz^;)8+P9R@Z#3p9AZs zI80O=V&l!Lpv)L2V|G50GHP_(3^@t)$OTsWr32{5Q96l_N-{AVqD3lKA!8!eAdQmP z5qp_?dbVRY7OdU~y(%3+b!v>&CQ1u~q@^Vbbe)gRQNeO+OIEM^0HVsikhW2|-&g+G zlKJt*PNjmvO4Eu0;Hrb~;jogPg-x`M3Xk6#Pd&X1-{&c@?m~P>s}3zjE7>#8l^;%# zOesN`&76%{PB0KXXrv`o%25Piv*pTG%*$_!W9<530}4{?ir}^tt46EztIFq9QMu{Q zB9W9meH>Me(`CgfSC%{CJK0O&r#a%Q=9j|vEySAY0ACOa;7ZMcW@0Vua z=ZH@Po>J`DAK-kE77-&uo;?o6q&(~mgQ94=)J{TOv^P=OlD!)(G1yN5PsD;fMIuvMPp?p?ELOCE< z)T0w`C3CR79(6+HO46vs8XnR#7ik{|9TwT4lHb$87`#dw!zr^P!Dy7vg{9j?fY4CuM{q)CDT1g`c@!K|w3rP~z+e?*Dh`8^Kcf`(5=W?lF2Fn5>S(d=r-Dzez9~>XEKPULz85Y>>EQ@{ zh(V~t6+_K5w$Is3w7*ij7_33}QNMaRLiZ5kH{D9L_nbWm`D{gTgyug2^nxSQ6|P9x zt3u6;bgWgkiDX;vNSucFURme}9Y>0s>Ij`kLJW0;uA^pja)cI;Xfb9-us_Kb>d7wj>mrpy%vv2-20vl3;@F$26-{b%fR>#!ik6gXaIG` zAstGAo!0x2)Vj@%#Dl4qK5>NR662YU(2-;lBORf&N#Jgd&~HiLmR<2RzY;UfIlBun z4tFFzNfK9fghr6S|Gw+c=7A*eT}S8u@I`=kKFV&S~aINC<5E>9*gd?{+|C&{c%+1BLB z{<YV%RStlHD~QMl%9XK zPpAEc;%KCfBmNqa%O&t`9b{%_)|IbamwUN0vvL0E+T7t?*-^%4d@k#C!x4qq!$`0y zGNT&{ipg)|P~Bmq0!pwu<%n+$yt2KG{G}Tk>zn9^HPE(WL>oDb>x=@%c?zDL$6i|r7O<=R@r=94(`d?@-I)yuR+3%gXN8$EWzdEAX1%E zsG2pDiM?>pBW94?(TjCuiPE(1H91Ynsy ztfg-UN4gZ6jkX_^z5B2&{PqC3Y5pX?JzU0Ut7Zq&UgmeOV&^?wDNJ z7n{9NW97cStcr*CSQ1#>15wZJ9aV-(dtX+|^(s~-G~2t#@jlE$M)YHWo-4;V5LEmV9l$&K8z1Pf17OkFw~ub ze!Td36?Nc)@5<`Ua`XTe#XI#S&BU8GHFv0Io`aqp@y}qeN}3~dFj>xx1FClz@fk#{ zgrEc>USFt+xMmSVys4pU5&9dg1^X&!_@9wsR}LPKqu*mKJQKd9mQKSO5{fxQr)ST9 zAosn;!dP$l$9t?Z`m@nMn9YLT@;#ggm*~mrNhT zl6Y7zd3+G7$9l@=gHY^rPg#91Yrz-vl?4OGp9(}uaSe1(C11@xS7`t9q{x)l@j=Cj`$a}Em-Uo_c-FO7V^iuONw3Y zNYJU&-k37Y5kHl@z@43{J$hq&?7pkn<1NZT;}viTrgwqH+9VOOs~^B9`kWO`9pcRn z_0)m9`T?uZ6(21|y5Ww=;uM-%7fZ7soJ#DXyr=eVS`gVPosD>;Iy&m@htw5Y)SO>; zn6dh}Xg75OJ`6;gOMl6;2{dNIaZ>pZW5AOb!~ve4U;uTi=zfMltVj zc%1Io;Jc7ofp$t&R$;kdMc?m99ahAV6GuOn9+=TpXN%o5pAOyQunU*jEF#Z<C_`d9cB`vAC!qAAxc%E4;X?=lrzMSi3MzAs9vR)Y`+ zKguab0%!Dk3A5Vdh;Knw;kAQ;6usAzEPvzw!{8%k^7IF+>Iki)|8VH&@79tkiaWa1 zd!*!|VQrwyBy~r!Er+ye%=(0k4WCulhum4}FHO^G@0WEh?Bs;b)X5>dWf6p{5byH5 zsAq3F$ps@>l`?ptR=SU5HJFn;IFR}9>`t=tNao)t>VzrJfLIJKj>Ngd(G>=xJkFsy zi$qwhcD8PPo?0%V9Nxz0MC6{Ka?21FS)l?7E7v-f0QsnHZG{SQ3Z+d!tx2*{GV}27 z9!Cp*Z1a+JDQ;?wdKCd>RG~*It#x)K)~DJT5C~1oi-j( zEN$QxDQS5bHN8^imhyu%j>KdzGnuqg7hhBA9;tk@jg+B_c2j{2ep3!F2FHcr(ma>5{vC{tayr|o^zlTevb}v<|q~zsH*+kmZGl4 zpepXfUW^8iFI4_-`{HV&U4AI>6sb)jv)UJrF}n$)hR#tvtL-oro{|S$s9bY|JH(TF z9PxJwJuBLa7B6?iS1H7sHG*l51ba%m?!J!r)uqQ^b4NVAO;uuy`Z?n1jY`6|%F+aQ zUCW{6RdfO!f6Wm;fC7{@-^r$<*&udEE+38X>r1(dF0SOc~Jno9ceO}y4{KYwS)$C%wEQEvSD!s@S!e7(yS%fbO0Pr()JmxNh2O54T z;Ylnr2nOl|3yEMk5#U8y_gypb2y8RLTD_X%q6Bo)kovy4HQHZ81`v|z$X=RetkDJy z$q4yJie4cdjG2Ol-hQfbFaHOwy6Vo$`D0mZ{f0Gxq1E!w_7&uD*KQ_{iw{lV9M0Ty znmJzRZ=jiM^=4(tmt$EQR$sOp$5Q$C59PLTIF4DiyL>T@)nOxK$atI^EwD> z+~vaYtS(z6_l?JLWX(KTegf;z-uZE%aMoysdu_2ypX<%XLS^Rb8OE%t72%oZWWkTj zd_CQmRi+%>q#Lt;F;X+=MShx?!{q7-%#YYlVChx69#PZ(;p*xCBZO zO=K~ZZo)?2mY++K_g^*CgX?DG+8 zsGtxzBdI)wsdzomg0vw3B9=my{Wz! zhR;IdgH+hOLeCmo%lD?TD%^9QoH~_Fwn-j`(?jbD_4@H`TQD%XH?${*_Or!@j!63hAspTPJ&^ zv&L+UT#(KJD%{vrDB>Gst=yf?{LHc?NovMiNk55}aZd4>*;jDOl+QtJzX@loCtPqq z8vFnFIOYbR=?srMMS72vKfa(D>GM$X4e`&j@o57C4g*^8gcno0BoCPqN@~GUZO=`z z4jlA-Wy-wy82{JBJ=1*4n2eVO6qZEPOX-zUEe60p-Jv&%QAu8z5ULL!70*j>4_0qe zeDe~5;&Gd7nHHXx5IGXJc?of$8lA~x(S%X<%qf=4lzk0fK*Qj)CSaDGhW(F;m}$M@ zFxBGwQK~=cXxn}OER-~Pa|VlMH>I~3=bHm%V>9d4wsw1Jw3?0Y;%*;|TpErDVb80K z{RPf-sIS1`y`nO9JD%{uOk6nf>1FKK@T49zQ_V}MA&YaGs?EYq%U*y*W#1N@^msQj{&(NS~anrt-;>@jAn2( zz*XG53tge^j{hs1-Bn5A^RivQkA9F@Xo;b^yCa4bY+>*yy2N(*5c(dzT>55UAPtf2 zGFVNvLXOQ~)y)qmf7s5;f&Wk((@>%up%)P#TTM>3cbV12(#6Tvtz1DVW!UMx9_5v% z12dZFl|LMz8)$kzQ^^rLQU=XpUM>0&r!^{)f>OQNx!{Brem?;%lv)cb!Ya|iDrl%u z89NxtgJp93EH=}-!wo`g4xOnMSI@(FwYnk8X0is}z7xr)3zR*PU<5}+sxnN>?VQQl zI`cV`a^+lBk@2q<%daeWzvOIUZtOf(o%8(@atF?5pE&d3^W@7#$V_ap$d-$dapG3l zZ!uPV;q&CA#Vn9do+ssE;496Ozb?jm8e1*7u>wm(KBIANyQSc-wvMG2pHMXUx6edbO|XD~s33SF*)tOuE*hf)=mfSMvI2tZVHv|EPTO zaKSg4)fE&io$zv!<(a}VFmYLK(3`H$XUbm7S#Q34rp#H+dewe90ISXmCQCb)r~?)s zy(lWZ2)O!MQ2uSa%WZSsJ3vN%&T8_TGv$EKS#!Qty#~tNpR*9(0<5_btxj7KEys56 zfYBnIg*VNUbP~@m5F5D8lx@CX?fI`Wq?5)Q7q}Xoj4*048H?Ck2eoNEe6sV)u+MJ?5 zyc~cvtug7i(r<=*x&m3}PU$jeCG!c01|iT%M$@sRrbkk15&iGjAf=c7PNd83D=}dn zo-U`YWc8aJn*Ii_Y2hC=syZOWZ7G7#s8m+t5oejP;sP01{*70(A^yDS@{g5R;nbck zLszj@@vcRsu`qRTUxE$C8Hqcq z@aE2`X>#IfEJ?km$xm0qde=^sdsZW>c6X}uT?3u?PtA>A!`d-^X-e+AwRp9JZ=Ec^ z`4U!}-y`?gmuyuTeqy3rx&d=w{B^l+1M~Hh6CqA>?e#F|&S*M{1Dn*~858B>4XjGp zXV=i&imB3lBl9hLi5`p-W&MpTq~h17@X#Gz3-+<%lpMH`t>AA?e)2VosBz{bTAOi% zX2Ziu^$9pSqJEKlKkcQHSz>f=+AUMQW?|(rcavi9zaJ*Z%&*yY9y(q&+k_Xw5_ZZx zn~*^qF-|_;glzjq>T@-@dNT_y*L0^=sQNg0dNZr-KWuDK-oRveV#0_1sit`RLz>t> zFH6sF(6x=m%4XlNsx^E;N>*Yt9VRoVs~W*m`Vt#?jCq&QrgdZGN8d32^270qEB)=yxwaZ1;~hL`&1``}`A3!RqonIryvjDHgZySI z_FdLp(D;8({6ElIejM|{|KP8;yx9ffKT_w92d(KXP>A?{kn5U*-6NheLN?#VF7n^r z&voC<7I8kR-B)XK8Rrj%$aTB$PSma;@|RsO_{W3gn_YM-_4Z)dVK@7kyA93_*@L%< z_@x1|***l;TL#D#``AK$roW8b&${s|{pIZaY$rd{PsaVge&Y}O<^~-=RLGC?k?jw{ z5wGi;YdOf=IG@ry_mjhHGvj@G$;6}Bm)L|{^ilSV@9ZJ-kHOLR=^;Dhv7!8V_uQ>{ ztOw(Fx=Pm*7<~=8$+{<)uYWIWYvfncylyg1JDV`iAtFX@P5CB84m!cc@Y7x8`4g;H z*jfv$6951B=lJewb}JsAWX3vc3BW1Iwf>_WEM@Gwxt&k4@odLAwy>tG#0a&Tg zZLpl7;#V_6O z1fOyEHR1RFEADK-qpGfce`XVgkc46Q5Ms*5hyjAqFob|Hq8%_o_>hj6TM-c=4T^{` zK%~KkGNU2}Zfc{VJ0RkSs3^gvf(8}ss9dFrIx6oiRkWj`jes`#&?{1!bAS7sH5hq$ z-|KyP-{w=zYK({=I&dxjg}hi~C0GY%X+riODWnp)6k9Q3Fs)aiSG?VP?fV?=qE+vaL8=9f{{KQ| z>}#{Jxz0izK=f2P?2zlC36nMU474N?HV{V!Ywht`#M+O{6R80goM1GM{ZOj@(PnQxPG`Prv%4GP zN+ciR0N8k}dBq{m0PloHI@$J3UY;Jo?O-K%F1QM=Ke1*Y6l6BmQ#b9KqmNql?1v+-JWOm z;IFo*tN}?PyN1~IhQa@}vf0!T{SlSa;aH8#K!zeYNMnI*&pnsM|BDj+KLv>W$O`K5 ziz7|Q9;5}y9BSLk&$I2%hS_#iiHjA*F6NKKHqwqd#)B9uMz{v!{9~l5$hP+lx9tPq z4A7M68MN)aQo&}h8aYTs)uUYd(L&oca)3tV!>uV{{wt~cRQdA!f6txj^RMPVrrsB$ zRP=Y0!VIQm7Sv7X>EclY#&I>8|`*aEV}=zw4BInor{$-`k@ngQbl>2Ja_8 z%?wvo3!2~VO>+hxI3?fSX7qa;d-R8ePIdav@{bYV%j+1m)5v?L;ZEl_Hu_^7PviFj z+`~u}vg+5al<}=kJLpt8e~^4N`3kYGT;bYwlmB=X^WU_RYxe)2ME~W=-=P=J-tm1W z9!Fo-E`Pettv+e5a0@OI;(Ea=1-~Zv=39~4|5%c1xLlC~$RT8Nt$y`8PmwM;?um8% z<-!{y*Uz6b>)M69nzSt4e4GzXj(z6|HMbo1?C%&Y-)h@g$h^mG`;q@dTAui!y}VsM zMY+f*4#>kfNEf>}VJAw?bjgzM%gyDl#~g0~pwPO`AQmGkM-X)PTta97n;#A{v-wS?2ZL4luTYCrdDL zI}Zifr<=;RepagRz4FFbPfr1M7GU0)yaMFb3`g z6JX0=uKy&;3FEllw*3V-fcao6SZ45k0)gQTw!IRJgH479cZ0zPZ2Jfp0ecRiVsJE= z0>fZnBj+P94mN@ba5vZr9vBkE;X%%!5MeOq90Gy)U=tVyLviNRqF+GkKZQF zx?miv0j-DWAs7U=fT7Lw6s&xNDFDOV8AcDKJXi|`xNF3thCtZ`hPd^#m^_&AQz~qv zB7@tQ8Zg3dug1aP@943~H?dd?>Cx{wR)CSG7#Wk_PKBVggANVDA1nZyz-eIYX&MNI zpW(=H45byNAP6>degPxTGS^@X+zDFG5fBW4IouNxU<~v>ParU~ixDeg$iWC`y}(p~ zp+B%_!9aqJjKKdT>|p)NbQlc0V$ZgZpoCvx)pL_cfjz<4|KPGQd2l&c|0)eK_!`g9 z+-zFGGBCV{xdkJCWav%)b*2(bf^lv_p*I*&-7Q-U&MO$!X46$}Y@PfD%;)1ov?6Ed zso84KkQVHljDchvBFM@h_b$*R!>vS`^h4RIhi8|5I$NFVY0@8OtFwDe9^YnnHeMvQ z8|ws8K3?bLsD278%~4Z4EqZm18m4N?^>aDu9Pf+??5$mOn_u_pS!3Lo};>pPhIYd5qB~l+t*&#W`CNc@9e7jMmJ^o3d($evA*1~ zKL1!>=7j7?r!bdf&+wH@^@T3>m0#=&Px1vjT-ynkG3^SC$?h;%`AWiRr=R)Ym;^h+n71`EplvpuXEO)Q4HV+%dY%rv`a*Gc0TQ5`9irHQif-o^!Ka(^Wm{ z&F{!aM)fGa8sMFbUK75GDN`~|-nmQ{}7AO>rV zKJHiJvVvaA+WZ^da(VPy{TaGzyQ!k0TFA-2<-H(&CYia~09Ok)*16?zvZY@2=c5j3NA04{T#{-%eT z7&Qm2{p&a-NSOc_f-B~X6g1ozpMRCQI?It|JlYG(boYxa_C%;v&bYer*Zn?1rT3}W7<)KdiQdZ}@UBRg;iJg7hEsWy72Wl_my zz3L1#pkoYurQUXinw51BHN=@~YA1J=&+ny{WUVv-wzb)_{SMju=U(bh9&c?I=KJ~P zXL8j!p3Xacmet6|8iVy^eN+#9;!IW0`2<|UD{b~x{nI>E)>SRa@&(4Q>YXcXl8)x7 z4OxELdW^xG{95y%pD3RvFNY)5+&A0Izqxag*=7Q8E8o;p`lzC;Y3O_3YO{YOYxvPV zD({j8$ed)GO@&S}Q`!iZ3CI1P_2)BZJSzd0-_Fkj-v<|ftJ5E!Ps?-rsy^PF?p$q2 zUD}r`uNXa^)U*4laUEmm2lckT>TK^8)SP$q|Lm(Kc0PvQ$ou~-CPc0t(@&l2E$hLh z^qyYaPhB*i7Jc-4vVxt7ndVHhSty&ah2GQe_EQr(9z{>_zYx{Wyd_)#efH^V`>QFv z8WpcmaW!c)vH@Gkzv_SOmto%~94Pe9R!>M@M*LvdFYNB^O`kue*^=HGIQ}gJ5 z=+Dnqqq2^oH*vsCD82D))mvYfug>ip;GpBGC|~7g)O*y6`X#?Qqhx$`hgfG{ zgJ-fY?zz~v1!?k3^3{7fZ0~*=b|u}|NvIhE_2>EOR&R(MYVB~nU?7{?a`em*`iX(+ zB5wkH$4LE^(K9%3$4Yh4AT=?o0^L8>wzn#MC|~vK5bE%)ew(kB&1%4~yo^_1Uj6zY z6$l(uS-#+yAKrAvXPc#P0ME=xI%}{h?c9ewVD6>7OV^hUR!asokZqjBJ2u>8HyC49 zT`{A-16vB)IbC&OSJkIk6{zl>yd#|D_j8mscMOxt%@5A+`)<^QLm1b|=(!8@%|le4 zcRu=-1$zAu*1#6@oQ1aifx8Bd3{ipTLAWM3bJdw-@EBYp97E{!l$<2T}w$P5+1KW`i$euhKENjQDgp0woFWdlE2iLyQ zjc~Pa478JsEdjR{j!`_x?SqTMx%*bY?Qsj_E=V?2Cl&DX1l-PuKIdFDD6b&EN?l~z zW`8xQ7#SVl>RzPhovVtx)##B$degaTK%RLrYB zb=AD%m2zCb)_k~HxFW+jeTz7K8%?$rTVu6;=BKJOx(EFTegWgh267c%Y>-w8{wTb& zDBvrFKL($3lS~@?4B`FUH1gro_l}vu7eI`LXPS6>CX$9%vSV$H|c)E;72nWdzR{X!_=r~4SLS6Y`f3|bvienuuKrL7Fz(@ z<;FIi-H211FLO+`nXD#kRoDg@8!3S7hKs?OU!8Shh1tr~Gg&@A7k_!S@oB+levNJS zcYSpKpgO~w!_drKrb~k~ZW?;duk|YQ(#`0Vzvk^c1HiuX6@OaYiLC4R;2w*$7LQfgafpIi?ZB)-2t_r;o^op3? zIGncZLf_-)W4n}5CXJ@t@vVAA5%P^ziL^ z(+F-l<_S7^yZ*-L=IJ@SN{=nZrwl!@N-r*^5i#_YcjzaJRcT%VeK+r4)5jEZx$iT+ zwOWl-MT5)(bmnTggeRB-9K(IdD^>}91=xmSTV|QFdtd#lk?O);$s_+fxpOkBmU+@H zS*>3m$u+eby>hkwW~5r`4Y6(ZT%#9^QseUK(C4m^HB6auBo0@-M!$vKd&Jo5bl!P% z$~XEXjKTubwL+2h0~Z@9^DeNXYLgxieYRoG23e&%Jsw=Lh-Ww=_n1Nikbmkh~p z8{pn?{oIFv8Ia};!oGX-N9Xe>=O4y0UaK!E<#rh~dW)V}s+RV8?XUkl`S@U#^e$`# zYxSX0H8wLN$SPWE+j`M2RFCHH1uBtqPpsdw+Fz~;x-I?4t$tb3#Q}Okxf-u(zHYv| zT=9!obHCPyCa61A!)N;DiKt9)w9zSX&-7kFT6#hcpd6JqH?S05C zHd1hs;MIcu!>)aa zSn{=k-yZVtj=pd7L&<+CnEjPo{;=ea33d|x4Z$9Qg9OhPEEF6oST0y0I9;&!J5D`O z>lz`h6I>wpl3-MDji45MM6gM4m*A^{?+B&@zY_dTu=C$c1EO4Gj=~{MaJb-L!BK)2 z3YH622wo$&Kyb0(&4RZH-X$0peApm&0qZd#wh3+*+$H$(-}EP!vQ+oK)!coG@^&z5 zIPWs`m081CQ`Ho+hNpx4`-R7+s=@01&-J@g)u0X+{?$zJz~;c^%J1=9sE1dm{%57v z^Um4sIyZOz_Nh!Ss!%^OA)l&H7nv%)sZcLcW%E=2O|9_I2wilAD$J|z@WboG#OPpk zvud)MZ@z-ImT8-QHHDRev%~E#*&UuDntWD+=A`uD6cj_9CdPF1+|~ z`TK?6Cw#C$KX)a?1A6#$HA}^Qr|+K5*ueImGR)~ zFP#opdeJO3%wy??W~ttnr9N=I2D`no?jdVNBlU$#@Ooq+9W! zo8PKCSMoM5sjsP2y*)9#tWpg-vyyK~Gs*eQY%pC(kUub1z0VAEbj|4*DWZp_4dwc4 zV-Ab?eChaX(4C31u2H?C@ocyBw@ww7^@x;i{m$ii=5&(zl5bNip5yZA9=|XC3Gp|F z8|-8UsP-Y zO%vWHac&X+xJ=DKsd$a>e&N}qocgVY#1IridL(uVzh5elj#+OB9~1xdWtQHI%EjM3 zoLJUp;(xFB%M!A_?ZkCxdT`fqU0TI9Qdg?yRjH+_zJvaxN{u@+`Ig&s83@a~Kkd$V zRq8Qw%(W%E+-m9grjzDHbJX~}uq^tt`5Q5Z9@g*9F`L#4T3xG_o*9h0wM>yPvCeKS z0e#oCs`td$b25Gc8^s)d(Itim|D^C?;m1q37lp5UK!0;Bdwl9yx4?R_w}`!In=ZXh z6&6`vx`r~b_h-*FownAy<S9MdN$Mp2MbRzM%Tlh8?tnS%vCsNXw zJB1%8d}OPBZmt?vwE01oFBd*3e5F(~LHNaHNhzPj{rel5q2jysfO%l-Nj=q| zzfs>hkA)nQxl8YoQ7$Djrvd%(JQi|nn_Jyr3A<6uA>Hi;)w?KUz731?nwZURIXIaZAaTuvx-hFMQKFy`JK#zFEJ1BSRC^ z-4>|cd5Ndo@*xRxNZf<>>#+-1#!audhR-BiUzVk5O;YAF{TgnV@WDs*CdzRPdx!9< zX@fqrK+P;l$tq+OIq5xdPpopor?-kP(qXphn-?-;K^gggl-h93E4R0XkqZ>j_-<=;??q}zUifLZvMu6N%1y#FJ+@I#U!)2r#AO62>!hV(uaqr+j_|95Z+gg$ z=iaecEy73iJByge*dwm_*HY|NF{hr;YBBpmNRAc%5PPfGV{f?St`h!)@ciHW#f0TA zMI8ex)k(eiFvRqt=>dKBVzso$Z~oGlG~D^g7s-m<|67+hSNK`NS8mazOIU{CdOdFm zH@c=x`V;b8sokp8u;G5WLYGLfUR-jfy2xv8HFvpSoh^K;UPQ4x>tUA_gI>L#`RBM*uNJ(D3h69Sg!~l`n~I)j|^ivd9v32^BrHpAxx*(@k z>nyf*XMJyT3(l4DBZRM)sZFnxknkZ{DYBngmkS?|8|Cd1=a<4KpLDtwO<$bWLNV}n zx{m8YDG(DrA{S1P@b&3HkGcNNyI5=w2w%U|bxc2bY!^N(mqNZ{=I3rPSTbqvN(G+^ zpK8<-YgFOvCK>Rbh`o0&ccd!i0CZSx6GMe>I;8=lg>RLS4N9B|!uy}q?^Dm2;f=20 zsM{}Vwb;Y@tYvCgG%S~DdJle4%vQDQznx3eq(7yL#htA4>l8*iD13dw^)Hc&=^Nn_ zahET3i&?htO;a7B`R!%u?2LjX)z?(dxpB^dYHP`|8yC-6GHXsv1XyzY!Ubt&_WXsv zyrDU7h5D6;Z;pHLIR8*@Ym{&C8>RO|)d9~){YXr$@$ir5ZczoE5&WM4p1X(ZZa4E0 zwm#Z<56=WkJu^iTu0>Dl+H!mRzWt#VLVe=qmHdVNiU>VMyT%Ab{f=fI&m X?>;rETTPbRvoz*5Uvr=8-{F4)DQNi6 delta 46616 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 diff --git a/progs/wasi_test.onyx b/progs/wasi_test.onyx index 5f7dfb93..b7d737df 100644 --- a/progs/wasi_test.onyx +++ b/progs/wasi_test.onyx @@ -62,101 +62,101 @@ print_u64_with_base :: proc (n_: u64, base: u64) { } print_string :: proc (s: string) -> u32 { - vec := IOVec.{ buf = s.data, len = s.len }; - tmp : Size; - fd_write(1, IOVecArray.{ ^vec, 1 }, ^tmp); - fd_datasync(1); + vec := IOVec.{ buf = s.data, len = s.len }; + tmp : Size; + fd_write(1, IOVecArray.{ ^vec, 1 }, ^tmp); + fd_datasync(1); - return tmp; + return tmp; } print_u8 :: proc (s: cstring) -> u32 { - return string_make(s) |> print_string(); + return string_make(s) |> print_string(); } print :: proc #overloaded { print_string, print_u8 } print_rights :: proc (rights: Rights) { - print_u64_with_base(cast(u64) rights, 2l); - print("\n"); - - if rights & Rights.DataSync != cast(Rights) 0 do print("DataSync\n"); - if rights & Rights.Read != cast(Rights) 0 do print("Read\n"); - if rights & Rights.Seek != cast(Rights) 0 do print("Seek\n"); - if rights & Rights.FdStatSetFlags != cast(Rights) 0 do print("FdStatSetFlags\n"); - if rights & Rights.Sync != cast(Rights) 0 do print("Sync\n"); - if rights & Rights.Tell != cast(Rights) 0 do print("Tell\n"); - if rights & Rights.Write != cast(Rights) 0 do print("Write\n"); - if rights & Rights.Advise != cast(Rights) 0 do print("Advise\n"); - if rights & Rights.Allocate != cast(Rights) 0 do print("Allocate\n"); - if rights & Rights.PathCreateDirectory != cast(Rights) 0 do print("PathCreateDirectory\n"); - if rights & Rights.PathCreateFile != cast(Rights) 0 do print("PathCreateFile\n"); - if rights & Rights.PathLinkSource != cast(Rights) 0 do print("PathLinkSource\n"); - if rights & Rights.PathLinkTarget != cast(Rights) 0 do print("PathLinkTarget\n"); - if rights & Rights.PathOpen != cast(Rights) 0 do print("PathOpen\n"); - if rights & Rights.ReadDir != cast(Rights) 0 do print("ReadDir\n"); - if rights & Rights.PathReadlink != cast(Rights) 0 do print("PathReadlink\n"); - if rights & Rights.PathRenameSource != cast(Rights) 0 do print("PathRenameSource\n"); - if rights & Rights.PathRenameTarget != cast(Rights) 0 do print("PathRenameTarget\n"); - if rights & Rights.PathFilestatGet != cast(Rights) 0 do print("PathFilestatGet\n"); - if rights & Rights.PathFilestateSetSize != cast(Rights) 0 do print("PathFilestateSetSize\n"); - if rights & Rights.PathFilestateSetTimes != cast(Rights) 0 do print("PathFilestateSetTimes\n"); - if rights & Rights.FilestatGet != cast(Rights) 0 do print("FilestatGet\n"); - if rights & Rights.FilestatSetSize != cast(Rights) 0 do print("FilestatSetSize\n"); - if rights & Rights.FilestatSetTimes != cast(Rights) 0 do print("FilestatSetTimes\n"); - if rights & Rights.PathSymlink != cast(Rights) 0 do print("PathSymlink\n"); - if rights & Rights.PathRemoveDirectory != cast(Rights) 0 do print("PathRemoveDirectory\n"); - if rights & Rights.PathUnlinkFile != cast(Rights) 0 do print("PathUnlinkFile\n"); - if rights & Rights.PollFDReadWrite != cast(Rights) 0 do print("PollFDReadWrite\n"); - if rights & Rights.SockShutdown != cast(Rights) 0 do print("SockShutdown\n"); + print_u64_with_base(cast(u64) rights, 2l); + print("\n"); + + if rights & Rights.DataSync != cast(Rights) 0 do print("DataSync\n"); + if rights & Rights.Read != cast(Rights) 0 do print("Read\n"); + if rights & Rights.Seek != cast(Rights) 0 do print("Seek\n"); + if rights & Rights.FdStatSetFlags != cast(Rights) 0 do print("FdStatSetFlags\n"); + if rights & Rights.Sync != cast(Rights) 0 do print("Sync\n"); + if rights & Rights.Tell != cast(Rights) 0 do print("Tell\n"); + if rights & Rights.Write != cast(Rights) 0 do print("Write\n"); + if rights & Rights.Advise != cast(Rights) 0 do print("Advise\n"); + if rights & Rights.Allocate != cast(Rights) 0 do print("Allocate\n"); + if rights & Rights.PathCreateDirectory != cast(Rights) 0 do print("PathCreateDirectory\n"); + if rights & Rights.PathCreateFile != cast(Rights) 0 do print("PathCreateFile\n"); + if rights & Rights.PathLinkSource != cast(Rights) 0 do print("PathLinkSource\n"); + if rights & Rights.PathLinkTarget != cast(Rights) 0 do print("PathLinkTarget\n"); + if rights & Rights.PathOpen != cast(Rights) 0 do print("PathOpen\n"); + if rights & Rights.ReadDir != cast(Rights) 0 do print("ReadDir\n"); + if rights & Rights.PathReadlink != cast(Rights) 0 do print("PathReadlink\n"); + if rights & Rights.PathRenameSource != cast(Rights) 0 do print("PathRenameSource\n"); + if rights & Rights.PathRenameTarget != cast(Rights) 0 do print("PathRenameTarget\n"); + if rights & Rights.PathFilestatGet != cast(Rights) 0 do print("PathFilestatGet\n"); + if rights & Rights.PathFilestateSetSize != cast(Rights) 0 do print("PathFilestateSetSize\n"); + if rights & Rights.PathFilestateSetTimes != cast(Rights) 0 do print("PathFilestateSetTimes\n"); + if rights & Rights.FilestatGet != cast(Rights) 0 do print("FilestatGet\n"); + if rights & Rights.FilestatSetSize != cast(Rights) 0 do print("FilestatSetSize\n"); + if rights & Rights.FilestatSetTimes != cast(Rights) 0 do print("FilestatSetTimes\n"); + if rights & Rights.PathSymlink != cast(Rights) 0 do print("PathSymlink\n"); + if rights & Rights.PathRemoveDirectory != cast(Rights) 0 do print("PathRemoveDirectory\n"); + if rights & Rights.PathUnlinkFile != cast(Rights) 0 do print("PathUnlinkFile\n"); + if rights & Rights.PollFDReadWrite != cast(Rights) 0 do print("PollFDReadWrite\n"); + if rights & Rights.SockShutdown != cast(Rights) 0 do print("SockShutdown\n"); } readline :: proc (buf: ^u8, bufsize: u32) -> u32 { - iov := IOVec.{ buf, bufsize }; - nread : Size; - fd_pread(0, IOVecArray.{ ^iov, 1 }, 0l, ^nread); + iov := IOVec.{ buf, bufsize }; + nread : Size; + fd_pread(0, IOVecArray.{ ^iov, 1 }, 0l, ^nread); - return nread; + return nread; } readdir :: proc (fd: FileDescriptor) { - buf : [1024] u8; - bufused : Size; - - if fd_readdir(fd, cast(^u8) buf, 1024, cast(DirCookie) 0, ^bufused) != Errno.Success { - print("Failed to readdir\n"); - return; - } - - dirent := cast(^DirEnt) buf; - while true { - print(string.{ cast(^u8) (cast(u32) dirent + sizeof DirEnt), dirent.d_namlen }); - print("\n"); - - print("\td_namlen: "); - print_u64_with_base(cast(u64) dirent.d_namlen, 16l); - print("\n"); - print("\td_type: "); - print_u64_with_base(cast(u64) dirent.d_type, 16l); - print("\n"); - - bufused -= sizeof DirEnt + dirent.d_namlen; - dirent = cast(^DirEnt) (cast(u32) dirent + sizeof DirEnt + dirent.d_namlen); - - if bufused <= 0 do break; - } + buf : [1024] u8; + bufused : Size; + + if fd_readdir(fd, cast(^u8) buf, 1024, cast(DirCookie) 0, ^bufused) != Errno.Success { + print("Failed to readdir\n"); + return; + } + + dirent := cast(^DirEnt) buf; + while true { + print(string.{ cast(^u8) (cast(u32) dirent + sizeof DirEnt), dirent.d_namlen }); + print("\n"); + + print("\td_namlen: "); + print_u64_with_base(cast(u64) dirent.d_namlen, 16l); + print("\n"); + print("\td_type: "); + print_u64_with_base(cast(u64) dirent.d_type, 16l); + print("\n"); + + bufused -= sizeof DirEnt + dirent.d_namlen; + dirent = cast(^DirEnt) (cast(u32) dirent + sizeof DirEnt + dirent.d_namlen); + + if bufused <= 0 do break; + } } timer_start :: proc -> Timestamp { - curr_time: Timestamp; - clock_time_get(ClockID.Realtime, cast(Timestamp) 1, ^curr_time); - return curr_time; + curr_time: Timestamp; + clock_time_get(ClockID.Realtime, cast(Timestamp) 1, ^curr_time); + return curr_time; } timer_end :: proc (start_time: Timestamp) -> Timestamp { - curr_time: Timestamp; - clock_time_get(ClockID.Realtime, cast(Timestamp) 1, ^curr_time); - return (curr_time - start_time) / 1000000l; + curr_time: Timestamp; + clock_time_get(ClockID.Realtime, cast(Timestamp) 1, ^curr_time); + return (curr_time - start_time) / 1000000l; } is_prime :: proc (n: u32) -> bool { @@ -166,125 +166,143 @@ is_prime :: proc (n: u32) -> bool { } Vec3 :: struct { - x: f32; - y: f32; - z: f32; + x: f32; + y: f32; + z: f32; } S :: struct { - name: string; - age: u32; - pos: Vec3; + name: string; + age: u32; + pos: Vec3; } output_s :: proc (sb: ^StringBuilder, s: ^S) -> ^StringBuilder { - sb |> sba("Hello, I'm ") - |> sba(s.name) - |> sba(". I am ") - |> sba(cast(u64) s.age) - |> sba(" years old. I am at (") - |> sba(cast(u64) s.pos.x) |> sba(", ") - |> sba(cast(u64) s.pos.y) |> sba(", ") - |> sba(cast(u64) s.pos.z) |> sba(").\n"); - - return sb; + sb |> sba("Hello, I'm ") + |> sba(s.name) + |> sba(". I am ") + |> sba(cast(u64) s.age) + |> sba(" years old. I am at (") + |> sba(cast(u64) s.pos.x) |> sba(", ") + |> sba(cast(u64) s.pos.y) |> sba(", ") + |> sba(cast(u64) s.pos.z) |> sba(").\n"); + + return sb; } main :: proc (argc: u32, argv: ^cstring) { - sb := string_builder_make(^heap_allocator, 256); - - timer := timer_start(); - defer { - ^sb |> string_builder_clear() - |> sba("Time taken: ") - |> sba(cast(u64) timer_end(timer), 10l) - |> sba("ms\n") - |> string_builder_to_string() - |> print(); - } - - ^sb |> sba("There are ") - |> sba(cast(u64) argc) - |> sba(" arguments.\n"); - - for i: 0, argc do ^sb |> sba(argv[i]) |> sba(" "); - ^sb |> sba("\n") - |> string_builder_to_string() - |> print(); - - fd: FileDescriptor = -1; - err := path_open(3, - LookupFlags.SymLinkFollow, - string_make(argv[1]), - cast(OFlags) 0, - Rights.DataSync | Rights.Write | Rights.Read | Rights.Tell | Rights.Seek | Rights.Advise | Rights.PathOpen | Rights.PathCreateFile, - Rights.DataSync | Rights.Write | Rights.Read | Rights.Tell | Rights.Seek | Rights.Advise | Rights.PathOpen | Rights.PathCreateFile, - FDFlags.Sync, - ^fd); - - defer if fd != -1 do fd_close(fd); - - - if err != Errno.Success { - print("Failed to open file\n"); - print("Error code: "); - print_u64_with_base(cast(u64) err, 16l); - proc_exit(1); - } - - print_u64_with_base(cast(u64) fd, 16l); - print("\n"); - - filelen : Filesize; - if fd_seek(fd, 0l, Whence.End, ^filelen) != Errno.Success { - print("Failed to seek in file\n"); - proc_exit(1); - } - print("the size is: "); - print_u64_with_base(cast(u64) filelen, 10l); - print("\n"); - - sum := 0l; - for i: 0, 20000 do if is_prime(i) do sum += cast(u64) i; - print("Sum of primes less than 20000 is: "); - print_u64_with_base(sum, 10l); - print("\n"); - - - matches := string_split(heap_allocator, "This is a test string to test splitting. It surprisingly works very well.", #char " "); - defer free(heap_allocator, matches.tokens); - - string_builder_clear(^sb); - for i: 0, matches.count { - ^sb |> sba(matches.tokens[i]) - |> sba("\n"); - } - - ^sb |> string_builder_to_string() |> print(); - - program := "+ + * s - /"; - tokens := string_split(heap_allocator, program, #char " "); - defer free(heap_allocator, tokens.tokens); - - acc := 0; - for i: 0, tokens.count { - tok :: tokens.tokens[i].data[0]; - - if tok == #char "+" do acc += 1; - elseif tok == #char "-" do acc -= 1; - elseif tok == #char "*" do acc *= 2; - elseif tok == #char "/" do acc /= 2; - elseif tok == #char "s" do acc *= acc; - } - - string_builder_clear(^sb); - ^sb |> sba("The program evaluated to '") |> sba(cast(u64) acc) |> sba("'\n"); - ^sb |> string_builder_to_string() |> print(); - ^sb |> string_builder_clear(); - - person := S.{ name = "Tester", age = 45, pos = Vec3.{ 1.0f, 2.0f, 3.0f } }; - ^sb |> output_s(^person) - |> sba("Here is another message in the same string!\n") - |> string_builder_to_string() - |> print(); + sb := string_builder_make(heap_allocator, 256); + + timer := timer_start(); + defer { + ^sb |> string_builder_clear() + |> sba("Time taken: ") + |> sba(cast(u64) timer_end(timer), 10l) + |> sba("ms\n") + |> string_builder_to_string() + |> print(); + } + + ^sb |> sba("There are ") + |> sba(cast(u64) argc) + |> sba(" arguments.\n"); + + for i: 0, argc do ^sb |> sba(argv[i]) |> sba(" "); + ^sb |> sba("\n") + |> string_builder_to_string() + |> print(); + + fd: FileDescriptor = -1; + if err := path_open(3, + LookupFlags.SymLinkFollow, + string_make(argv[1]), + cast(OFlags) 0, + Rights.DataSync | Rights.Write | Rights.Read | Rights.Tell | Rights.Seek | Rights.Advise | Rights.PathOpen | Rights.PathCreateFile, + Rights.DataSync | Rights.Write | Rights.Read | Rights.Tell | Rights.Seek | Rights.Advise | Rights.PathOpen | Rights.PathCreateFile, + FDFlags.Sync, + ^fd); + err != Errno.Success { + print("Failed to open file\n"); + print("Error code: "); + print_u64_with_base(cast(u64) err, 16l); + proc_exit(1); + } + defer fd_close(fd); + + print_u64_with_base(cast(u64) fd, 16l); + print("\n"); + + filelen : Filesize; + if fd_seek(fd, 0l, Whence.End, ^filelen) != Errno.Success { + print("Failed to seek in file\n"); + proc_exit(1); + } + print("the size is: "); + print_u64_with_base(cast(u64) filelen, 10l); + print("\n"); + + sum := 0l; + for i: 0, 20000 do if is_prime(i) do sum += cast(u64) i; + print("Sum of primes less than 20000 is: "); + print_u64_with_base(sum, 10l); + print("\n"); + + + matches := string_split(heap_allocator, "This is a test string to test splitting. It surprisingly works very well.", #char " "); + defer free(heap_allocator, matches.tokens); + + string_builder_clear(^sb); + for i: 0, matches.count { + ^sb |> sba(matches.tokens[i]) + |> sba("\n"); + } + + ^sb |> string_builder_to_string() |> print(); + + program := "+ + * s - /"; + tokens := string_split(heap_allocator, program, #char " "); + defer free(heap_allocator, tokens.tokens); + + acc := 0; + for i: 0, tokens.count { + tok :: tokens.tokens[i].data[0]; + + if tok == #char "+" do acc += 1; + elseif tok == #char "-" do acc -= 1; + elseif tok == #char "*" do acc *= 2; + elseif tok == #char "/" do acc /= 2; + elseif tok == #char "s" do acc *= acc; + } + + string_builder_clear(^sb); + ^sb |> sba("The program evaluated to '") |> sba(cast(u64) acc) |> sba("'\n"); + ^sb |> string_builder_to_string() |> print(); + ^sb |> string_builder_clear(); + + person := S.{ name = "Tester", age = 45, pos = Vec3.{ 1.0f, 2.0f, 3.0f } }; + ^sb |> output_s(^person) + |> sba("Here is another message in the same string!\n") + |> string_builder_to_string() + |> print(); + + if res := 5 + 4; res == 9 { + ^sb |> string_builder_clear() + |> sba("This worked! ") + |> sba(cast(u64) ^res) + |> sba("\n") + |> string_builder_to_string() + |> print(); + } else { + ^sb |> string_builder_clear() + |> sba("This did not work! ") + |> sba(cast(u64) ^res) + |> sba("\n") + |> string_builder_to_string() + |> print(); + } + + while i := 0; i < 10 { + print("Looping\n"); + i += 1; + } } diff --git a/src/onyxbuiltins.c b/src/onyxbuiltins.c index 77e1972e..67f1a2c5 100644 --- a/src/onyxbuiltins.c +++ b/src/onyxbuiltins.c @@ -3,19 +3,19 @@ #include "onyxmsgs.h" #include "onyxutils.h" -AstBasicType basic_type_void = { { Ast_Kind_Basic_Type, 0, NULL, "void" }, &basic_types[Basic_Kind_Void] }; -AstBasicType basic_type_bool = { { Ast_Kind_Basic_Type, 0, NULL, "bool" }, &basic_types[Basic_Kind_Bool] }; -AstBasicType basic_type_i8 = { { Ast_Kind_Basic_Type, 0, NULL, "i8" }, &basic_types[Basic_Kind_I8] }; -AstBasicType basic_type_u8 = { { Ast_Kind_Basic_Type, 0, NULL, "u8" }, &basic_types[Basic_Kind_U8] }; -AstBasicType basic_type_i16 = { { Ast_Kind_Basic_Type, 0, NULL, "i16" }, &basic_types[Basic_Kind_I16] }; -AstBasicType basic_type_u16 = { { Ast_Kind_Basic_Type, 0, NULL, "u16" }, &basic_types[Basic_Kind_U16] }; -AstBasicType basic_type_i32 = { { Ast_Kind_Basic_Type, 0, NULL, "i32" }, &basic_types[Basic_Kind_I32] }; -AstBasicType basic_type_u32 = { { Ast_Kind_Basic_Type, 0, NULL, "u32" }, &basic_types[Basic_Kind_U32] }; -AstBasicType basic_type_i64 = { { Ast_Kind_Basic_Type, 0, NULL, "i64" }, &basic_types[Basic_Kind_I64] }; -AstBasicType basic_type_u64 = { { Ast_Kind_Basic_Type, 0, NULL, "u64" }, &basic_types[Basic_Kind_U64] }; -AstBasicType basic_type_f32 = { { Ast_Kind_Basic_Type, 0, NULL, "f32" }, &basic_types[Basic_Kind_F32] }; -AstBasicType basic_type_f64 = { { Ast_Kind_Basic_Type, 0, NULL, "f64" }, &basic_types[Basic_Kind_F64] }; -AstBasicType basic_type_rawptr = { { Ast_Kind_Basic_Type, 0, NULL, "rawptr" }, &basic_types[Basic_Kind_Rawptr] }; +AstBasicType basic_type_void = { Ast_Kind_Basic_Type, 0, NULL, "void" , &basic_types[Basic_Kind_Void] }; +AstBasicType basic_type_bool = { Ast_Kind_Basic_Type, 0, NULL, "bool" , &basic_types[Basic_Kind_Bool] }; +AstBasicType basic_type_i8 = { Ast_Kind_Basic_Type, 0, NULL, "i8" , &basic_types[Basic_Kind_I8] }; +AstBasicType basic_type_u8 = { Ast_Kind_Basic_Type, 0, NULL, "u8" , &basic_types[Basic_Kind_U8] }; +AstBasicType basic_type_i16 = { Ast_Kind_Basic_Type, 0, NULL, "i16" , &basic_types[Basic_Kind_I16] }; +AstBasicType basic_type_u16 = { Ast_Kind_Basic_Type, 0, NULL, "u16" , &basic_types[Basic_Kind_U16] }; +AstBasicType basic_type_i32 = { Ast_Kind_Basic_Type, 0, NULL, "i32" , &basic_types[Basic_Kind_I32] }; +AstBasicType basic_type_u32 = { Ast_Kind_Basic_Type, 0, NULL, "u32" , &basic_types[Basic_Kind_U32] }; +AstBasicType basic_type_i64 = { Ast_Kind_Basic_Type, 0, NULL, "i64" , &basic_types[Basic_Kind_I64] }; +AstBasicType basic_type_u64 = { Ast_Kind_Basic_Type, 0, NULL, "u64" , &basic_types[Basic_Kind_U64] }; +AstBasicType basic_type_f32 = { Ast_Kind_Basic_Type, 0, NULL, "f32" , &basic_types[Basic_Kind_F32] }; +AstBasicType basic_type_f64 = { Ast_Kind_Basic_Type, 0, NULL, "f64" , &basic_types[Basic_Kind_F64] }; +AstBasicType basic_type_rawptr = { Ast_Kind_Basic_Type, 0, NULL, "rawptr", &basic_types[Basic_Kind_Rawptr] }; static OnyxToken builtin_heap_start_token = { Token_Type_Symbol, 12, "__heap_start ", { 0 } }; static OnyxToken builtin_stack_top_token = { Token_Type_Symbol, 11, "__stack_top ", { 0 } }; diff --git a/src/onyxchecker.c b/src/onyxchecker.c index a90494ee..feace16d 100644 --- a/src/onyxchecker.c +++ b/src/onyxchecker.c @@ -9,8 +9,8 @@ CHECK(block, AstBlock* block); CHECK(statement_chain, AstNode* start); CHECK(statement, AstNode* stmt); CHECK(return, AstReturn* retnode); -CHECK(if, AstIf* ifnode); -CHECK(while, AstWhile* whilenode); +CHECK(if, AstIfWhile* ifnode); +CHECK(while, AstIfWhile* whilenode); CHECK(for, AstFor* fornode); CHECK(call, AstCall* call); CHECK(binaryop, AstBinaryOp** pbinop, b32 assignment_is_ok); @@ -62,7 +62,9 @@ CHECK(return, AstReturn* retnode) { return 0; } -CHECK(if, AstIf* ifnode) { +CHECK(if, AstIfWhile* ifnode) { + if (ifnode->assignment != NULL) check_statement((AstNode *) ifnode->assignment); + if (check_expression(&ifnode->cond)) return 1; if (!type_is_bool(ifnode->cond->type)) { @@ -78,7 +80,9 @@ CHECK(if, AstIf* ifnode) { return 0; } -CHECK(while, AstWhile* whilenode) { +CHECK(while, AstIfWhile* whilenode) { + if (whilenode->assignment != NULL) check_statement((AstNode *) whilenode->assignment); + if (check_expression(&whilenode->cond)) return 1; if (!type_is_bool(whilenode->cond->type)) { @@ -88,7 +92,10 @@ CHECK(while, AstWhile* whilenode) { return 1; } - return check_block(whilenode->stmt); + if (whilenode->true_stmt) if (check_block(whilenode->true_stmt)) return 1; + if (whilenode->false_stmt) if (check_block(whilenode->false_stmt)) return 1; + + return 0; } CHECK(for, AstFor* fornode) { @@ -900,8 +907,8 @@ CHECK(statement, AstNode* stmt) { case Ast_Kind_Continue: return 0; case Ast_Kind_Return: return check_return((AstReturn *) stmt); - case Ast_Kind_If: return check_if((AstIf *) stmt); - case Ast_Kind_While: return check_while((AstWhile *) stmt); + case Ast_Kind_If: return check_if((AstIfWhile *) stmt); + case Ast_Kind_While: return check_while((AstIfWhile *) stmt); case Ast_Kind_For: return check_for((AstFor *) stmt); case Ast_Kind_Block: return check_block((AstBlock *) stmt); case Ast_Kind_Defer: { @@ -1113,8 +1120,8 @@ CHECK(node, AstNode* node) { case Ast_Kind_Overloaded_Function: return check_overloaded_function((AstOverloadedFunction *) node); case Ast_Kind_Block: return check_block((AstBlock *) node); case Ast_Kind_Return: return check_return((AstReturn *) node); - case Ast_Kind_If: return check_if((AstIf *) node); - case Ast_Kind_While: return check_while((AstWhile *) node); + case Ast_Kind_If: return check_if((AstIfWhile *) node); + case Ast_Kind_While: return check_while((AstIfWhile *) node); case Ast_Kind_Call: return check_call((AstCall *) node); case Ast_Kind_Binary_Op: return check_binaryop((AstBinaryOp **) &node, 1); default: return check_expression((AstTyped **) &node); diff --git a/src/onyxparser.c b/src/onyxparser.c index 1794b7f0..bbd2cfa9 100644 --- a/src/onyxparser.c +++ b/src/onyxparser.c @@ -27,8 +27,8 @@ static AstNumLit* parse_float_literal(OnyxParser* parser); static b32 parse_possible_struct_literal(OnyxParser* parser, AstTyped** ret); static AstTyped* parse_factor(OnyxParser* parser); static AstTyped* parse_expression(OnyxParser* parser); -static AstIf* parse_if_stmt(OnyxParser* parser); -static AstWhile* parse_while_stmt(OnyxParser* parser); +static AstIfWhile* parse_if_stmt(OnyxParser* parser); +static AstIfWhile* parse_while_stmt(OnyxParser* parser); static AstFor* parse_for_stmt(OnyxParser* parser); static b32 parse_possible_symbol_declaration(OnyxParser* parser, AstNode** ret); static AstReturn* parse_return_statement(OnyxParser* parser); @@ -705,15 +705,31 @@ expression_done: } // 'if' ('elseif' )* ('else' )? -static AstIf* parse_if_stmt(OnyxParser* parser) { +static AstIfWhile* parse_if_stmt(OnyxParser* parser) { expect_token(parser, Token_Type_Keyword_If); + AstIfWhile* if_node = make_node(AstIfWhile, Ast_Kind_If); + AstIfWhile* root_if = if_node; + + if ((parser->curr + 1)->type == ':') { + if_node->local = make_node(AstLocal, Ast_Kind_Local); + if_node->local->token = expect_token(parser, Token_Type_Symbol); + + expect_token(parser, ':'); + + AstBinaryOp* assignment = make_node(AstBinaryOp, Ast_Kind_Binary_Op); + assignment->operation = Binary_Op_Assign; + assignment->token = expect_token(parser, '='); + assignment->left = (AstTyped *) if_node->local; + assignment->right = parse_expression(parser); + + if_node->assignment = assignment; + expect_token(parser, ';'); + } + AstTyped* cond = parse_expression(parser); AstBlock* true_stmt = parse_block(parser); - AstIf* if_node = make_node(AstIf, Ast_Kind_If); - AstIf* root_if = if_node; - if_node->cond = cond; if (true_stmt != NULL) if_node->true_stmt = true_stmt; @@ -722,7 +738,7 @@ static AstIf* parse_if_stmt(OnyxParser* parser) { if (parser->hit_unexpected_token) return root_if; consume_token(parser); - AstIf* elseif_node = make_node(AstIf, Ast_Kind_If); + AstIfWhile* elseif_node = make_node(AstIfWhile, Ast_Kind_If); cond = parse_expression(parser); true_stmt = parse_block(parser); @@ -747,16 +763,34 @@ static AstIf* parse_if_stmt(OnyxParser* parser) { } // 'while' -static AstWhile* parse_while_stmt(OnyxParser* parser) { +static AstIfWhile* parse_while_stmt(OnyxParser* parser) { OnyxToken* while_token = expect_token(parser, Token_Type_Keyword_While); + AstIfWhile* while_node = make_node(AstIfWhile, Ast_Kind_While); + while_node->token = while_token; - AstTyped* cond = parse_expression(parser); - AstBlock* stmt = parse_block(parser); + if ((parser->curr + 1)->type == ':') { + while_node->local = make_node(AstLocal, Ast_Kind_Local); + while_node->local->token = expect_token(parser, Token_Type_Symbol); - AstWhile* while_node = make_node(AstWhile, Ast_Kind_While); - while_node->token = while_token; - while_node->cond = cond; - while_node->stmt = stmt; + expect_token(parser, ':'); + + AstBinaryOp* assignment = make_node(AstBinaryOp, Ast_Kind_Binary_Op); + assignment->operation = Binary_Op_Assign; + assignment->token = expect_token(parser, '='); + assignment->left = (AstTyped *) while_node->local; + assignment->right = parse_expression(parser); + + while_node->assignment = assignment; + expect_token(parser, ';'); + } + + while_node->cond = parse_expression(parser); + while_node->true_stmt = parse_block(parser); + + if (parser->curr->type == Token_Type_Keyword_Else) { + consume_token(parser); + while_node->false_stmt = parse_block(parser); + } return while_node; } diff --git a/src/onyxsymres.c b/src/onyxsymres.c index 66206ac5..603e5a63 100644 --- a/src/onyxsymres.c +++ b/src/onyxsymres.c @@ -16,8 +16,8 @@ static void symres_align_of(AstAlignOf* so); static void symres_field_access(AstFieldAccess** fa); static void symres_expression(AstTyped** expr); static void symres_return(AstReturn* ret); -static void symres_if(AstIf* ifnode); -static void symres_while(AstWhile* whilenode); +static void symres_if(AstIfWhile* ifnode); +static void symres_while(AstIfWhile* whilenode); static void symres_for(AstFor* fornode); static void symres_statement_chain(AstNode** walker); static b32 symres_statement(AstNode** stmt); @@ -325,22 +325,40 @@ static void symres_return(AstReturn* ret) { symres_expression(&ret->expr); } -static void symres_if(AstIf* ifnode) { +static void symres_if(AstIfWhile* ifnode) { + if (ifnode->assignment != NULL) { + ifnode->scope = scope_create(semstate.node_allocator, semstate.curr_scope); + scope_enter(ifnode->scope); + + symbol_introduce(semstate.curr_scope, ifnode->local->token, (AstNode *) ifnode->local); + + symres_statement((AstNode **) &ifnode->assignment); + } + symres_expression(&ifnode->cond); - // BUG: This will not work for the following case: - // if cond foo := 10 - // else foo := 20 - // - // The declaration will cause a problem but semantically the above - // doesn't make sense. if (ifnode->true_stmt != NULL) symres_statement((AstNode **) &ifnode->true_stmt); if (ifnode->false_stmt != NULL) symres_statement((AstNode **) &ifnode->false_stmt); + + if (ifnode->assignment != NULL) scope_leave(); } -static void symres_while(AstWhile* whilenode) { +static void symres_while(AstIfWhile* whilenode) { + if (whilenode->assignment != NULL) { + whilenode->scope = scope_create(semstate.node_allocator, semstate.curr_scope); + scope_enter(whilenode->scope); + + symbol_introduce(semstate.curr_scope, whilenode->local->token, (AstNode *) whilenode->local); + + symres_statement((AstNode **) &whilenode->assignment); + } + symres_expression(&whilenode->cond); - symres_block(whilenode->stmt); + + if (whilenode->true_stmt) symres_block(whilenode->true_stmt); + if (whilenode->false_stmt) symres_block(whilenode->false_stmt); + + if (whilenode->assignment != NULL) scope_leave(); } static void symres_for(AstFor* fornode) { @@ -363,8 +381,8 @@ static b32 symres_statement(AstNode** stmt) { switch ((*stmt)->kind) { case Ast_Kind_Local: symres_local((AstLocal **) stmt); return 1; case Ast_Kind_Return: symres_return((AstReturn *) *stmt); return 0; - case Ast_Kind_If: symres_if((AstIf *) *stmt); return 0; - case Ast_Kind_While: symres_while((AstWhile *) *stmt); return 0; + case Ast_Kind_If: symres_if((AstIfWhile *) *stmt); return 0; + case Ast_Kind_While: symres_while((AstIfWhile *) *stmt); return 0; case Ast_Kind_For: symres_for((AstFor *) *stmt); return 0; case Ast_Kind_Call: symres_call((AstCall *) *stmt); return 0; case Ast_Kind_Argument: symres_expression((AstTyped **) &((AstArgument *) *stmt)->value); return 0; diff --git a/src/onyxwasm.c b/src/onyxwasm.c index 7c23f9ad..dad44852 100644 --- a/src/onyxwasm.c +++ b/src/onyxwasm.c @@ -306,6 +306,9 @@ static u64 local_allocate(LocalAllocator* la, AstLocal* local) { if (la->max_stack < la->curr_stack) la->max_stack = la->curr_stack; + if (size % alignment != 0) + size += alignment - (size % alignment); + if (la->max_stack - la->curr_stack >= size) { la->curr_stack += size; } else { @@ -354,8 +357,8 @@ COMPILE_FUNC(statement, AstNode* stmt); COMPILE_FUNC(assignment, AstBinaryOp* assign); COMPILE_FUNC(store_instruction, Type* type, u32 offset); COMPILE_FUNC(load_instruction, Type* type, u32 offset); -COMPILE_FUNC(if, AstIf* if_node); -COMPILE_FUNC(while, AstWhile* while_node); +COMPILE_FUNC(if, AstIfWhile* if_node); +COMPILE_FUNC(while, AstIfWhile* while_node); COMPILE_FUNC(for, AstFor* for_node); COMPILE_FUNC(defer, AstDefer* defer); COMPILE_FUNC(deferred_stmts, AstNode* node); @@ -445,8 +448,8 @@ COMPILE_FUNC(statement, AstNode* stmt) { switch (stmt->kind) { case Ast_Kind_Return: compile_return(mod, &code, (AstReturn *) 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_If: compile_if(mod, &code, (AstIfWhile *) stmt); break; + case Ast_Kind_While: compile_while(mod, &code, (AstIfWhile *) stmt); break; case Ast_Kind_For: compile_for(mod, &code, (AstFor *) stmt); break; case Ast_Kind_Break: compile_structured_jump(mod, &code, ((AstBreak *) stmt)->count); break; case Ast_Kind_Continue: compile_structured_jump(mod, &code, -((AstContinue *) stmt)->count); break; @@ -635,21 +638,26 @@ COMPILE_FUNC(load_instruction, Type* type, u32 offset) { *pcode = code; } -COMPILE_FUNC(if, AstIf* if_node) { +COMPILE_FUNC(if, AstIfWhile* if_node) { bh_arr(WasmInstruction) code = *pcode; + if (if_node->assignment != NULL) { + bh_imap_put(&mod->local_map, (u64) if_node->local, local_allocate(mod->local_alloc, if_node->local)); + + compile_assignment(mod, &code, if_node->assignment); + } + compile_expression(mod, &code, if_node->cond); WID(WI_IF_START, 0x40); bh_arr_push(mod->structured_jump_target, 0); - if (if_node->true_stmt) compile_block(mod, &code, if_node->true_stmt, 0); if (if_node->false_stmt) { WI(WI_ELSE); if (if_node->false_stmt->kind == Ast_Kind_If) { - compile_if(mod, &code, (AstIf *) if_node->false_stmt); + compile_if(mod, &code, (AstIfWhile *) if_node->false_stmt); } else { compile_block(mod, &code, if_node->false_stmt, 0); } @@ -657,33 +665,68 @@ COMPILE_FUNC(if, AstIf* if_node) { bh_arr_pop(mod->structured_jump_target); + if (if_node->assignment != NULL) { + local_free(mod->local_alloc, if_node->local); + } + WI(WI_IF_END); *pcode = code; } -COMPILE_FUNC(while, AstWhile* while_node) { +COMPILE_FUNC(while, AstIfWhile* while_node) { bh_arr(WasmInstruction) code = *pcode; - WID(WI_BLOCK_START, 0x40); - WID(WI_LOOP_START, 0x40); + if (while_node->assignment != NULL) { + bh_imap_put(&mod->local_map, (u64) while_node->local, local_allocate(mod->local_alloc, while_node->local)); - compile_expression(mod, &code, while_node->cond); - WI(WI_I32_EQZ); - WID(WI_COND_JUMP, 0x01); + compile_assignment(mod, &code, while_node->assignment); + } - bh_arr_push(mod->structured_jump_target, 1); - bh_arr_push(mod->structured_jump_target, 2); + if (while_node->false_stmt == NULL) { + WID(WI_BLOCK_START, 0x40); + WID(WI_LOOP_START, 0x40); - compile_block(mod, &code, while_node->stmt, 0); + compile_expression(mod, &code, while_node->cond); + WI(WI_I32_EQZ); + WID(WI_COND_JUMP, 0x01); - bh_arr_pop(mod->structured_jump_target); - bh_arr_pop(mod->structured_jump_target); + bh_arr_push(mod->structured_jump_target, 1); + bh_arr_push(mod->structured_jump_target, 2); - WID(WI_JUMP, 0x00); + compile_block(mod, &code, while_node->true_stmt, 0); - WI(WI_LOOP_END); - WI(WI_BLOCK_END); + bh_arr_pop(mod->structured_jump_target); + bh_arr_pop(mod->structured_jump_target); + + WID(WI_JUMP, 0x00); + + WI(WI_LOOP_END); + WI(WI_BLOCK_END); + + } else { + compile_expression(mod, &code, while_node->cond); + + bh_arr_push(mod->structured_jump_target, 1); + bh_arr_push(mod->structured_jump_target, 2); + WID(WI_IF_START, 0x40); + + WID(WI_LOOP_START, 0x40); + compile_block(mod, &code, while_node->true_stmt, 0); + compile_expression(mod, &code, while_node->cond); + WID(WI_COND_JUMP, 0x00); + WI(WI_LOOP_END); + + WI(WI_ELSE); + compile_block(mod, &code, while_node->false_stmt, 0); + WID(WI_IF_END, 0x40); + + bh_arr_pop(mod->structured_jump_target); + bh_arr_pop(mod->structured_jump_target); + } + + if (while_node->assignment != NULL) + local_free(mod->local_alloc, while_node->local); *pcode = code; } -- 2.25.1