From 96366a98a897f502fedad6181cf855ea69878879 Mon Sep 17 00:00:00 2001 From: IgorCielniak Date: Thu, 11 Dec 2025 20:25:34 +0100 Subject: [PATCH] added run time strings --- a.out | Bin 6928 -> 10376 bytes a.sl | 2 +- build/a.asm | 284 ++++++++++++++++++++++++++ build/a.o | Bin 0 -> 3296 bytes build/call_syntax_parens.asm | 19 ++ build/call_syntax_parens.o | Bin 3056 -> 3248 bytes build/loops_and_cmp.asm | 19 ++ build/loops_and_cmp.o | Bin 3120 -> 3312 bytes build/override_dup_compile_time.asm | 19 ++ build/override_dup_compile_time.o | Bin 2912 -> 3120 bytes build/string_puts.asm | 305 ++++++++++++++++++++++++++++ build/string_puts.o | Bin 0 -> 3552 bytes hello.sl | 5 + main.py | 38 +++- stdlib.sl | 21 ++ tests/run_tests.py | 14 ++ 16 files changed, 722 insertions(+), 4 deletions(-) create mode 100644 build/a.asm create mode 100644 build/a.o create mode 100644 build/string_puts.asm create mode 100644 build/string_puts.o create mode 100644 hello.sl diff --git a/a.out b/a.out index 9a54c1f663bd689403674acbda0efa18814cd1ca..8bc6f17c21736d7ab0c10456f430ca531187afa3 100755 GIT binary patch literal 10376 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 P2YDYRhW90!14#b`mvs=j literal 0 HcmV?d00001 diff --git a/build/call_syntax_parens.asm b/build/call_syntax_parens.asm index 0bd0700..7df47c7 100644 --- a/build/call_syntax_parens.asm +++ b/build/call_syntax_parens.asm @@ -65,6 +65,25 @@ puts_finish_digits: mov rsi, r9 syscall ret +word_puts_str: + ; expects (addr, len) on data stack + mov rdx, [r12] + add r12, 8 + mov rsi, [r12] + add r12, 8 + cmp rdx, 0 + je puts_str_write_newline + mov rax, 1 + mov rdi, 1 + syscall +puts_str_write_newline: + mov byte [rel print_buf], 10 + mov rax, 1 + mov rdi, 1 + lea rsi, [rel print_buf] + mov rdx, 1 + syscall + ret word_dup: mov rax, [r12] sub r12, 8 diff --git a/build/call_syntax_parens.o b/build/call_syntax_parens.o index 2cb5c54fb25511d1241f9520bd57daa892c9232d..4f2a189ad61abe3ddf49694765297ba3e8e3594e 100644 GIT binary patch delta 959 zcmZ9}JxD@P6ae6RpFT=6LQ2FIk!lJmqc8}up+Uh2A!rJR5E4>C4ckPVq#uk6L7NUv zMHDuO1yO`kK@for{n*kFg3x3M_U`qRcJ6TQIp4W|k5@Gwn^I|-+RfOM@aUi^W}*(m zolL}7Q8#B^j<5h7*34*|Qe_!x(~Rkw)dnk5E3L3z>CoOc=t^97x;7`o>`Z)-h%Qf+ zbr(GJ$VG9swnfhENq$O!w{rz)NTS{BRc(P#iOa~|1CJv)2_q2xu(t&kNdC5;w| z>6yl8%~f% z!LN|V!S9i8ftQf)fmal_w|{d68Y)%05^?~(fc%tMG)8*HJW4Ezc+28SUJ~(*?Q71> zYwMA)HyjC(-^3dY`6E7W&=+0x2YtDDt(&rRmvgENck;*bd%hduR`Q9w4h~Fy0OVO{ A82|tP delta 804 zcmZ9~JxIe)5CGtJX@gA^go=jZphE{iMe0%~i-WcS(c)ZCaBvcF7a|CPlMM%5iqK37 zbtq&IL5EI)9TaqN5OfnMSO+JGHF>$VdT+RQ_uaevkkk?_qga6z+et&-e#$@|6Ob7$ zszR>0Xt)RE6mG+$cCUrfKnK!Vr9Z54_zEeg;*fIgLS$S?u6pgZdC-iRH_;^cXF9p! z=Wp>KOnbPfE`xB3>IPUx@;V@H<=zWOe%B+Josd5>KP7K5uaSGqFGE*^jthN;H5xqY zpVg2#h!pcj@+|Wg@=fMVa*O#Fc{y}TmO=QT#swSDWewti`3U(3^D**o<`d+D!3XIs z|NgVo$o^{xF;BkEJV(C6e2sjcd4b$!z7=>ufGDxXE)7(f?~&J;ACku--Pe-IG1{5| gC9M0=k?{;a{oIxD8a4gOeb<*j{_!|7V8%N0zqV9RY5)KL diff --git a/build/loops_and_cmp.asm b/build/loops_and_cmp.asm index c6ae2cf..58926cf 100644 --- a/build/loops_and_cmp.asm +++ b/build/loops_and_cmp.asm @@ -65,6 +65,25 @@ puts_finish_digits: mov rsi, r9 syscall ret +word_puts_str: + ; expects (addr, len) on data stack + mov rdx, [r12] + add r12, 8 + mov rsi, [r12] + add r12, 8 + cmp rdx, 0 + je puts_str_write_newline + mov rax, 1 + mov rdi, 1 + syscall +puts_str_write_newline: + mov byte [rel print_buf], 10 + mov rax, 1 + mov rdi, 1 + lea rsi, [rel print_buf] + mov rdx, 1 + syscall + ret word_dup: mov rax, [r12] sub r12, 8 diff --git a/build/loops_and_cmp.o b/build/loops_and_cmp.o index 1f7e196db71d8f883c8ba7aff64701c8856a41a9..8e4f71d7f4e537498834a2e3d5d3b95f83a19c04 100644 GIT binary patch delta 988 zcmZ9{KS+W>6aeshUwxz|gs4rKO}nN~kb3iU@&FgPN6hTdL&Ubc$u+u1tZIt0c1nbgO7%7@Ew1*|@*1G2Tk5Ijr^)zee{Eze67({(?S1{0%*- zyIn3t_`*UGcsn@a!1l;V{U5;2i96*Q*aPtv^l##w=uYLow@mucUBcsrn*L>AL*#%L z5BQ0Xq9=(@qNj<^pdTAt_K#rU!cY+JT1CGhzK(uNJcV8$zJp#ok*)Oe6bAA8- delta 824 zcmZ9{KS%;$6aet|PLK2yLPX4JC~6A_Cux#sFase7YG{aRaHz=5@rs%yc@R-c*A@y1 z7qkTtRJ1e%QAChaOQ36i#Pq(`k?)3g-}ig(eee4kv1;G$5#~x(67!|!6y_<0sYq1^ z=bQ1We`gz~bsY19q2!S)O#0sfYBxnSOkkP9TE#}stfmb%X-*%)FDmH6;isQgE3^IK z%iMTJJM~up_KBWDbI0jMxKpRNvB-Y!idyWmzY0HQZwN25H-(=m*TA5qo~Sv1-T7;7 zO9)rjK}ZXK;rbQf@9d^%#llzlD#m_iFCQ_M$yM z&WUta0$`kdQTQbLhVU%=rto?8lJMn@n}Dz<5^LO07G7Y#6u!k?7hYr!dH%l`;J|TJ kOw$-di)#KTR-9;4$cW;F6K`q4IJF~z1*Fwr*7tYHFKPNtga7~l diff --git a/build/override_dup_compile_time.asm b/build/override_dup_compile_time.asm index 1fc2fbb..99c6ae4 100644 --- a/build/override_dup_compile_time.asm +++ b/build/override_dup_compile_time.asm @@ -65,6 +65,25 @@ puts_finish_digits: mov rsi, r9 syscall ret +word_puts_str: + ; expects (addr, len) on data stack + mov rdx, [r12] + add r12, 8 + mov rsi, [r12] + add r12, 8 + cmp rdx, 0 + je puts_str_write_newline + mov rax, 1 + mov rdi, 1 + syscall +puts_str_write_newline: + mov byte [rel print_buf], 10 + mov rax, 1 + mov rdi, 1 + lea rsi, [rel print_buf] + mov rdx, 1 + syscall + ret word_dup: mov rax, [r12] sub r12, 8 diff --git a/build/override_dup_compile_time.o b/build/override_dup_compile_time.o index 14b8148689c784e590e1372a5b9e36115629b7bb..388f9ebc9575456b39efb6fa8518153e33277a75 100644 GIT binary patch delta 948 zcmZ9{Pbh<790%~{_ioc(Q^;n^!BTP{g&3Djl-lAzxw0H~Ahfnuob0d*Nzs#|GNl|G zu#`WC`4dp_T%=l8t1>Rr#uhEiu)-SjCfw$+D# zUU>}!Tu~d7YtU+Z#kQGGL6dr_8uG?d(5db^jNKg1Lo2-UDrLv-tPdqG?V+W1`3)w& zm{xWO`nilK<+dw%cWIG=%N^pDV-cs16{q5@{Vfzi$rpR*+FCE73sH(Iowbg^(3%8b z*sfcP8w2=Nc}xZ%73$`imA z$tmN_z_y5cxN#5}!a% znOx4-FxWE%V*Wh(Iq?PbTjCu3p7=WYEAee$9(@cji^cT2dbZU(=zmaVa1Aonw58<%k72^>X?Hq>(nq9lZ;S>bcV5;k zf>T!GARhHv828DaLea@7`785F@-OC9@;37u?NUUs)thpLp}Sw#ZDBKiAk-#d{;w=S@LD(i{u;3 zm&mu7>z4uHGG7no=LCp7*4UzhD$Gmdx6F4y;0z>T7i}vAhbo?7(a*0{tf6bwyv^to N_=|WETZsI>z#pjhM*RQ) diff --git a/build/string_puts.asm b/build/string_puts.asm new file mode 100644 index 0000000..edace3c --- /dev/null +++ b/build/string_puts.asm @@ -0,0 +1,305 @@ +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: + 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_puts_str: + ; expects (addr, len) on data stack + mov rdx, [r12] + add r12, 8 + mov rsi, [r12] + add r12, 8 + cmp rdx, 0 + je puts_str_write_newline + mov rax, 1 + mov rdi, 1 + syscall +puts_str_write_newline: + mov byte [rel print_buf], 10 + mov rax, 1 + mov rdi, 1 + lea rsi, [rel print_buf] + mov rdx, 1 + 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__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__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_str + ; push str_1 + sub r12, 8 + mov qword [r12], str_1 + ; push 11 + sub r12, 8 + mov qword [r12], 11 + call word_puts_str + ; push str_2 + sub r12, 8 + mov qword [r12], str_2 + ; push 0 + sub r12, 8 + mov qword [r12], 0 + call word_puts_str + ; push 0 + sub r12, 8 + mov qword [r12], 0 + ret +section .data +str_0: db 104, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100, 0 +str_0_len equ 11 +str_1: db 108, 105, 110, 101, 49, 10, 108, 105, 110, 101, 50, 0 +str_1_len equ 11 +str_2: db 0 +str_2_len equ 0 +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/string_puts.o b/build/string_puts.o new file mode 100644 index 0000000000000000000000000000000000000000..8b8d1c850f5b543a973f4c7dc06ea708c1bf51ca GIT binary patch literal 3552 zcmbW3U1%It6vyu-o4WbXtXj1~&_1jXp4r5GuyPH z7+8u9OAtXH6k8P(!6yqo#ENLUZ3;z$s9+(83ZfCsL+V4KiLU3~d*&mj**rL~d(Zuy z|2g;0xpVK#3u6=GZLt{huNZrbg*~4#HWHd>kFW%bN9g}E`B?mSfP{~H@swJ-l2E*BOG7|=J3`VJ6*{H1&7SX6HdjZN_z244 zF&_Of{~Nv71^--7?N*vA%LfLO=B3~Jl+4$PcSGI0xo{c4%1ieGRlJ6BcD4GmTH9i7 zrw|_nyd1xy3mTF6Gm+lAu6i32-b!yrL#-balT+)1a+0;bncEX;dpnlJW6%{MoZUs9 zN@U=-_eVnY;;9C|Psn*9l?V~P{rVITuP>!~-~xfHh#KP|e&^w6XY&YX1%Mz(%2mqi z%I0<}dN7iy-j`C2H$LIz>wUGs#|=k``d-_|_vSvnxAyU!-^X_@^eJ_QcY>wh^YRXf z`c2k*#63@9WhR3)+Pzk4eJHimDOLe<$u$(5Km72d$r=uceE9T*wWzJbqKq*BV@$1G zjjS1TfXZn=>A#4qrVmei2{FO4gK;g+ccO$~^9ih-`={9ys=b^GEu1{d+B9)CI2G5N zStyhb&zJ3j!3tK%%yjYptnX$l?V6`umNs-(XX(7-u(UJhxVEe3!8%ivE%t4*pi6xi z-@@Y0dz@`F_j0$3li^lR`<^EoKd){*u^tfNG1gDg^BdPZ9k%@+#p{7h{x9 zq5c)3pF#dM;b)M4O8AS&e<1uka$30ek@xVzMy?COjXqz4&gVEdxZas{5`_EL_fwZ5q>xF?+Nci{ukl>$nPQVwL#<=!iSL$ z6F!doNy48%?h!tP{2jt)kY6CYg8VY!&m#YZ@UzHo5dJc9{#K1%Zy;|cTj^cFi5LPu z5PYMFp9Mjxk5Jze5NU`P9PD?hzk+)I`@;{rj`{t*-+n7NnIt$@11=0-&VFgZ*8{%$ z-nLrsHX&$OMW#8fZoAl|OJ&VGZMoVh zy-+n79L9!FGA`Hjydw?6nzdZC3*~Y}QpcJtNo&R`SvLFi#Wuw%!wRzieO|4|k z^J88PWmGF@*pO7jl~0+rw48YznU>81U+S4$Y!&l^7IA8<786!Ib@s z=x2g{R`j!?Z@}U~F4<@<6wQ`IHiA@Oy None: + self.text.extend([ + f" ; push {label}", + " sub r12, 8", + f" mov qword [r12], {label}", + ]) + def push_from(self, register: str) -> None: self.text.extend([ " sub r12, 8", @@ -1083,10 +1090,14 @@ class Assembler: self.dictionary = dictionary self.stack_bytes = 65536 self.io_buffer_bytes = 128 + self._string_literals: Dict[str, Tuple[str, int]] = {} + self._data_section: Optional[List[str]] = None def emit(self, module: Module) -> Emission: emission = Emission() emission.text.extend(self._runtime_prelude()) + self._string_literals = {} + self._data_section = emission.data valid_defs = (Definition, AsmDefinition) definitions = [form for form in module.forms if isinstance(form, valid_defs)] @@ -1104,8 +1115,23 @@ class Assembler: self._emit_definition(definition, emission.text) emission.bss.extend(self._bss_layout()) + self._data_section = None return emission + def _intern_string_literal(self, value: str) -> Tuple[str, int]: + if self._data_section is None: + raise CompileError("string literal emission requested without data section") + if value in self._string_literals: + return self._string_literals[value] + label = f"str_{len(self._string_literals)}" + encoded = value.encode("utf-8") + bytes_with_nul = list(encoded) + [0] + byte_list = ", ".join(str(b) for b in bytes_with_nul) + self._data_section.append(f"{label}: db {byte_list}") + self._data_section.append(f"{label}_len equ {len(encoded)}") + self._string_literals[value] = (label, len(encoded)) + return self._string_literals[value] + def _emit_definition(self, definition: Union[Definition, AsmDefinition], text: List[str]) -> None: label = sanitize_label(definition.name) text.append(f"{label}:") @@ -1131,9 +1157,15 @@ class Assembler: def _emit_node(self, node: ASTNode, builder: FunctionEmitter) -> None: if isinstance(node, Literal): - if not isinstance(node.value, int): - raise CompileError("string literals are compile-time only") - builder.push_literal(node.value) + if isinstance(node.value, int): + builder.push_literal(node.value) + return + if isinstance(node.value, str): + label, length = self._intern_string_literal(node.value) + builder.push_label(label) + builder.push_literal(length) + return + raise CompileError(f"unsupported literal type {type(node.value)!r}") return if isinstance(node, WordRef): self._emit_wordref(node, builder) diff --git a/stdlib.sl b/stdlib.sl index 28381c8..d7b2c85 100644 --- a/stdlib.sl +++ b/stdlib.sl @@ -47,6 +47,27 @@ puts_finish_digits: } ; +:asm puts_str { + ; expects (addr, len) on data stack + mov rdx, [r12] + add r12, 8 + mov rsi, [r12] + add r12, 8 + cmp rdx, 0 + je puts_str_write_newline + mov rax, 1 + mov rdi, 1 + syscall +puts_str_write_newline: + mov byte [rel print_buf], 10 + mov rax, 1 + mov rdi, 1 + lea rsi, [rel print_buf] + mov rdx, 1 + syscall +} +; + :asm dup { mov rax, [r12] sub r12, 8 diff --git a/tests/run_tests.py b/tests/run_tests.py index 68a6af3..4578995 100644 --- a/tests/run_tests.py +++ b/tests/run_tests.py @@ -99,6 +99,20 @@ compile-only """, expected_stdout="6\n", ), + TestCase( + name="string_puts", + source=f""" +import {ROOT / 'stdlib.sl'} + +: main + \"hello world\" puts_str + \"line1\\nline2\" puts_str + \"\" puts_str + 0 +; +""", + expected_stdout="hello world\nline1\nline2\n\n", + ), ]