From 65742222806fbb3a90eda877cb9b7fdf1887147e Mon Sep 17 00:00:00 2001 From: IgorCielniak Date: Sun, 14 Dec 2025 00:38:19 +0100 Subject: [PATCH] commit --- __pycache__/main.cpython-314.pyc | Bin 146648 -> 146914 bytes a.out | Bin 10408 -> 11072 bytes a.sl | 3 +- build/a.asm | 93 +++- build/a.o | Bin 3440 -> 4096 bytes build/call_syntax_parens.asm | 93 +++- build/call_syntax_parens.o | Bin 3488 -> 4176 bytes build/hello.asm | 388 ++++++++++++++ build/hello.o | Bin 0 -> 4096 bytes build/loops_and_cmp.asm | 93 +++- build/loops_and_cmp.o | Bin 3552 -> 4208 bytes build/main.asm | 93 +++- build/main.o | Bin 3472 -> 4160 bytes build/override_dup_compile_time.asm | 93 +++- build/override_dup_compile_time.o | Bin 3376 -> 4016 bytes build/string_puts.asm | 93 +++- build/string_puts.o | Bin 3712 -> 4368 bytes build/test.asm | 93 +++- build/test.o | Bin 6784 -> 7472 bytes fn.sl | 26 +- main.py | 567 +++++++++++--------- stdlib.sl | 115 +++- tests/__pycache__/run_tests.cpython-314.pyc | Bin 0 -> 5770 bytes 23 files changed, 1473 insertions(+), 277 deletions(-) create mode 100644 build/hello.asm create mode 100644 build/hello.o create mode 100644 tests/__pycache__/run_tests.cpython-314.pyc diff --git a/__pycache__/main.cpython-314.pyc b/__pycache__/main.cpython-314.pyc index 8c2e145e55052fc0f3849d4388b87c850fb32098..a3aa38d1d044b23ae348481d1cfc96f884077925 100644 GIT binary patch delta 51264 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�MB}A-;+6MZ~u;ZW8|~ z<6k5GI^+Gs4>P`%_zA{eB7T&x zaUbzBjJFZLZBp@g77)Lm@rQ{oWIRSZ$@p60TN%$0|HNIz{eFk|GRAij-^}zNW zpCG=WsaSs=cpa>Z`reKTc24q}$9ZWK{w{GIUvy{VJ&{>fG-EY~G6`X3tWer&PNvN0 z+PGz|4)tWCVofR?F?+LCMqmMww3&>q>4_(!W-8g!=g{7CJZYKm<5WZ4q>jW_#+7GJ zD%DFd;wzJm6^ke1nN=pqWLJ@FuhVBF4SI=EtD|Yh%B%?yOQ$RcnSKzGos3hfl?^}c zH2d9nsH0}T7su}fH~rmiNM(eS5mUw-GFl^MYec~o&u$GX0p-qY4Qs7Y&u*LTx;sW9 zp=OuJCS4oX!f6jBslybdBdI2CwyF%J!F1GVZ@#^8m5#J$CZY+*U8YCH=;~Y)m`5E& zA}y_sxg>=v>yKvQPf%P%){aV3u~;TbWA@Z)x*qYj6!+10%ZNyC6|v9c5kW~2W1(cY z&kRKY{ogRUFStuyRm)m+Ia&Q@~24DUC$DHCG@M zPN#~xjmJdLjK|Das3#LO{cTPynv9r!+Kl8HmF*Fx|8$Y}Lz;KHW@KYCk97BK zLO={oCbm0irj9k!p`&#=o!0tC>xj+}Y#D?VqOHY|KPpqEP_4FaMx;er0|nfkbMLwD z-FHLsPyg)h4ELV4OlvqYCDmj%5w_3dGm!jkcc zm#cCH${8qUpqznn2Fe*IXP}&cat6v7C}*IYfpP}^A2Sdhz4cOE1?wvOJv_SdA9a&7-)`*jM3E=kXJ-^(H*nc!DnI& zU1qyy841G_}(D&>NeLtC@?-{qx7-6&$ad<*Fufh_Zzpjyae9c{ynXZur%7Ls` zQG0FEI2=VhaUxd=pR4kC!S9wyxqnt#^URAPLmmEV$ zpDOv5E;)dbdsK-!mj;|m3rbp52_7nYF5-498q_{~nJDLpE4QmqauXJ3|ARaB4zB(< zxJcD5RQ(x%{Ryf*z~V4Ur2zV!koa~}a?F&pZ&7U6AtyNc+WRo%{mPK-Ff;oh9C8S| zf@r1C3c15Tp-bDL@xt!hR6KcKTxL0Pi4(?G5sjdVa$#8eTo+ka{>X~E}og- z_m_RAXC@mE-44iJs;&;Gvj=>oG8}w$JbHVGt`@l*K35+fwUZg8*YVmJd=Kv&`>l)0 zBJoH_A3lN_^(GnB9)s!Nr6nVsh^f5Wae zw4Oxk%Mi*wf>tY9ThLmrPISuV4x(=rNaV1p0$=~zTT$`uMHosw2`q-ROQ(qE_F5l&2CCWllHMnN{ZhehlfT~~ z!L7WmV1A9a5VthmN&G2|8ukn8pKdSL7#NXAp z4-W+F%Te}nj8jenc?+ZyjC z{+`B@#4l*PpZG~t~@ueESM0}&h=i-$QdCqFQkvLoAjo(bXRpWOOPig$? z#2?l87UF{%PZ2+?@m<6xHC`ZIv)DV&v1#~EiO<*cFA`s?@k7KP)cBjkqZe?#MUaSofm%&YHocn6H*el|_Rw>W&A zD+a538lEJ+XPH+&2)rKFCI1dX2HVN`)OkKW4bKzTS$tH zLV6}MnO=&K*p?PnJdsZ1wwom5Lq+qwV$5h3^c-dSVp(D3`Xj_lf44xUKPrugG~&`& zO-3MU1{_(NYX^FyfEH>7dX(OnYp-gRG24WZO3A6D@@dD$#5o~p(pfV=(X;NFdJ{bl z3t`qZQ?V2*Czs4njINH2p|1&5BpPiC2y;^glkJb?5<4lbBs-?1nRq-Gqo}T0F3Kf- zTAd^V*NlktS`i0KJt8P6Vmy-W88BfPVi9=gV6A#Pm#1x|{!~8c(MJ<~o^~qZjprtq z0yxKs+U^OGz{+GPjdDz9HzkPlWHX*&6LA(c6LB*hN#ILh^ROb_d<6*&K%2x2{Y5|&f#4G*9|jc z(TEjctT{K3vLfA3TUk+WmzEXVVX%7@GwMZL=kMHT7{b(I z>}Ig=#UcMXLMp#6mSKZ2=kMJ_Q~tRewZzzPdr$ea-Y8HIgTn`|ZMGTyQIjn}2p@bu jYSpbb|`CnZwR8%=Gy8nLxHtEtr diff --git a/a.sl b/a.sl index 9f3cb37..f18d4fc 100644 --- a/a.sl +++ b/a.sl @@ -2,4 +2,5 @@ import stdlib.sl : main "hello world" puts -; \ No newline at end of file +; +compile-time main \ No newline at end of file diff --git a/build/a.asm b/build/a.asm index f676e86..12c9dff 100644 --- a/build/a.asm +++ b/build/a.asm @@ -19,7 +19,7 @@ _start: mov rax, 60 syscall word_puts: - ; detects string if top is len>=0 and next is a pointer in [data_start, data_end) + ; detects string if top is len>=0 and next is a pointer in [data_start, data_end] mov rax, [r12] ; len or int value mov rbx, [r12 + 8] ; possible address cmp rax, 0 @@ -114,6 +114,64 @@ word_swap: mov [r12], rbx mov [r12 + 8], rax ret +word_rot: + mov rax, [r12] ; x3 + mov rbx, [r12 + 8] ; x2 + mov rcx, [r12 + 16] ; x1 + mov [r12], rcx ; top = x1 + mov [r12 + 8], rax ; next = x3 + mov [r12 + 16], rbx ; third = x2 + ret +word__2drot: + mov rax, [r12] ; x3 + mov rbx, [r12 + 8] ; x2 + mov rcx, [r12 + 16] ; x1 + mov [r12], rbx ; top = x2 + mov [r12 + 8], rcx ; next = x1 + mov [r12 + 16], rax ; third = x3 + ret +word_nip: + mov rax, [r12] + add r12, 8 ; drop lower element + mov [r12], rax ; keep original top + ret +word_tuck: + mov rax, [r12] ; x2 + mov rbx, [r12 + 8] ; x1 + sub r12, 8 ; make room + mov [r12], rax ; x2 + mov [r12 + 8], rbx ; x1 + mov [r12 + 16], rax ; x2 + ret +word_2dup: + mov rax, [r12] ; b + mov rbx, [r12 + 8] ; a + sub r12, 8 + mov [r12], rbx ; push a + sub r12, 8 + mov [r12], rax ; push b + ret +word_2drop: + add r12, 16 + ret +word_2swap: + mov rax, [r12] ; d + mov rbx, [r12 + 8] ; c + mov rcx, [r12 + 16] ; b + mov rdx, [r12 + 24] ; a + mov [r12], rcx ; top = b + mov [r12 + 8], rdx ; next = a + mov [r12 + 16], rax ; third = d + mov [r12 + 24], rbx ; fourth = c + ret +word_2over: + mov rax, [r12 + 16] ; b + mov rbx, [r12 + 24] ; a + sub r12, 8 + mov [r12], rbx ; push a + sub r12, 8 + mov [r12], rax ; push b + ret word__2b: mov rax, [r12] add r12, 8 @@ -242,6 +300,39 @@ word_exit: mov rax, 60 syscall ret +word_and: + mov rax, [r12] + add r12, 8 + mov rbx, [r12] + test rax, rax + setz cl + test rbx, rbx + setz dl + movzx rcx, cl + movzx rdx, dl + and rcx, rdx + mov [r12], rcx + ret +word_or: + mov rax, [r12] + add r12, 8 + mov rbx, [r12] + test rax, rax + setz cl + test rbx, rbx + setz dl + movzx rcx, cl + movzx rdx, dl + or rcx, rdx + mov [r12], rcx + ret +word_not: + mov rax, [r12] + test rax, rax + setz al + movzx rax, al + mov [r12], rax + ret word__3er: mov rax, [r12] add r12, 8 diff --git a/build/a.o b/build/a.o index fb710811f2c073eb05fec9e28f02eabecc2dba69..9d068215e1991b2d043ef83093b25f244c98e78a 100644 GIT binary patch literal 4096 zcmbW4U1%It6oBtGNxNxlcPX(33AEJ}45n+cX_3%Y6G(MNHwbM(g}^ZBZkom2**H7f zw9sNDL^`a&m-L}v^{M!%fQ`Nu{EnsB%tSON7W21{4fj7^S6O5uL=5h$M6p8kar<)8tBXOr^g>bi$3@F z^!N^x=5|83Ny)mFoTy%@Pw1nUqndklau3j0gCv#yL{uBSBaRl)4(^toF#6XrqhbM5DHF zqeuFX`FZr|xv(DYXi(mu)uykkZP#iS|7g)VW;ORmec|@WO8}-%Z2_veRc-7>`Bxq0 z?KDc`9e}UYZ(0vsXg2Pbx;vkCr(+E?l|Q4pTc4<69f0&EqWY+Zusm1{-EB$eE~u1? zM3rsGup!9O0+2ysnU|rx~iYz2F50; zSi2xgSa*6A-CL{Z-dRQW_A0uwfljN4U?1fAV9qX-3eG@Z1vV9gKB`P#rHN|b^*d?2 zCo$QGi)^4+A-*BZ_egts!tSoc*i>xdA{^Y<#3e2E@in++we8>HhW@u*V_>IYoGI|0 zx_eopx8P9i6A){k&_}-r9c>r@RV#(v{VF(QKJ5J(e7r{ig{$@WLQ@cAT;tsJ#agY3 z6x&cXpD%73Dcbpr0!b%()Dg*y>6jupP%4RJX{hAbjyV9*v4ZMpY-jVPvRA&V-0@XX zFXn5@nba-&3yJSx_Od1Cx@F$bO;Q&TkFo@<#8ZrS5_cHaiBB;8BJmFyH;Mnicwq%T zLi{gg{~GZ%Sg24_^N5J8jGvV@5z)r@yTm&f|A6>YjLT;p>c5}y%Vb|RZ z4CB8L|A_Hh#J^$u4)O09uao15SY&(?@h$AAJV5+m#%_M+{wDEVjH~^Nhyvs1$bO9R_lTcn zT>gB+x%!OpDYE~K@oU8IF#a9!M)(Q}x0}QtWPFbJR>p4=$FHey`-k|mjIWdRWkm+Z z%`5O`$>(eMh7Gre$ew>UKPEX_EI6ioE+^)P+Pebp^|=&$`{!5SFA?Y8;rO)}hyA*z z4U}{F%;RR#EER-Na!lKyE@>5w?9rTK95M6dtbm`8j4@nxN&;_SX&Y8{B%iagM$yV2 zQ*_wQS&jjh8kz%Soyi@}d7k-VahPJ{4qHkZ%vrh8kU?fLRi-?wa%OC>m#BCoYb&WV zViL29jzUHX3`w?fq;<-NURLUq9}n$FoeJWlg5XAKzz^vOrY8(~!Y&dzGe&2|gB^j~ zdB`)M+8LdPLfUK~?`-$ol~5>nt1FZ(U&g&qdefqWMJk8oE!^nzDrAGGtnFaE!#S@U zb|4naoF(vcfOa2uwq3}(kjI>29bh66>k6;Yie>HrLs2Zb*g=<7G{iNIru zkK_`4G01;2Fb=pntG(oj9DSE+sy)ZJ_dn}Mh-3W4nu>FZ@g?G)Fn*lAN%o^NG<@E@ HIpg?Wj4{B< delta 829 zcmZor_#ic50h1&1#6@OI6IdtSvSV7nI$4SlOhqx;i9TRu0D}`O5Sk508BJcxsLi#3 z3nKE1aq=TZGo}qZlcks}n0T2thcG!aZjNSYW}NKEmc;Yv&;S32Au1U*uVB+)s*h)c za-q~&FwMx2gC>3rDqf2wejh468BP2JRD30x_!p@7QHc2DG)DeDh`4Q^2Jm1yEYlMT7VCmV2a z)L%rCNrUQmgeG1975|JTUJVuhfhOJx73XC}awd>D0V=Kx5$A!+&SGSk+{h@(yc9wk zuLdjp_@5iD0>an|7H48W=!A&x1L|{R6s?EE5Xf|}Lb&b=U@oTkb+|aH4<6wVe*+b7 xU_e#R3$#gqfpPMF9-)Z=9Fs5d?4SIYcj4rDeDfze@UM{2hK2*kJ5VOrX#j3rP22zg diff --git a/build/call_syntax_parens.asm b/build/call_syntax_parens.asm index 031a9dd..e644000 100644 --- a/build/call_syntax_parens.asm +++ b/build/call_syntax_parens.asm @@ -19,7 +19,7 @@ _start: mov rax, 60 syscall word_puts: - ; detects string if top is len>=0 and next is a pointer in [data_start, data_end) + ; detects string if top is len>=0 and next is a pointer in [data_start, data_end] mov rax, [r12] ; len or int value mov rbx, [r12 + 8] ; possible address cmp rax, 0 @@ -114,6 +114,64 @@ word_swap: mov [r12], rbx mov [r12 + 8], rax ret +word_rot: + mov rax, [r12] ; x3 + mov rbx, [r12 + 8] ; x2 + mov rcx, [r12 + 16] ; x1 + mov [r12], rcx ; top = x1 + mov [r12 + 8], rax ; next = x3 + mov [r12 + 16], rbx ; third = x2 + ret +word__2drot: + mov rax, [r12] ; x3 + mov rbx, [r12 + 8] ; x2 + mov rcx, [r12 + 16] ; x1 + mov [r12], rbx ; top = x2 + mov [r12 + 8], rcx ; next = x1 + mov [r12 + 16], rax ; third = x3 + ret +word_nip: + mov rax, [r12] + add r12, 8 ; drop lower element + mov [r12], rax ; keep original top + ret +word_tuck: + mov rax, [r12] ; x2 + mov rbx, [r12 + 8] ; x1 + sub r12, 8 ; make room + mov [r12], rax ; x2 + mov [r12 + 8], rbx ; x1 + mov [r12 + 16], rax ; x2 + ret +word_2dup: + mov rax, [r12] ; b + mov rbx, [r12 + 8] ; a + sub r12, 8 + mov [r12], rbx ; push a + sub r12, 8 + mov [r12], rax ; push b + ret +word_2drop: + add r12, 16 + ret +word_2swap: + mov rax, [r12] ; d + mov rbx, [r12 + 8] ; c + mov rcx, [r12 + 16] ; b + mov rdx, [r12 + 24] ; a + mov [r12], rcx ; top = b + mov [r12 + 8], rdx ; next = a + mov [r12 + 16], rax ; third = d + mov [r12 + 24], rbx ; fourth = c + ret +word_2over: + mov rax, [r12 + 16] ; b + mov rbx, [r12 + 24] ; a + sub r12, 8 + mov [r12], rbx ; push a + sub r12, 8 + mov [r12], rax ; push b + ret word__2b: mov rax, [r12] add r12, 8 @@ -242,6 +300,39 @@ word_exit: mov rax, 60 syscall ret +word_and: + mov rax, [r12] + add r12, 8 + mov rbx, [r12] + test rax, rax + setz cl + test rbx, rbx + setz dl + movzx rcx, cl + movzx rdx, dl + and rcx, rdx + mov [r12], rcx + ret +word_or: + mov rax, [r12] + add r12, 8 + mov rbx, [r12] + test rax, rax + setz cl + test rbx, rbx + setz dl + movzx rcx, cl + movzx rdx, dl + or rcx, rdx + mov [r12], rcx + ret +word_not: + mov rax, [r12] + test rax, rax + setz al + movzx rax, al + mov [r12], rax + ret word__3er: mov rax, [r12] add r12, 8 diff --git a/build/call_syntax_parens.o b/build/call_syntax_parens.o index 4cfec6cc1283112073934f3ca22c12992eb6328c..1c32cdf479c8a9767945fe161f3424548bb9b27f 100644 GIT binary patch literal 4176 zcmbW4YiJx*6oBtGN!_%y8zhz>!M34u>P;v1ERUs{@uIJo)W@mbujo^iu zd+v9h_snBwpWBjncv&PO{1Fikh+ySYA$kLmEHYR)aVywF;i%?+NKhdZi|4;>5nnX*^WR5){=|FR42l~wD9fj*{;4{( z#{TrcfwkgjQj>_o%xg#0I@}nHXIXHbzXfb~PtfmJ49`Nmr6z%8pfAs#n7A7)2E3mV z6B|(~ZGv!9l67Bqqk5q>u8(~Z)x0xPSbwZelETh-R2#c0_HRo}$Q>poWWkB<;{M)5 z_vZ)h*Ss0c`yN~ywDCE2)f6WG7*DafS?RGNK-xqXCOoCo#UN*~PgbIhErvs_{7S8Ses+1ARzCepv(`SRdEe;se;k?taQ^Tbpqf|I#xLbB>rl5_ zFO4?>o~>QI0;W(k-e5oVCF&|-juo=479M?TiDHn+f ziFkwVtx{a~cE%fSQle7=z59J7G z3$lcDN0!jNx`ghHC3LSZp?fXRX$28n2f06}*@ITWJupy!iweR3b!MQ@NImf9O|nK);uMG1ZX-`ksjlCG3j!mA18#gvNqs301g=0=ze*rJ(f7{gub{fW+2Jh(` zw>9<~+*Dfx#M&bCu}?#{HY|Xuox;^U7u;kO*#8Ci_>Te#XKLg4!jcf=4Ir1^`MX>$ z%`TM7KE=n}m(jX}FX7UgAq!ZGVrfSi9Jj&AH%44K7y=lnltHttm_$dZA5KNIRHM~R z?R7$v71Nc%EsrnQqwo66qzt~z7pT5+Ykm_dzv)84G9S@f3z z-~TuN0?4;A#K8`R$7Z>Rh>kD>xu3Yp_*29u8MlbP%eX`QBI5_E@WaIaWcDu+Uxtke zjpI^|h_#HLAl|~beE&lq+8LiA`v)06NBnWdzb2k#{0HJMF#a>~qm2JW{5{71A^s)f z^>Q5%UoqZDe1UP*mxx%ye)l(!{auW!zC=VD%vj=oqYo^aaxwhJB%ngwCYVne<_MAa@S=2Gl#F zb10-u1@fl0in|gr8Gm<~yj_v;S}46~Q^G8@!}d3Bbow1~KvdRFu-_5OZ-*0z8Pl?r z<#0AD@WX&^11Y8;R}yXua8#4wLiZd+)Fg?z@`L$dQIQPvWy60`@b<+=?>c=k(BC`x tMWDF4hx^GN?a}u-e9ho^v$ag4K2R&mttvifftj{iQh-_O2D{so2){tf^D delta 783 zcmcbhut0jk0;Ubj6Bn5=ePEsFC^qqf29PmXiqQ^4MKRim8n7{d!3Gux4dNP3UdyP> z`G5-|!ZP_GqdC(Dp2<>77EHX%n?snK88=6>G&4?iWJ_Wf`uG3;i?@F!uVPbRI{jzz z88#dKwSR#^p8tV_3y?UxS%F=EsXm?&Vj7IR2WBubC7ov%WL&aC3i6>8<$R$2`0vAX9MKqamsE$Wy;*C)8&uHR3Q1KsV;?tnw zyv(RxUI-OehKQ@cWmiKbO3*ZHVPu%x$SBIZA4;D9(vFOxN$0`pL5jf)xH-3Qh(qEE lq#o6!Z{X@t#lJC5e#N6dS&{d`WEZ}LlmGM0o4kO30{~!BT>$_9 diff --git a/build/hello.asm b/build/hello.asm new file mode 100644 index 0000000..1d5188d --- /dev/null +++ b/build/hello.asm @@ -0,0 +1,388 @@ +section .text +%define DSTK_BYTES 65536 +%define RSTK_BYTES 65536 +%define PRINT_BUF_BYTES 128 +global _start +_start: + ; initialize data/return stack pointers + lea r12, [rel dstack_top] + mov r15, r12 + lea r13, [rel rstack_top] + call word_main + mov rax, 0 + cmp r12, r15 + je .no_exit_value + mov rax, [r12] + add r12, 8 +.no_exit_value: + mov rdi, rax + mov rax, 60 + syscall +word_puts: + ; detects string if top is len>=0 and next is a pointer in [data_start, data_end) + mov rax, [r12] ; len or int value + mov rbx, [r12 + 8] ; possible address + cmp rax, 0 + jl puts_print_int + lea r8, [rel data_start] + lea r9, [rel data_end] + cmp rbx, r8 + jl puts_print_int + cmp rbx, r9 + jge puts_print_int + ; treat as string: (addr below len) + mov rdx, rax ; len + mov rsi, rbx ; addr + add r12, 16 ; pop len + addr + test rdx, rdx + jz puts_str_newline_only + mov rax, 1 + mov rdi, 1 + syscall +puts_str_newline_only: + mov byte [rel print_buf], 10 + mov rax, 1 + mov rdi, 1 + lea rsi, [rel print_buf] + mov rdx, 1 + syscall + ret + +puts_print_int: + mov rax, [r12] + add r12, 8 + mov rbx, rax + mov r8, 0 + cmp rbx, 0 + jge puts_abs + neg rbx + mov r8, 1 +puts_abs: + lea rsi, [rel print_buf_end] + mov rcx, 0 + mov r10, 10 + cmp rbx, 0 + jne puts_digits + dec rsi + mov byte [rsi], '0' + inc rcx + jmp puts_sign +puts_digits: +puts_loop: + xor rdx, rdx + mov rax, rbx + div r10 + add dl, '0' + dec rsi + mov [rsi], dl + inc rcx + mov rbx, rax + test rbx, rbx + jne puts_loop +puts_sign: + cmp r8, 0 + je puts_finish_digits + dec rsi + mov byte [rsi], '-' + inc rcx +puts_finish_digits: + mov byte [rsi + rcx], 10 + inc rcx + mov rax, 1 + mov rdi, 1 + mov rdx, rcx + mov r9, rsi + mov rsi, r9 + syscall + ret +word_dup: + mov rax, [r12] + sub r12, 8 + mov [r12], rax + ret +word_drop: + add r12, 8 + ret +word_over: + mov rax, [r12 + 8] + sub r12, 8 + mov [r12], rax + ret +word_swap: + mov rax, [r12] + mov rbx, [r12 + 8] + mov [r12], rbx + mov [r12 + 8], rax + ret +word_rot: + mov rax, [r12] ; x3 + mov rbx, [r12 + 8] ; x2 + mov rcx, [r12 + 16] ; x1 + mov [r12], rcx ; top = x1 + mov [r12 + 8], rax ; next = x3 + mov [r12 + 16], rbx ; third = x2 + ret +word__2drot: + mov rax, [r12] ; x3 + mov rbx, [r12 + 8] ; x2 + mov rcx, [r12 + 16] ; x1 + mov [r12], rbx ; top = x2 + mov [r12 + 8], rcx ; next = x1 + mov [r12 + 16], rax ; third = x3 + ret +word_nip: + mov rax, [r12] + add r12, 8 ; drop lower element + mov [r12], rax ; keep original top + ret +word_tuck: + mov rax, [r12] ; x2 + mov rbx, [r12 + 8] ; x1 + sub r12, 8 ; make room + mov [r12], rax ; x2 + mov [r12 + 8], rbx ; x1 + mov [r12 + 16], rax ; x2 + ret +word_2dup: + mov rax, [r12] ; b + mov rbx, [r12 + 8] ; a + sub r12, 8 + mov [r12], rbx ; push a + sub r12, 8 + mov [r12], rax ; push b + ret +word_2drop: + add r12, 16 + ret +word_2swap: + mov rax, [r12] ; d + mov rbx, [r12 + 8] ; c + mov rcx, [r12 + 16] ; b + mov rdx, [r12 + 24] ; a + mov [r12], rcx ; top = b + mov [r12 + 8], rdx ; next = a + mov [r12 + 16], rax ; third = d + mov [r12 + 24], rbx ; fourth = c + ret +word_2over: + mov rax, [r12 + 16] ; b + mov rbx, [r12 + 24] ; a + sub r12, 8 + mov [r12], rbx ; push a + sub r12, 8 + mov [r12], rax ; push b + ret +word__2b: + mov rax, [r12] + add r12, 8 + add qword [r12], rax + ret +word__2d: + mov rax, [r12] + add r12, 8 + sub qword [r12], rax + ret +word__2a: + mov rax, [r12] + add r12, 8 + imul qword [r12] + mov [r12], rax + ret +word__2f: + mov rbx, [r12] + add r12, 8 + mov rax, [r12] + cqo + idiv rbx + mov [r12], rax + ret +word__25: + mov rbx, [r12] + add r12, 8 + mov rax, [r12] + cqo + idiv rbx + mov [r12], rdx + ret +word__3d_3d: + mov rax, [r12] + add r12, 8 + mov rbx, [r12] + cmp rbx, rax + mov rbx, 0 + sete bl + mov [r12], rbx + ret +word__21_3d: + mov rax, [r12] + add r12, 8 + mov rbx, [r12] + cmp rbx, rax + mov rbx, 0 + setne bl + mov [r12], rbx + ret +word__3c: + mov rax, [r12] + add r12, 8 + mov rbx, [r12] + cmp rbx, rax + mov rbx, 0 + setl bl + mov [r12], rbx + ret +word__3e: + mov rax, [r12] + add r12, 8 + mov rbx, [r12] + cmp rbx, rax + mov rbx, 0 + setg bl + mov [r12], rbx + ret +word__3c_3d: + mov rax, [r12] + add r12, 8 + mov rbx, [r12] + cmp rbx, rax + mov rbx, 0 + setle bl + mov [r12], rbx + ret +word__3e_3d: + mov rax, [r12] + add r12, 8 + mov rbx, [r12] + cmp rbx, rax + mov rbx, 0 + setge bl + mov [r12], rbx + ret +word__40: + mov rax, [r12] + mov rax, [rax] + mov [r12], rax + ret +word__21: + mov rax, [r12] + add r12, 8 + mov rbx, [r12] + mov [rax], rbx + add r12, 8 + ret +word_mmap: + mov r9, [r12] + add r12, 8 + mov r8, [r12] + add r12, 8 + mov r10, [r12] + add r12, 8 + mov rdx, [r12] + add r12, 8 + mov rsi, [r12] + add r12, 8 + mov rdi, [r12] + mov rax, 9 + syscall + mov [r12], rax + ret +word_munmap: + mov rsi, [r12] + add r12, 8 + mov rdi, [r12] + mov rax, 11 + syscall + mov [r12], rax + ret +word_exit: + mov rdi, [r12] + add r12, 8 + mov rax, 60 + syscall + ret +word_and: + mov rax, [r12] + add r12, 8 + mov rbx, [r12] + test rax, rax + setz cl + test rbx, rbx + setz dl + movzx rcx, cl + movzx rdx, dl + and rcx, rdx + mov [r12], rcx + ret +word_or: + mov rax, [r12] + add r12, 8 + mov rbx, [r12] + test rax, rax + setz cl + test rbx, rbx + setz dl + movzx rcx, cl + movzx rdx, dl + or rcx, rdx + mov [r12], rcx + ret +word_not: + mov rax, [r12] + test rax, rax + setz al + movzx rax, al + mov [r12], rax + ret +word__3er: + mov rax, [r12] + add r12, 8 + sub r13, 8 + mov [r13], rax + ret +word_r_3e: + mov rax, [r13] + add r13, 8 + sub r12, 8 + mov [r12], rax + ret +word_rdrop: + add r13, 8 + ret +word_pick: + mov rcx, [r12] + add r12, 8 + mov rax, [r12 + rcx * 8] + sub r12, 8 + mov [r12], rax + ret +word_rpick: + mov rcx, [r12] + add r12, 8 + mov rax, [r13 + rcx * 8] + sub r12, 8 + mov [r12], rax + ret +word_main: + ; push str_0 + sub r12, 8 + mov qword [r12], str_0 + ; push 11 + sub r12, 8 + mov qword [r12], 11 + call word_puts + ret +section .data +data_start: +str_0: db 104, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100, 0 +str_0_len equ 11 +data_end: +section .bss +align 16 +dstack: resb DSTK_BYTES +dstack_top: +align 16 +rstack: resb RSTK_BYTES +rstack_top: +align 16 +print_buf: resb PRINT_BUF_BYTES +print_buf_end: \ No newline at end of file diff --git a/build/hello.o b/build/hello.o new file mode 100644 index 0000000000000000000000000000000000000000..5ba708dc99541ab692756f927a73353d1c8a1961 GIT binary patch literal 4096 zcmbW4U1%It6oBvMr``PM#!^erKrODKkfiyo1fwR9$gJJGw1vJz#@+0u8M;4lb~b4- z#mW-sxaP?eELg<{AH)|ytFbCgvNcs}V-1B0rGlWeV10;!sU)zTbMKj*$!QY73p@AR z@BH0+?wy}~wLkoPna?Mj<`d5fcjQnZdR&p@9^n@i9{T@8%!R*g%)O^fff1IXj@fO8 zG5VJ?{t*SNWt@c*_krHOf&VP|pA<9^io^5o*uWP}9sj4u&*^w=8$hu>16kt2pk1w0 zJx=Et_~Bf!)vHbfq33Hy)m2*fQ5Kx%Zv5Zbaqjm9t#wJWe+sSqd2$}W;;CIgHM^iq-pKwMf_Yn2 z(zprmLdE^n(0OKKe;2Zs!}emJlBROUAF?Zg1*`**zMwypa}bsXixILLf*~7J%0;4l zI9M05YZVXKgTcCcl;{*j?>cs?0!sC)L2|J80Y; zoT+*%IPNQPIpI<$buQ6iw6T+va}NLf1k)G!hy>zHxGa6A*~^eDwJj--?{Y^03Lh)!lQRV+KIa>h)smnc0J zHjw*FqDIVI9y3LK#<_6c>qNR|I5OIWIN9ZJ>J*KzE z9N6m0?L&?M)lP38@@V6(+|g2US3)xBtS*^Nm1NutrH`a2VVcU3au%+)I~6iPRMw`u z-ciFThv|yRh>;TbNkF@gJKG}URZql86^E2DI33`xI^BXInu@4S5_JHg*GMYEi{G#rPWW&lsPeZ;}J( M3=QvhXU;hO7nz5`W&i*H literal 0 HcmV?d00001 diff --git a/build/loops_and_cmp.asm b/build/loops_and_cmp.asm index 02100b5..4127d7b 100644 --- a/build/loops_and_cmp.asm +++ b/build/loops_and_cmp.asm @@ -19,7 +19,7 @@ _start: mov rax, 60 syscall word_puts: - ; detects string if top is len>=0 and next is a pointer in [data_start, data_end) + ; detects string if top is len>=0 and next is a pointer in [data_start, data_end] mov rax, [r12] ; len or int value mov rbx, [r12 + 8] ; possible address cmp rax, 0 @@ -114,6 +114,64 @@ word_swap: mov [r12], rbx mov [r12 + 8], rax ret +word_rot: + mov rax, [r12] ; x3 + mov rbx, [r12 + 8] ; x2 + mov rcx, [r12 + 16] ; x1 + mov [r12], rcx ; top = x1 + mov [r12 + 8], rax ; next = x3 + mov [r12 + 16], rbx ; third = x2 + ret +word__2drot: + mov rax, [r12] ; x3 + mov rbx, [r12 + 8] ; x2 + mov rcx, [r12 + 16] ; x1 + mov [r12], rbx ; top = x2 + mov [r12 + 8], rcx ; next = x1 + mov [r12 + 16], rax ; third = x3 + ret +word_nip: + mov rax, [r12] + add r12, 8 ; drop lower element + mov [r12], rax ; keep original top + ret +word_tuck: + mov rax, [r12] ; x2 + mov rbx, [r12 + 8] ; x1 + sub r12, 8 ; make room + mov [r12], rax ; x2 + mov [r12 + 8], rbx ; x1 + mov [r12 + 16], rax ; x2 + ret +word_2dup: + mov rax, [r12] ; b + mov rbx, [r12 + 8] ; a + sub r12, 8 + mov [r12], rbx ; push a + sub r12, 8 + mov [r12], rax ; push b + ret +word_2drop: + add r12, 16 + ret +word_2swap: + mov rax, [r12] ; d + mov rbx, [r12 + 8] ; c + mov rcx, [r12 + 16] ; b + mov rdx, [r12 + 24] ; a + mov [r12], rcx ; top = b + mov [r12 + 8], rdx ; next = a + mov [r12 + 16], rax ; third = d + mov [r12 + 24], rbx ; fourth = c + ret +word_2over: + mov rax, [r12 + 16] ; b + mov rbx, [r12 + 24] ; a + sub r12, 8 + mov [r12], rbx ; push a + sub r12, 8 + mov [r12], rax ; push b + ret word__2b: mov rax, [r12] add r12, 8 @@ -242,6 +300,39 @@ word_exit: mov rax, 60 syscall ret +word_and: + mov rax, [r12] + add r12, 8 + mov rbx, [r12] + test rax, rax + setz cl + test rbx, rbx + setz dl + movzx rcx, cl + movzx rdx, dl + and rcx, rdx + mov [r12], rcx + ret +word_or: + mov rax, [r12] + add r12, 8 + mov rbx, [r12] + test rax, rax + setz cl + test rbx, rbx + setz dl + movzx rcx, cl + movzx rdx, dl + or rcx, rdx + mov [r12], rcx + ret +word_not: + mov rax, [r12] + test rax, rax + setz al + movzx rax, al + mov [r12], rax + ret word__3er: mov rax, [r12] add r12, 8 diff --git a/build/loops_and_cmp.o b/build/loops_and_cmp.o index 9fbed6fe4a773f8cf92f92823478979ad0689e86..e0f75f3c327b76d4333aafe9ec99f61f3f2f510f 100644 GIT binary patch literal 4208 zcmbW4YiJx*6oBuxo4RSM8?=^K0&VFEDrwB4p#*E2Kx$`ngV0t)C=8qIrd`a=Zf9rv zfYcV2K! z=)aipR#eP0SU7Pj*hJu}<$pv_Ary<}zkMEGG24k27=lPq#hW7;h#-sQv#A|92SO)s?{PFVLXwm2V5HGJs zX?g>M8_(wr~#nct6`12B1XB~Z<&Xd_n&-|JAfT`!H- z1HKTxZ7EEFYMc*s=UUvEjMh;pKSy*Y9IId-fb_;9deKGL9&Cp0G{tlWRLVu7Qask6 zJIfWA(Eqlp_w6){GY;P4H*c%> z3mmGg0%C0ydhxx$(S`+3wNtpem;6KK!QPL-$9)t~xERJ4nt~wXgYF(5d|fyi?BxOLgF5lK)yI3emmn^$lhlBG2)|)CyAe8JVX2o#t+uuMdE)j`!exG*r>pG zRmvf;n(^0(H#7bQ@ixZK65qo3MdI5Tzf3&K_*cZAX8bDg_)2zE))8OFxawC(v@+gF_C1VmCjL0%+lXfv-$C4A+#r5}@jb*R7~f0$ zYsL=|zrnae{7&|<^epkUjK4sQ?2Py8(7mxy0w{Bz>h8UL1e zJ-)L7<45AF82^*_YR3O2j$d!VQ7`)#5)U(e2k`@puOa?COk5y_9cc2DX~9mC5>Fc&I|kjOUp1*`-jqI%E+2S2Nlg(Y11~~Qp-d? zStrxG)2=6`r5NemrjiEJW;(yeATyaNS;(oJNek>H%I-^9O3Lp~5VNwjLPk3nl5D0) zYZnHdRO)sw9@>$*-H+4m2RGXLy^yYuaD_ov=p>;dX>=rA*yhU}1Fiw}&gd8jXj8tt zq1AI&LMG$xE>kc)8SjPC!!1)nmfB&u8#g-K4p|^7Bg@}!F739%^2JOdZHl-tn6(VN zHAX8fQgATZ1b#Env5+EAk%VIcfz)K!&`nDbHA$jQLVsaUc#?s>INT=$k1alObMyrv u|C@rf&(-tN3k(Nx^qs4!@d!c~obOZEi!)nQagH)RNBnKZhovV$nEnAIhXOnR delta 834 zcmeyM@IZRP0;ZG96Bn5=39wCc6r1=#1IU;x#b^hjq8RN&1K1eA-~|xk! zz%Ia)6we6dLaCcznvo#~P5cp5ycSLTHB@{un)nx}_)5mfiHsukj0{K76!3ugj0_La z#6_Xvf6>I{pyHBDV3Xm57F666P23DB9taW-fh%WVu!l;-qG|AeiWj1Z2SLSGqKU^% zUdSarc>xzk{Y5mHBB+i>XyP?c@y}@D?NIR_XyOy0;=IgA&IdB*K*g0I;x=&EWl)Jg zG!2`f;>Bp<`xzM~H!_McpMuhtfwUu|XyPrfdXQo;18)9P9O7@_;;26OjzgSrvLLU) Y!~l-Tj=ZNQ$MY?mEXBWg@&W!002Kaa-2eap diff --git a/build/main.asm b/build/main.asm index 031a9dd..e644000 100644 --- a/build/main.asm +++ b/build/main.asm @@ -19,7 +19,7 @@ _start: mov rax, 60 syscall word_puts: - ; detects string if top is len>=0 and next is a pointer in [data_start, data_end) + ; detects string if top is len>=0 and next is a pointer in [data_start, data_end] mov rax, [r12] ; len or int value mov rbx, [r12 + 8] ; possible address cmp rax, 0 @@ -114,6 +114,64 @@ word_swap: mov [r12], rbx mov [r12 + 8], rax ret +word_rot: + mov rax, [r12] ; x3 + mov rbx, [r12 + 8] ; x2 + mov rcx, [r12 + 16] ; x1 + mov [r12], rcx ; top = x1 + mov [r12 + 8], rax ; next = x3 + mov [r12 + 16], rbx ; third = x2 + ret +word__2drot: + mov rax, [r12] ; x3 + mov rbx, [r12 + 8] ; x2 + mov rcx, [r12 + 16] ; x1 + mov [r12], rbx ; top = x2 + mov [r12 + 8], rcx ; next = x1 + mov [r12 + 16], rax ; third = x3 + ret +word_nip: + mov rax, [r12] + add r12, 8 ; drop lower element + mov [r12], rax ; keep original top + ret +word_tuck: + mov rax, [r12] ; x2 + mov rbx, [r12 + 8] ; x1 + sub r12, 8 ; make room + mov [r12], rax ; x2 + mov [r12 + 8], rbx ; x1 + mov [r12 + 16], rax ; x2 + ret +word_2dup: + mov rax, [r12] ; b + mov rbx, [r12 + 8] ; a + sub r12, 8 + mov [r12], rbx ; push a + sub r12, 8 + mov [r12], rax ; push b + ret +word_2drop: + add r12, 16 + ret +word_2swap: + mov rax, [r12] ; d + mov rbx, [r12 + 8] ; c + mov rcx, [r12 + 16] ; b + mov rdx, [r12 + 24] ; a + mov [r12], rcx ; top = b + mov [r12 + 8], rdx ; next = a + mov [r12 + 16], rax ; third = d + mov [r12 + 24], rbx ; fourth = c + ret +word_2over: + mov rax, [r12 + 16] ; b + mov rbx, [r12 + 24] ; a + sub r12, 8 + mov [r12], rbx ; push a + sub r12, 8 + mov [r12], rax ; push b + ret word__2b: mov rax, [r12] add r12, 8 @@ -242,6 +300,39 @@ word_exit: mov rax, 60 syscall ret +word_and: + mov rax, [r12] + add r12, 8 + mov rbx, [r12] + test rax, rax + setz cl + test rbx, rbx + setz dl + movzx rcx, cl + movzx rdx, dl + and rcx, rdx + mov [r12], rcx + ret +word_or: + mov rax, [r12] + add r12, 8 + mov rbx, [r12] + test rax, rax + setz cl + test rbx, rbx + setz dl + movzx rcx, cl + movzx rdx, dl + or rcx, rdx + mov [r12], rcx + ret +word_not: + mov rax, [r12] + test rax, rax + setz al + movzx rax, al + mov [r12], rax + ret word__3er: mov rax, [r12] add r12, 8 diff --git a/build/main.o b/build/main.o index b86790271f7dd3c0b9f676178184207224cd51d1..5f778c49d4b602127f4595df524368d06457a26b 100644 GIT binary patch literal 4160 zcmbW4duUr#7{E`uwx-=QQRgh9xQ#_r=;D^HO0moqTDiAN|8esH4z5X)Zo%fk&CMRt z=^z$%i3O1k8P3Na3d4T{@liL_ZP6BWPMqR|srZMFz!aP!owO3a@0{=E-h68+c;Mdi zo!|F7-+kof$)V_dO+KG+hEHr0?#iJ;^t&R-{lYJrJ@o&Hm*g7f@cV8eTYe$NE(EW~j&2`mGBdH(3st!Ob~{}P?r zgi>WIgqxA9chU0erRI=c{Lru2b2C_fphc3>u8?0VUJ(;JqEm8*(J5JQw6{FbAMO40 z;60jsMzg;M*Pu3e-dZ(-$v?nTpk-Eiw7W=~>cNC3l)CKZEDy*^wBmv|*rv^29FRU_ z{x13qoM?wL8WdJ))pN70o3-lcOP$)5^P2sQKL5v|GXTyVUISFK%i83{!jC%CZM8|` zO@L>cuWN_NQ;q$JZeNbt=K?KM%CCOiZVr{P4?qS(e!b`*Y!5a=w>v|+4Jzd#Q7IY< z>h>zdb$eGRc$E^JqUb&7C?SVRR*OuzFo4%krjR-aQmY60&6AXNhB{OkJ1GE$>X17L zV(}fy-5UmzVQE4kki z;Y7@eiEuoh7vcP#yk%OkI7kQ5YNoZB9FHk`$GhQ-nVZGs>QV+P#>Z-YVBVvB3EC#MiLj{k6n5GQN@cX2w+?ePV#|9MXqhS-@!1%Modl)}PJk9uV;**TOLHr2gCyBquc$xT5jGrZb zh4HV6x3Q15ABeAI{1WkXjQ>R(zt-x8?4wT%Gu}@8dB$&)oHZW;-qL{ICOO*_*oSLe z7FH{%w*goG4=|22sM&9?+1K+2h%fa$A8hcxl|kc$)Og~~bS#w#$MR`mP zjpY86W$cZO7m{LM)=U_=f|VC|0!!1#B=?P{GD#zw89$(C&P-)20}i!}#mPF6+MRMd z$FtcS#YpYWC}}K}N#*w#WF}K33OSWCVS>Fx*}X|qN%?&-VrJG-$cTU;$(a;st-|PI zN*$@iLpxGO+&B?8xDkohLOMds5yl*$hlK8g(VcMM7FX^bbquI?M)#;kn{?%^n``b$ zNT;3Mr3;ywjMqZxV;M@ArFLYTjT_xghfENawdw9RmvY)+x*}eEWjU733j7qH+dzs* z$d!QG0vy$3SkOIF5j9Dou6(>OCTfy_zIDTSGVpfAM{SY55a{omyxSF5&&eQpqdodA e!q*Fq?G5-|563tQRTbwj z^?(Z^@{MuwBStf(2RxIdm@JrhnKy?pIWumKW@%=e?8uhHF7)sJ{}*rnOkTyNz;yc0 zRLg*^WQ2^S!7c(Ve#08@QDBg8luc>&B|WXM4izX=tuMH7Dn6`zbI{u(O2 z5>5O&RQxDJydKO25zJr#MuvxI8hD`Mf6>H6q2iKEa3jDBMX0zbnz$}hJP<|Pn}NX$ zDiMn!!N6b-6)!{+_k@bCL=z94JdsO$@&qo9`ip2XnNS^%(8P!9L4(8N2S z;=IhLUWSA{BZD$TTm>#W7pkEIO~W!qhRKbLqRbni^e!On$S9h05Ud`g7|ej1a|Va_ kWwV3H@&x`30KTDJ00000 diff --git a/build/override_dup_compile_time.asm b/build/override_dup_compile_time.asm index 98ad08c..a8380b5 100644 --- a/build/override_dup_compile_time.asm +++ b/build/override_dup_compile_time.asm @@ -19,7 +19,7 @@ _start: mov rax, 60 syscall word_puts: - ; detects string if top is len>=0 and next is a pointer in [data_start, data_end) + ; detects string if top is len>=0 and next is a pointer in [data_start, data_end] mov rax, [r12] ; len or int value mov rbx, [r12 + 8] ; possible address cmp rax, 0 @@ -114,6 +114,64 @@ word_swap: mov [r12], rbx mov [r12 + 8], rax ret +word_rot: + mov rax, [r12] ; x3 + mov rbx, [r12 + 8] ; x2 + mov rcx, [r12 + 16] ; x1 + mov [r12], rcx ; top = x1 + mov [r12 + 8], rax ; next = x3 + mov [r12 + 16], rbx ; third = x2 + ret +word__2drot: + mov rax, [r12] ; x3 + mov rbx, [r12 + 8] ; x2 + mov rcx, [r12 + 16] ; x1 + mov [r12], rbx ; top = x2 + mov [r12 + 8], rcx ; next = x1 + mov [r12 + 16], rax ; third = x3 + ret +word_nip: + mov rax, [r12] + add r12, 8 ; drop lower element + mov [r12], rax ; keep original top + ret +word_tuck: + mov rax, [r12] ; x2 + mov rbx, [r12 + 8] ; x1 + sub r12, 8 ; make room + mov [r12], rax ; x2 + mov [r12 + 8], rbx ; x1 + mov [r12 + 16], rax ; x2 + ret +word_2dup: + mov rax, [r12] ; b + mov rbx, [r12 + 8] ; a + sub r12, 8 + mov [r12], rbx ; push a + sub r12, 8 + mov [r12], rax ; push b + ret +word_2drop: + add r12, 16 + ret +word_2swap: + mov rax, [r12] ; d + mov rbx, [r12 + 8] ; c + mov rcx, [r12 + 16] ; b + mov rdx, [r12 + 24] ; a + mov [r12], rcx ; top = b + mov [r12 + 8], rdx ; next = a + mov [r12 + 16], rax ; third = d + mov [r12 + 24], rbx ; fourth = c + ret +word_2over: + mov rax, [r12 + 16] ; b + mov rbx, [r12 + 24] ; a + sub r12, 8 + mov [r12], rbx ; push a + sub r12, 8 + mov [r12], rax ; push b + ret word__2b: mov rax, [r12] add r12, 8 @@ -242,6 +300,39 @@ word_exit: mov rax, 60 syscall ret +word_and: + mov rax, [r12] + add r12, 8 + mov rbx, [r12] + test rax, rax + setz cl + test rbx, rbx + setz dl + movzx rcx, cl + movzx rdx, dl + and rcx, rdx + mov [r12], rcx + ret +word_or: + mov rax, [r12] + add r12, 8 + mov rbx, [r12] + test rax, rax + setz cl + test rbx, rbx + setz dl + movzx rcx, cl + movzx rdx, dl + or rcx, rdx + mov [r12], rcx + ret +word_not: + mov rax, [r12] + test rax, rax + setz al + movzx rax, al + mov [r12], rax + ret word__3er: mov rax, [r12] add r12, 8 diff --git a/build/override_dup_compile_time.o b/build/override_dup_compile_time.o index 2b38b61582802613fb04671eaac1c330628462f7..85ecd1a07f981191f7cf41383313a9a41b3be7a3 100644 GIT binary patch literal 4016 zcmbW4U1%It6oBuxN!_H;U8F5R1Esi%O1o{728|7xKq9ks^I{9W6o%RCq#e3{%+59~ zG+0;y9oC=^$wNS^FQN}VC|He^(zL5B^(Sf-TBr(wVxbCFkyJLYo^$V+pPVKU9N4|* ze&_d|duMj`#o_d`>mm{1T@mrL2xcA?VjvJn9uQH{5~BZ4#9a8u; zV2=Ll8Gn}tBs~i!?gbuQ!~dk9Ldc)zzkdZ^H1+a7L4MxAd)ozy6pXh=kY7ndP#b;2S}UhMd!0hT@P~B2W2H%wIL?jw8a~P(ud4H zLZ892?eL8Tm5o|+;nId(TJyrKE^YT!&Apyl{PW~R01KzK0M*>OHhH7+a|-Hq+NALg zz?WL?Ylk6Jjr&>3y`6R!Vy#rlZ_$+7lBi=JfD9#~sj7#tJ=lzt+m%SUpi(Xp)zXQ0 z%I#1*u8oh@+CFD@a{K%9G1B4A_3aNu2em&4{o}_jl(W%NfKmjmRr(8)K zi|Me>T>|t2Q?SxzwZ+D2bW*d2-OX!_W>abaz+BYvOI}IG zJm!dG)^H4w%#_O_Sw38LY{$rebUd#{n%id1Q1+hpsv|x+TEy+`=_7~fAk&$v$9W&8;7HyL+`UtoNK z_z#S`#Q$M@hWKXovT~aEHpbr~-plxV#Pf`wBR_Z72YE`D<15h^0_S7Pd&T} zPy1X7zP&ns7=Jl8$ezDP<6C2VrRQp~aX3{9< zg!#Y$@(wJ4S%7=9_lc}IUl{0IDy+l~NlFH)-F}vs}q<4cM$pwqF zPG$6nQg{3D(2msIL7eU&xZa)dLwbVY31gnnOF~ap@5y>_cOdtSdIr=xy=OF}H3NCi zF5g`V`MkHfe5K&axED%q6ewYl+EMTpuJ?EyvO!eVcCg-(<+Z~O#Jph@1pe&P?n}{x z6j?Y8V6O(*$96aWAK delta 777 zcmdlWzd>rk0wzc1iHppbCa_L)6r1=#1IU;x#b^hjq8RN&FR(Iz!3-7%%?6|lCa-1G z<}BcXh%ill$Y{>gz%yBj$%2WOd23E7&BMyy6+5TqyMvOfxd%pozbOir1ove}{@sW}KYJC{oYJuo6uH517x$a1>2k z0xJFxOsQ5}W z@vO;;T;h`zxH#%BqRG@jbv!~7?|_PbMiZY575{-IJ{Ky^%Z%hLAaey&Tp1$H1DD;z z$S}E)QIvTvls*Qe9T`RI&w@38RD&6C^*3;c--nB%y66=S@h?#E1_o61sz93r7#Jtl g^9W50;Fvs-=lbN`ybC9n@pW;--N3*w`5)gV0C>qv4gdfE diff --git a/build/string_puts.asm b/build/string_puts.asm index e868593..d9d9ed8 100644 --- a/build/string_puts.asm +++ b/build/string_puts.asm @@ -19,7 +19,7 @@ _start: mov rax, 60 syscall word_puts: - ; detects string if top is len>=0 and next is a pointer in [data_start, data_end) + ; detects string if top is len>=0 and next is a pointer in [data_start, data_end] mov rax, [r12] ; len or int value mov rbx, [r12 + 8] ; possible address cmp rax, 0 @@ -114,6 +114,64 @@ word_swap: mov [r12], rbx mov [r12 + 8], rax ret +word_rot: + mov rax, [r12] ; x3 + mov rbx, [r12 + 8] ; x2 + mov rcx, [r12 + 16] ; x1 + mov [r12], rcx ; top = x1 + mov [r12 + 8], rax ; next = x3 + mov [r12 + 16], rbx ; third = x2 + ret +word__2drot: + mov rax, [r12] ; x3 + mov rbx, [r12 + 8] ; x2 + mov rcx, [r12 + 16] ; x1 + mov [r12], rbx ; top = x2 + mov [r12 + 8], rcx ; next = x1 + mov [r12 + 16], rax ; third = x3 + ret +word_nip: + mov rax, [r12] + add r12, 8 ; drop lower element + mov [r12], rax ; keep original top + ret +word_tuck: + mov rax, [r12] ; x2 + mov rbx, [r12 + 8] ; x1 + sub r12, 8 ; make room + mov [r12], rax ; x2 + mov [r12 + 8], rbx ; x1 + mov [r12 + 16], rax ; x2 + ret +word_2dup: + mov rax, [r12] ; b + mov rbx, [r12 + 8] ; a + sub r12, 8 + mov [r12], rbx ; push a + sub r12, 8 + mov [r12], rax ; push b + ret +word_2drop: + add r12, 16 + ret +word_2swap: + mov rax, [r12] ; d + mov rbx, [r12 + 8] ; c + mov rcx, [r12 + 16] ; b + mov rdx, [r12 + 24] ; a + mov [r12], rcx ; top = b + mov [r12 + 8], rdx ; next = a + mov [r12 + 16], rax ; third = d + mov [r12 + 24], rbx ; fourth = c + ret +word_2over: + mov rax, [r12 + 16] ; b + mov rbx, [r12 + 24] ; a + sub r12, 8 + mov [r12], rbx ; push a + sub r12, 8 + mov [r12], rax ; push b + ret word__2b: mov rax, [r12] add r12, 8 @@ -242,6 +300,39 @@ word_exit: mov rax, 60 syscall ret +word_and: + mov rax, [r12] + add r12, 8 + mov rbx, [r12] + test rax, rax + setz cl + test rbx, rbx + setz dl + movzx rcx, cl + movzx rdx, dl + and rcx, rdx + mov [r12], rcx + ret +word_or: + mov rax, [r12] + add r12, 8 + mov rbx, [r12] + test rax, rax + setz cl + test rbx, rbx + setz dl + movzx rcx, cl + movzx rdx, dl + or rcx, rdx + mov [r12], rcx + ret +word_not: + mov rax, [r12] + test rax, rax + setz al + movzx rax, al + mov [r12], rax + ret word__3er: mov rax, [r12] add r12, 8 diff --git a/build/string_puts.o b/build/string_puts.o index a845dafff1818bcfa15293aee2c375cd61579f8c..4e953ac2727c6a9d49c4396d7cfc072ac5fdb5f5 100644 GIT binary patch literal 4368 zcmbW4Z)jUp6u@t`c1yd?MA>GQ;x>(-($zNEkYd$VT6xhFbes5P@<^7n3rk)~^3ra& z;UpCI$O;a+4+EVaMEo`p{L@Xut#KP}T5$@BV}4QDKnL6W&`AsNoO{pBdp&I`c;V%q z`#b;cJ@>u)US1!FJ-5Q=6T11t)50BTDnzdgj*zlU5-zHk)gH6Wl zl|Jc1=BLo7?{qW#qCs(uQJp!zs?(^R{j<&Jx@NJEZSO*~eA%C=_5tavw5p~)^Q3q7Y zMWS*n6pT78ibtJYq2MAVI>petUn?PpN>+g%~!)5Eiqu#-6J4{^y^aE3{GL9RwbM@#tPo#2N$mp(ojvE-5 ztYGcjEMDEQWpr;ZqkDH5-HBy%@3=anEZlvN>w`HvP%5|w2FtLiAPiDv2FvTH2D;x$ zIz9yj#A?V4OW1LK?l z?=uURRk{H;)qsFl10q^F=ef0E0936McJ~|iCab~zZ^1`D3MgD?zynP|ka3OIFU?h} z(rPK?$vR4ma{VY%R)pA-%4Bkz#&Y>gQe@Irs;e1)!)UHrhn?DIi;iU6j*E^&p&&X6 zdkS{mjwe9cpH)4L^QlZ+*=z5*JswRB;#PGjgO&1RU94HThL#+|IO^n#8+UUJne*(ePScy9}sV6{3GIB zjLWkE>ii7j=g59L<1@r_jQ>LX2;;vIKhF3K;-4@+OZ+>=)%tznN5)E667V*uDt9|l`ZH&K1_F2Y1BtFjgDdNW%pCQ{5tct)v}I0@jT;qOU{Z6j%{`LgOcB>;)(5T?PTBLg&>FP*!PgV{=U_2 z&yu|!>pn*I{5$_;$yqVMX;+QQg6J?}xDK~!TnaV&{dIVWIRD>pFL(x*I_DF`bSC*Y zykXMTusKq+3mx%7R+t4lp0}y%uySTWB3{~b5>@* zq9YK`HsMmkc%q<$WO_Jllbp%rMkq#l*izC^+DaGpm}DkXC5s~}XEG1=66Hoyc_kIb z;>7YfTOl(Hh9p~Q(%Qw{dzCs|i-&fk4!d!}Zg4Z4sD;!*Tnj^5*hWGmX-1M7cDZt7 zw>F^KnUUQdZOWCmcGldLkj?7VWs6o##=TJbxJ3zbR1Qlo+>Gc7)y delta 988 zcmbQB)F3-y0aH8k#6@OI7g#6WvSa$dI$4SlOhqx;i5jpmfPn@pga&cVCa-1G=1ky* zh^S0{$Y{IQg zRUDEag)erXNgf7?0>S2YY(`A=@r)22jJytJFf!zzi9djf*P@BPgo;l_6aNGiUx_CE z4=R2XB3=*Xf(S0K03*XgG!4Q~@xN%|GEi|zCb$t`h6YsJ6iwU&DjtX;?#;kp3zdjP zkzinOgNhfTi3dQ%SE7l>Om5^7pWML3QGXFlrU0tr5t?`vRQxlVcq>%=2by?4RGgO? z)yuP>;>r+l9=PlhMuy3ajH1lzA$0v#u)>f3p(zfoZa-L@i2LuVN zKp0n{=A#KS+=r+aVUR?Vc>#2oBcrI{d$0nK^T71Xg%xLxTzATjUV)Kof`gIu%VE<~sncd~5aq diff --git a/build/test.asm b/build/test.asm index 522ba94..e368921 100644 --- a/build/test.asm +++ b/build/test.asm @@ -19,7 +19,7 @@ _start: mov rax, 60 syscall word_puts: - ; detects string if top is len>=0 and next is a pointer in [data_start, data_end) + ; detects string if top is len>=0 and next is a pointer in [data_start, data_end] mov rax, [r12] ; len or int value mov rbx, [r12 + 8] ; possible address cmp rax, 0 @@ -114,6 +114,64 @@ word_swap: mov [r12], rbx mov [r12 + 8], rax ret +word_rot: + mov rax, [r12] ; x3 + mov rbx, [r12 + 8] ; x2 + mov rcx, [r12 + 16] ; x1 + mov [r12], rcx ; top = x1 + mov [r12 + 8], rax ; next = x3 + mov [r12 + 16], rbx ; third = x2 + ret +word__2drot: + mov rax, [r12] ; x3 + mov rbx, [r12 + 8] ; x2 + mov rcx, [r12 + 16] ; x1 + mov [r12], rbx ; top = x2 + mov [r12 + 8], rcx ; next = x1 + mov [r12 + 16], rax ; third = x3 + ret +word_nip: + mov rax, [r12] + add r12, 8 ; drop lower element + mov [r12], rax ; keep original top + ret +word_tuck: + mov rax, [r12] ; x2 + mov rbx, [r12 + 8] ; x1 + sub r12, 8 ; make room + mov [r12], rax ; x2 + mov [r12 + 8], rbx ; x1 + mov [r12 + 16], rax ; x2 + ret +word_2dup: + mov rax, [r12] ; b + mov rbx, [r12 + 8] ; a + sub r12, 8 + mov [r12], rbx ; push a + sub r12, 8 + mov [r12], rax ; push b + ret +word_2drop: + add r12, 16 + ret +word_2swap: + mov rax, [r12] ; d + mov rbx, [r12 + 8] ; c + mov rcx, [r12 + 16] ; b + mov rdx, [r12 + 24] ; a + mov [r12], rcx ; top = b + mov [r12 + 8], rdx ; next = a + mov [r12 + 16], rax ; third = d + mov [r12 + 24], rbx ; fourth = c + ret +word_2over: + mov rax, [r12 + 16] ; b + mov rbx, [r12 + 24] ; a + sub r12, 8 + mov [r12], rbx ; push a + sub r12, 8 + mov [r12], rax ; push b + ret word__2b: mov rax, [r12] add r12, 8 @@ -242,6 +300,39 @@ word_exit: mov rax, 60 syscall ret +word_and: + mov rax, [r12] + add r12, 8 + mov rbx, [r12] + test rax, rax + setz cl + test rbx, rbx + setz dl + movzx rcx, cl + movzx rdx, dl + and rcx, rdx + mov [r12], rcx + ret +word_or: + mov rax, [r12] + add r12, 8 + mov rbx, [r12] + test rax, rax + setz cl + test rbx, rbx + setz dl + movzx rcx, cl + movzx rdx, dl + or rcx, rdx + mov [r12], rcx + ret +word_not: + mov rax, [r12] + test rax, rax + setz al + movzx rax, al + mov [r12], rax + ret word__3er: mov rax, [r12] add r12, 8 diff --git a/build/test.o b/build/test.o index b4a5541657f9f05e68828bd3341d013da1177cc0..450ae02c165b3cd4b781d1d1ea021936d54917d4 100644 GIT binary patch literal 7472 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 literal 6784 zcmbW5dyG_99mmhGyY2E=zygIPSbVHat+4Eahig$6W#LXbo6wgHq3v~cXNFGMnOWzt zuoT$pN@TKGZQ5>{nm$a7ru7eM+9ri6|*f9KAb zAG`a9H<@#P=X1Wl-}#-#J#%LUJ0t6-g+j_)A@vnisTrzNN5y2jL)EKVi~fHm`oiZL z;odRL2hB688|GG5)wNWIe~sXMvjpI(%(#JgJ$)wge^_xM>@WMjZUSFOP5-Oe&)nqP zE~bX+9(?7`IsZN+M;GR26MeX<76H=LNFSLy_@@@2RBBWVSoXh^G(w{N4&R_}>ac%P zb##ZX>_0N{IVie{e~XMPgXO(6U8((=wO`5Chlgt$!$ZHScZy^C*ASgkr^)cWjrGpZ zMYZ$J$OuBK$Ou+KMcPX{J0k6G?z+_}9(9VR$aSu>=R|(iesq2a#hkih+G9oqIU_6K z{Hotvs`Ob}t21$iE~{PBo$-@vwGYb=z-R5N*kBM8W;*5L$F6C1%16#Fc3Mt2#dpKw z|9to;f#Z9xC+ZYS&YqKnzl168{B$i|M)+9m>=|^kvMK&1T>LOnJU*w6Q#n^3F4i`d zFb_o5HP(lR48rtaGQ!2hjo~6S1=)u~aN+3-f8MT)FD0!8FP0{x36m8E;(e`wu%^6la5`XiAkymk%p1-c)S$fP} zJTqOx^LY-;eFfLoH14OZh#lw8mBnY;e2v!g?yStk&0UH^be&!fV`K!@Huif;fOI&T^} z{2IAc(Q|NKk6>@WDp3)1Zx0xUxK|6^>C2V`Po{~7GtN7Ig(SbUB{&w1L`QiSk|%A+ zT~cxkl73rqx0D=!d>av|O^BzQ( zLul%Nm4X$feoaVp<-Gv9jM{^2@T7UO;qeU=3(3QqhcPw4x*k@IoxQ#MdP43cH*?xK zdk*L4nGQ3EJa(yEKKluSP6544DCi#Z>;1q=Q}4?9$zrxboMt`Xqiaob)-Fr{3wm`t=j-K6q3}6gR5vxhh@@6#s6-_O$ z9)DE@@^~1XliucB+P}~E>Axi;26Hmuj3B}Wv z!hRI=CR+~0LzcqMLmx2>P;8n?aV-?9EyY#6ypLH~U@7cgbRMUnxbRVBwDvis6$hbs z+frN=;}s}guoU)u=oq6=jF2LDOzc$kak-dwo%bLlUJuM~qj(m@K@=xZTtcxBi`<0b zb`;xCD4YUcKv6(ZMzIl3`oB;-f?`M0=F>1y*7bz8Lu!fOKVrUA@Sibn z5!}x^q`oTnYplOR@G<7D;J;_yEBGIo?-KkB^Tz}~%lvu4$CoT^@Vl8G5!|2Oka}D2Bo6NTg?yp}+Z5R9!>-PvgQ;#R4 zMg{*Q^PdRb#{5OWZ)1K)aDQDx>Mg-DtUoRIZssjG&8_SE%{U=nSb1f?ub{8B$rn{ry3UgKt3VTFLrm!PhZQ34RCj z-Gcl3CZq-h&$IrB;NM|BF8CwN>+!W|T~AHIpJP5-==U>UBlt1q_Y3|9<}tzl&iqlq zFEW2l@H)M&A+=BNMa&z_A3Hp@o0*2aLU$qA8(W@_=kiU_TuQmQd^DTqTT?pY#xg}{ldo!6n zj*;Aw_N_!RoyDAOO$`c`gRl$qPw?IX7}W{jvY62@4`MqA8n z3uG-7yRF9vc%W`ukJTEl*ejY%%og8BrA#WRLOQT9aY0BjZci0@tMsvCe^ot|sg75fU=9#$ zC$3j^kOBEjmZ#D58LXxO(VlFks@r5jMcibZYys&c8%-yn9#4P z^8TXb-EP^dtGY~NveZVUiwDVVYvvj{ZR0uSP9bWI?TAy-wnwY&!F!24=&3IB@b+NT zlj0}M)G1^l?WdHACesQ(cKG1XCMBX`bdb=#_HS;U9^kA`{F^5JSFc&hc)!IF|8m)nvsdsd%wG|FC;!H}i4&Fi F{0}=G&-wrW diff --git a/fn.sl b/fn.sl index 45b0c4b..6b736c0 100644 --- a/fn.sl +++ b/fn.sl @@ -100,27 +100,29 @@ compile-only compile-only : fn-lexemes-from-tokens - list-new >r # tokens (r: acc) - 0 # tokens idx + >r # (r: tokens) + list-new # acc begin - over list-length over swap >= if # stop when idx >= len - drop drop # drop idx and tokens (flag consumed by if) - r> exit # return acc + 0 rpick list-empty? if + rdrop exit then - over over list-get token-lexeme # tokens idx lex - r> swap list-append >r # tokens idx - 1 + # tokens idx+1 + 0 rpick list-pop-front # acc tokens' first + rdrop # acc tokens' + swap # acc first tokens' + >r # acc first (r: tokens') + token-lexeme # acc lex + list-append # acc' again ; compile-only : fn-validate-body dup list-length 0 == if "empty function body" parse-error then - dup >r 0 r> swap list-get "return" string= 0 == if "function body must start with 'return'" parse-error then + dup 0 list-get token-lexeme "return" string= 0 == if "function body must start with 'return'" parse-error then dup list-last ";" string= 0 == if "function body must terminate with ';'" parse-error then - list-clone # work on a copy - list-pop drop # drop trailing ';' - list-pop-front drop # drop leading 'return' + list-clone # body body' + list-pop drop # body expr' (trim trailing ';') + list-pop-front drop # body expr (trim leading 'return') dup list-length 0 == if "missing return expression" parse-error then ; compile-only diff --git a/main.py b/main.py index dd0d125..5e8da15 100644 --- a/main.py +++ b/main.py @@ -11,6 +11,8 @@ This file now contains working scaffolding for: from __future__ import annotations import argparse +import ctypes +import mmap import subprocess import sys import textwrap @@ -18,6 +20,13 @@ from dataclasses import dataclass, field from pathlib import Path from typing import Any, Callable, Dict, Iterable, List, Optional, Sequence, Set, Union, Tuple +try: # lazy optional import; required for compile-time :asm execution + from keystone import Ks, KsError, KS_ARCH_X86, KS_MODE_64 +except Exception: # pragma: no cover - optional dependency + Ks = None + KsError = Exception + KS_ARCH_X86 = KS_MODE_64 = None + class ParseError(Exception): """Raised when the source stream cannot be parsed.""" @@ -764,11 +773,13 @@ class CompileTimeVM: self.stack: List[Any] = [] self.return_stack: List[Any] = [] self.loop_stack: List[Dict[str, Any]] = [] + self._handles = _CTHandleTable() def reset(self) -> None: self.stack.clear() self.return_stack.clear() self.loop_stack.clear() + self._handles.clear() def push(self, value: Any) -> None: self.stack.append(value) @@ -778,6 +789,22 @@ class CompileTimeVM: raise ParseError("compile-time stack underflow") return self.stack.pop() + def _resolve_handle(self, value: Any) -> Any: + if isinstance(value, int): + for delta in (0, -1, 1): + candidate = value + delta + if candidate in self._handles.objects: + obj = self._handles.objects[candidate] + self._handles.objects[value] = obj + return obj + # Occasionally a raw object id can appear on the stack; recover it if we still + # hold the object reference. + for obj in self._handles.objects.values(): + if id(obj) == value: + self._handles.objects[value] = obj + return obj + return value + def peek(self) -> Any: if not self.stack: raise ParseError("compile-time stack underflow") @@ -790,19 +817,24 @@ class CompileTimeVM: return value def pop_str(self) -> str: - value = self.pop() + value = self._resolve_handle(self.pop()) if not isinstance(value, str): raise ParseError("expected string on compile-time stack") return value def pop_list(self) -> List[Any]: - value = self.pop() + value = self._resolve_handle(self.pop()) if not isinstance(value, list): - raise ParseError("expected list on compile-time stack") + known = value in self._handles.objects if isinstance(value, int) else False + handles_size = len(self._handles.objects) + handle_keys = list(self._handles.objects.keys()) + raise ParseError( + f"expected list on compile-time stack, got {type(value).__name__} value={value!r} known_handle={known} handles={handles_size}:{handle_keys!r} stack={self.stack!r}" + ) return value def pop_token(self) -> Token: - value = self.pop() + value = self._resolve_handle(self.pop()) if not isinstance(value, Token): raise ParseError("expected token on compile-time stack") return value @@ -826,9 +858,210 @@ class CompileTimeVM: if definition is None: raise ParseError(f"word '{word.name}' has no compile-time definition") if isinstance(definition, AsmDefinition): - raise ParseError(f"word '{word.name}' cannot run at compile time") + self._run_asm_definition(word) + return self._execute_nodes(definition.body) + def _run_asm_definition(self, word: Word) -> None: + definition = word.definition + if Ks is None: + raise ParseError("keystone is required for compile-time :asm execution; install keystone-engine") + if not isinstance(definition, AsmDefinition): # pragma: no cover - defensive + raise ParseError(f"word '{word.name}' has no asm body") + asm_body = definition.body.strip("\n") + + string_mode = word.name == "puts" + + handles = self._handles + + non_int_data = any(not isinstance(v, int) for v in self.stack) + non_int_return = any(not isinstance(v, int) for v in self.return_stack) + + # Collect all strings present on data and return stacks so we can point + # puts() at a real buffer and pass its range check (data_start..data_end). + strings: List[str] = [] + if string_mode: + for v in self.stack + self.return_stack: + if isinstance(v, str): + strings.append(v) + data_blob = b"" + string_addrs: Dict[str, Tuple[int, int]] = {} + if strings: + offset = 0 + parts: List[bytes] = [] + seen: Dict[str, Tuple[int, int]] = {} + for s in strings: + if s in seen: + string_addrs[s] = seen[s] + continue + encoded = s.encode("utf-8") + b"\x00" + parts.append(encoded) + addr = offset + length = len(encoded) - 1 + seen[s] = (addr, length) + string_addrs[s] = (addr, length) + offset += len(encoded) + data_blob = b"".join(parts) + string_buffer: Optional[ctypes.Array[Any]] = None + data_start = 0 + data_end = 0 + if data_blob: + string_buffer = ctypes.create_string_buffer(data_blob) + data_start = ctypes.addressof(string_buffer) + data_end = data_start + len(data_blob) + handles.refs.append(string_buffer) + for s, (off, _len) in string_addrs.items(): + handles.objects[data_start + off] = s + + PRINT_BUF_BYTES = 128 + print_buffer = ctypes.create_string_buffer(PRINT_BUF_BYTES) + handles.refs.append(print_buffer) + print_buf = ctypes.addressof(print_buffer) + + wrapper_lines = [] + wrapper_lines.extend([ + "_ct_entry:", + " push rbx", + " push r12", + " push r13", + " push r14", + " push r15", + " mov r12, rdi", # data stack pointer + " mov r13, rsi", # return stack pointer + " mov r14, rdx", # out ptr for r12 + " mov r15, rcx", # out ptr for r13 + ]) + if asm_body: + patched_body = [] + for line in asm_body.splitlines(): + line = line.strip() + if line == "ret": + line = "jmp _ct_save" + if "lea r8, [rel data_start]" in line: + line = line.replace("lea r8, [rel data_start]", f"mov r8, {data_start}") + if "lea r9, [rel data_end]" in line: + line = line.replace("lea r9, [rel data_end]", f"mov r9, {data_end}") + if "mov byte [rel print_buf]" in line or "mov byte ptr [rel print_buf]" in line: + patched_body.append(f"mov rax, {print_buf}") + patched_body.append("mov byte ptr [rax], 10") + continue + if "lea rsi, [rel print_buf_end]" in line: + line = f"mov rsi, {print_buf + PRINT_BUF_BYTES}" + if "lea rsi, [rel print_buf]" in line: + line = f"mov rsi, {print_buf}" + patched_body.append(line) + wrapper_lines.extend(patched_body) + wrapper_lines.extend([ + "_ct_save:", + " mov [r14], r12", + " mov [r15], r13", + " pop r15", + " pop r14", + " pop r13", + " pop r12", + " pop rbx", + " ret", + ]) + def _normalize_sizes(line: str) -> str: + for size in ("qword", "dword", "word", "byte"): + line = line.replace(f"{size} [", f"{size} ptr [") + return line + + def _strip_comment(line: str) -> str: + return line.split(";", 1)[0].rstrip() + + normalized_lines = [] + for raw in wrapper_lines: + stripped = _strip_comment(raw) + if not stripped.strip(): + continue + normalized_lines.append(_normalize_sizes(stripped)) + ks = Ks(KS_ARCH_X86, KS_MODE_64) + try: + encoding, _ = ks.asm("\n".join(normalized_lines)) + except KsError as exc: + debug_lines = "\n".join(normalized_lines) + raise ParseError( + f"keystone failed for word '{word.name}': {exc}\n--- asm ---\n{debug_lines}\n--- end asm ---" + ) from exc + if encoding is None: + raise ParseError( + f"keystone produced no code for word '{word.name}' (lines: {len(wrapper_lines)})" + ) + + code = bytes(encoding) + code_buf = mmap.mmap(-1, len(code), prot=mmap.PROT_READ | mmap.PROT_WRITE | mmap.PROT_EXEC) + code_buf.write(code) + code_ptr = ctypes.addressof(ctypes.c_char.from_buffer(code_buf)) + func_type = ctypes.CFUNCTYPE(None, ctypes.c_uint64, ctypes.c_uint64, ctypes.c_uint64, ctypes.c_uint64) + func = func_type(code_ptr) + + handles = self._handles + + def _marshal_stack(py_stack: List[Any]) -> Tuple[int, int, int, Any]: + capacity = len(py_stack) + 16 + buffer = (ctypes.c_int64 * capacity)() + base = ctypes.addressof(buffer) + top = base + capacity * 8 + sp = top + for value in py_stack: + sp -= 8 + if isinstance(value, int): + ctypes.c_int64.from_address(sp).value = value + elif isinstance(value, str): + if string_mode: + offset, strlen = string_addrs.get(value, (0, 0)) + addr = data_start + offset if data_start else handles.store(value) + # puts expects (len, addr) with len on top + ctypes.c_int64.from_address(sp).value = addr + sp -= 8 + ctypes.c_int64.from_address(sp).value = strlen + else: + ctypes.c_int64.from_address(sp).value = handles.store(value) + else: + ctypes.c_int64.from_address(sp).value = handles.store(value) + return sp, top, base, buffer + + # r12/r13 must point at the top element (or top of buffer if empty) + buffers: List[Any] = [] + d_sp, d_top, d_base, d_buf = _marshal_stack(self.stack) + buffers.append(d_buf) + r_sp, r_top, r_base, r_buf = _marshal_stack(self.return_stack) + buffers.append(r_buf) + out_d = ctypes.c_uint64(0) + out_r = ctypes.c_uint64(0) + func(d_sp, r_sp, ctypes.addressof(out_d), ctypes.addressof(out_r)) + + new_d = out_d.value + new_r = out_r.value + if not (d_base <= new_d <= d_top): + raise ParseError(f"compile-time asm '{word.name}' corrupted data stack pointer") + if not (r_base <= new_r <= r_top): + raise ParseError(f"compile-time asm '{word.name}' corrupted return stack pointer") + + def _unmarshal_stack(sp: int, top: int, table: _CTHandleTable) -> List[Any]: + if sp == top: + return [] + values: List[Any] = [] + addr = top - 8 + while addr >= sp: + raw = ctypes.c_int64.from_address(addr).value + if raw in table.objects: + obj = table.objects[raw] + if isinstance(obj, str) and values and isinstance(values[-1], int): + # collapse (len, addr) pairs back into the original string + values.pop() + values.append(obj) + else: + values.append(obj) + else: + values.append(raw) + addr -= 8 + return values + + self.stack = _unmarshal_stack(new_d, d_top, handles) + self.return_stack = _unmarshal_stack(new_r, r_top, handles) + def _call_word_by_name(self, name: str) -> None: word = self.dictionary.lookup(name) if word is None: @@ -1085,6 +1318,27 @@ def _parse_string_literal(token: Token) -> Optional[str]: return "".join(result) +class _CTHandleTable: + """Keeps Python object references stable across compile-time asm calls.""" + + def __init__(self) -> None: + self.objects: Dict[int, Any] = {} + self.refs: List[Any] = [] + self.string_buffers: List[ctypes.Array[Any]] = [] + + def clear(self) -> None: + self.objects.clear() + self.refs.clear() + self.string_buffers.clear() + + def store(self, value: Any) -> int: + addr = id(value) + self.refs.append(value) + self.objects[addr] = value + return addr + + + class Assembler: def __init__(self, dictionary: Dictionary) -> None: self.dictionary = dictionary @@ -1298,6 +1552,24 @@ def macro_compile_only(ctx: MacroContext) -> Optional[List[ASTNode]]: return None +def macro_compile_time(ctx: MacroContext) -> Optional[List[ASTNode]]: + """Run the next word at compile time and still emit it for runtime.""" + parser = ctx.parser + if parser._eof(): + raise ParseError("word name missing after 'compile-time'") + tok = parser.next_token() + name = tok.lexeme + word = parser.dictionary.lookup(name) + if word is None: + raise ParseError(f"unknown word '{name}' for compile-time") + if word.compile_only: + raise ParseError(f"word '{name}' is compile-time only") + parser.compile_time_vm.invoke(word) + if isinstance(parser.context_stack[-1], Definition): + parser.emit_node(WordRef(name=name)) + return None + + def macro_begin_text_macro(ctx: MacroContext) -> Optional[List[ASTNode]]: parser = ctx.parser if parser._eof(): @@ -1447,14 +1719,6 @@ def _ensure_lexer(value: Any) -> SplitLexer: return value -def _truthy(value: Any) -> bool: - if isinstance(value, bool): - return value - if isinstance(value, int): - return value != 0 - return value is not None - - def _coerce_str(value: Any) -> str: if isinstance(value, str): return value @@ -1473,217 +1737,21 @@ def _default_template(template: Optional[Token]) -> Token: return template -def _trunc_divmod(a: int, b: int) -> Tuple[int, int]: - if b == 0: - raise ParseError("division by zero") - quot = abs(a) // abs(b) - if (a < 0) ^ (b < 0): - quot = -quot - rem = a - quot * b - return quot, rem - - -def _ct_dup(vm: CompileTimeVM) -> None: - vm.push(vm.peek()) - - -def _ct_drop(vm: CompileTimeVM) -> None: - vm.pop() - - -def _ct_swap(vm: CompileTimeVM) -> None: - a = vm.pop() - b = vm.pop() - vm.push(a) - vm.push(b) - - -def _ct_over(vm: CompileTimeVM) -> None: - if len(vm.stack) < 2: - raise ParseError("over requires two stack values") - vm.push(vm.stack[-2]) - - -def _ct_rot(vm: CompileTimeVM) -> None: - if len(vm.stack) < 3: - raise ParseError("rot requires three stack values") - vm.stack[-3], vm.stack[-2], vm.stack[-1] = vm.stack[-2], vm.stack[-1], vm.stack[-3] - - -def _ct_nip(vm: CompileTimeVM) -> None: - if len(vm.stack) < 2: - raise ParseError("nip requires two stack values") - top = vm.pop() - vm.pop() - vm.push(top) - - -def _ct_tuck(vm: CompileTimeVM) -> None: - if len(vm.stack) < 2: - raise ParseError("tuck requires two stack values") - first = vm.pop() - second = vm.pop() - vm.push(first) - vm.push(second) - vm.push(first) - - -def _ct_2dup(vm: CompileTimeVM) -> None: - if len(vm.stack) < 2: - raise ParseError("2dup requires two stack values") - second = vm.pop() - first = vm.pop() - vm.push(first) - vm.push(second) - vm.push(first) - vm.push(second) - - -def _ct_2drop(vm: CompileTimeVM) -> None: - if len(vm.stack) < 2: - raise ParseError("2drop requires two stack values") - vm.pop() - vm.pop() - - -def _ct_2swap(vm: CompileTimeVM) -> None: - if len(vm.stack) < 4: - raise ParseError("2swap requires four stack values") - a = vm.pop() - b = vm.pop() - c = vm.pop() - d = vm.pop() - vm.push(a) - vm.push(b) - vm.push(c) - vm.push(d) - - -def _ct_2over(vm: CompileTimeVM) -> None: - if len(vm.stack) < 4: - raise ParseError("2over requires four stack values") - vm.push(vm.stack[-4]) - vm.push(vm.stack[-3]) - - -def _ct_minus_rot(vm: CompileTimeVM) -> None: - if len(vm.stack) < 3: - raise ParseError("-rot requires three stack values") - vm.stack[-3], vm.stack[-2], vm.stack[-1] = vm.stack[-1], vm.stack[-3], vm.stack[-2] - - -def _ct_binary_int(vm: CompileTimeVM, func: Callable[[int, int], int]) -> None: - b = vm.pop_int() - a = vm.pop_int() - vm.push(func(a, b)) - - -def _ct_add(vm: CompileTimeVM) -> None: - _ct_binary_int(vm, lambda a, b: a + b) - - -def _ct_sub(vm: CompileTimeVM) -> None: - _ct_binary_int(vm, lambda a, b: a - b) - - -def _ct_mul(vm: CompileTimeVM) -> None: - _ct_binary_int(vm, lambda a, b: a * b) - - -def _ct_div(vm: CompileTimeVM) -> None: - divisor = vm.pop_int() - dividend = vm.pop_int() - quot, _ = _trunc_divmod(dividend, divisor) - vm.push(quot) - - -def _ct_mod(vm: CompileTimeVM) -> None: - divisor = vm.pop_int() - dividend = vm.pop_int() - _, rem = _trunc_divmod(dividend, divisor) - vm.push(rem) - - -def _ct_compare(vm: CompileTimeVM, predicate: Callable[[Any, Any], bool]) -> None: - b = vm.pop() - a = vm.pop() - vm.push(1 if predicate(a, b) else 0) - - -def _ct_eq(vm: CompileTimeVM) -> None: - _ct_compare(vm, lambda a, b: a == b) - - -def _ct_ne(vm: CompileTimeVM) -> None: - _ct_compare(vm, lambda a, b: a != b) - - -def _ct_lt(vm: CompileTimeVM) -> None: - _ct_compare(vm, lambda a, b: a < b) - - -def _ct_le(vm: CompileTimeVM) -> None: - _ct_compare(vm, lambda a, b: a <= b) - - -def _ct_gt(vm: CompileTimeVM) -> None: - _ct_compare(vm, lambda a, b: a > b) - - -def _ct_ge(vm: CompileTimeVM) -> None: - _ct_compare(vm, lambda a, b: a >= b) - - -def _ct_and(vm: CompileTimeVM) -> None: - b = _truthy(vm.pop()) - a = _truthy(vm.pop()) - vm.push(1 if (a and b) else 0) - - -def _ct_or(vm: CompileTimeVM) -> None: - b = _truthy(vm.pop()) - a = _truthy(vm.pop()) - vm.push(1 if (a or b) else 0) - - -def _ct_not(vm: CompileTimeVM) -> None: - vm.push(1 if not _truthy(vm.pop()) else 0) - - -def _ct_to_r(vm: CompileTimeVM) -> None: - vm.return_stack.append(vm.pop()) - - -def _ct_r_from(vm: CompileTimeVM) -> None: - if not vm.return_stack: - raise ParseError("return stack underflow") - vm.push(vm.return_stack.pop()) - - -def _ct_rdrop(vm: CompileTimeVM) -> None: - if not vm.return_stack: - raise ParseError("return stack underflow") - vm.return_stack.pop() - - -def _ct_rpick(vm: CompileTimeVM) -> None: - index = vm.pop_int() - if index < 0 or index >= len(vm.return_stack): - raise ParseError("rpick index out of range") - vm.push(vm.return_stack[-1 - index]) - - -def _ct_pick(vm: CompileTimeVM) -> None: - index = vm.pop_int() - if index < 0 or index >= len(vm.stack): - raise ParseError("pick index out of range") - vm.push(vm.stack[-1 - index]) - - def _ct_nil(vm: CompileTimeVM) -> None: vm.push(None) +def _ct_puts(vm: CompileTimeVM) -> None: + value = vm.pop() + if isinstance(value, str): + print(value) + return + if isinstance(value, int): + print(value) + return + raise ParseError("puts expects string or integer at compile time") + + def _ct_nil_p(vm: CompileTimeVM) -> None: vm.push(1 if vm.pop() is None else 0) @@ -1704,6 +1772,12 @@ def _ct_list_append(vm: CompileTimeVM) -> None: vm.push(lst) +def _ct_drop(vm: CompileTimeVM) -> None: + if not vm.stack: + return + vm.pop() + + def _ct_list_pop(vm: CompileTimeVM) -> None: lst = _ensure_list(vm.pop()) if not lst: @@ -1723,7 +1797,7 @@ def _ct_list_pop_front(vm: CompileTimeVM) -> None: def _ct_list_length(vm: CompileTimeVM) -> None: - lst = _ensure_list(vm.pop()) + lst = vm.pop_list() vm.push(len(lst)) @@ -1955,13 +2029,24 @@ def _ct_int_to_string(vm: CompileTimeVM) -> None: def _ct_identifier_p(vm: CompileTimeVM) -> None: - value = vm.pop_str() + value = vm._resolve_handle(vm.pop()) + if isinstance(value, Token): + value = value.lexeme + if not isinstance(value, str): + vm.push(0) + return vm.push(1 if _is_identifier(value) else 0) def _ct_token_lexeme(vm: CompileTimeVM) -> None: - token = vm.pop_token() - vm.push(token.lexeme) + value = vm._resolve_handle(vm.pop()) + if isinstance(value, Token): + vm.push(value.lexeme) + return + if isinstance(value, str): + vm.push(value) + return + raise ParseError("expected token or string on compile-time stack") def _ct_token_from_lexeme(vm: CompileTimeVM) -> None: @@ -2068,43 +2153,12 @@ def _register_compile_time_primitives(dictionary: Dictionary) -> None: if compile_only: word.compile_only = True - register("dup", _ct_dup) - register("drop", _ct_drop) - register("swap", _ct_swap) - register("over", _ct_over) - register("rot", _ct_rot) - register("nip", _ct_nip) - register("tuck", _ct_tuck) - register("2dup", _ct_2dup) - register("2drop", _ct_2drop) - register("2swap", _ct_2swap) - register("2over", _ct_2over) - register("-rot", _ct_minus_rot) - register("+", _ct_add) - register("-", _ct_sub) - register("*", _ct_mul) - register("/", _ct_div) - register("%", _ct_mod) - register("==", _ct_eq) - register("!=", _ct_ne) - register("<", _ct_lt) - register("<=", _ct_le) - register(">", _ct_gt) - register(">=", _ct_ge) - register("and", _ct_and) - register("or", _ct_or) - register("not", _ct_not) - register(">r", _ct_to_r) - register("r>", _ct_r_from) - register("rdrop", _ct_rdrop) - register("rpick", _ct_rpick) - register("pick", _ct_pick) - register("nil", _ct_nil, compile_only=True) register("nil?", _ct_nil_p, compile_only=True) register("list-new", _ct_list_new, compile_only=True) register("list-clone", _ct_list_clone, compile_only=True) register("list-append", _ct_list_append, compile_only=True) + register("drop", _ct_drop) register("list-pop", _ct_list_pop, compile_only=True) register("list-pop-front", _ct_list_pop_front, compile_only=True) register("list-length", _ct_list_length, compile_only=True) @@ -2239,6 +2293,7 @@ def bootstrap_dictionary() -> Dictionary: dictionary = Dictionary() dictionary.register(Word(name="immediate", immediate=True, macro=macro_immediate)) dictionary.register(Word(name="compile-only", immediate=True, macro=macro_compile_only)) + dictionary.register(Word(name="compile-time", immediate=True, macro=macro_compile_time)) dictionary.register(Word(name="macro:", immediate=True, macro=macro_begin_text_macro)) dictionary.register(Word(name=";macro", immediate=True, macro=macro_end_text_macro)) dictionary.register(Word(name="struct:", immediate=True, macro=macro_struct_begin)) diff --git a/stdlib.sl b/stdlib.sl index 25a96b6..a25fa30 100644 --- a/stdlib.sl +++ b/stdlib.sl @@ -1,5 +1,5 @@ :asm puts { - ; detects string if top is len>=0 and next is a pointer in [data_start, data_end) + ; detects string if top is len>=0 and next is a pointer in [data_start, data_end] mov rax, [r12] ; len or int value mov rbx, [r12 + 8] ; possible address cmp rax, 0 @@ -104,6 +104,80 @@ puts_finish_digits: } ; +:asm rot { + mov rax, [r12] ; x3 + mov rbx, [r12 + 8] ; x2 + mov rcx, [r12 + 16] ; x1 + mov [r12], rcx ; top = x1 + mov [r12 + 8], rax ; next = x3 + mov [r12 + 16], rbx ; third = x2 +} +; + +:asm -rot { + mov rax, [r12] ; x3 + mov rbx, [r12 + 8] ; x2 + mov rcx, [r12 + 16] ; x1 + mov [r12], rbx ; top = x2 + mov [r12 + 8], rcx ; next = x1 + mov [r12 + 16], rax ; third = x3 +} +; + +:asm nip { + mov rax, [r12] + add r12, 8 ; drop lower element + mov [r12], rax ; keep original top +} +; + +:asm tuck { + mov rax, [r12] ; x2 + mov rbx, [r12 + 8] ; x1 + sub r12, 8 ; make room + mov [r12], rax ; x2 + mov [r12 + 8], rbx ; x1 + mov [r12 + 16], rax ; x2 +} +; + +:asm 2dup { + mov rax, [r12] ; b + mov rbx, [r12 + 8] ; a + sub r12, 8 + mov [r12], rbx ; push a + sub r12, 8 + mov [r12], rax ; push b +} +; + +:asm 2drop { + add r12, 16 +} +; + +:asm 2swap { + mov rax, [r12] ; d + mov rbx, [r12 + 8] ; c + mov rcx, [r12 + 16] ; b + mov rdx, [r12 + 24] ; a + mov [r12], rcx ; top = b + mov [r12 + 8], rdx ; next = a + mov [r12 + 16], rax ; third = d + mov [r12 + 24], rbx ; fourth = c +} +; + +:asm 2over { + mov rax, [r12 + 16] ; b + mov rbx, [r12 + 24] ; a + sub r12, 8 + mov [r12], rbx ; push a + sub r12, 8 + mov [r12], rax ; push b +} +; + :asm + { mov rax, [r12] add r12, 8 @@ -264,6 +338,45 @@ puts_finish_digits: } ; +:asm and { + mov rax, [r12] + add r12, 8 + mov rbx, [r12] + test rax, rax + setz cl + test rbx, rbx + setz dl + movzx rcx, cl + movzx rdx, dl + and rcx, rdx + mov [r12], rcx +} +; + +:asm or { + mov rax, [r12] + add r12, 8 + mov rbx, [r12] + test rax, rax + setz cl + test rbx, rbx + setz dl + movzx rcx, cl + movzx rdx, dl + or rcx, rdx + mov [r12], rcx +} +; + +:asm not { + mov rax, [r12] + test rax, rax + setz al + movzx rax, al + mov [r12], rax +} +; + :asm >r { mov rax, [r12] add r12, 8 diff --git a/tests/__pycache__/run_tests.cpython-314.pyc b/tests/__pycache__/run_tests.cpython-314.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b51fee4164b2e03b65a19f51a06a7fd31590b66b GIT binary patch literal 5770 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