From 2129feb17e6a87ca72800b95450e47db5bc2c199 Mon Sep 17 00:00:00 2001 From: Steve Kemp Date: Sun, 27 Sep 2026 18:58:36 +0300 Subject: [PATCH 1/2] Ported `getc` and `putc` from assembly to lisp. This closes #259, and is a pretty trivial change. --- PRIMITIVES.md | 8 ++++---- compiler/template.tmpl | 37 ------------------------------------- inception.lisp | 2 -- stdlib.slisp | 24 ++++++++++++++++-------- 4 files changed, 20 insertions(+), 51 deletions(-) diff --git a/PRIMITIVES.md b/PRIMITIVES.md index 2014985..06c18b2 100644 --- a/PRIMITIVES.md +++ b/PRIMITIVES.md @@ -129,8 +129,6 @@ added to them too. * `fwrite` * Write the given data, with length, to the open file handle. * To simplify usage `fwrite` will accept a nil-filehandle, and return nil. - * `getc` - * Read a single character from STDIN, return NIL on failure. * `implode` * Convert the given list of characters to a string. * `int` @@ -154,8 +152,6 @@ added to them too. * Return the contents of one of our embedded packages at runtime. * `packages` * Return the names of our embedded packages. - * `putc` - * Print the given character. * `printfloat` * Print the specified floating point number. * `printint` @@ -246,6 +242,8 @@ The implementation of these primitives can be found in the file [stdlib.slisp](s * Return the offset of matching items inside the given list. * `flatten` * Flatten the given list of lists into a single list +* `getc` + * Read a single character from STDIN, return NIL on failure. * `getenv` * Return the value of the given environmental variable, nor NIL if not found. * Uses `environment`. @@ -299,6 +297,8 @@ The implementation of these primitives can be found in the file [stdlib.slisp](s * Print "anything". * `println` * Print "anything" by invoking `print`, then outputting a newline. +* `putc` + * Print the given character. * `random` * Return a random integer between zero and N-1. * `range` diff --git a/compiler/template.tmpl b/compiler/template.tmpl index b44190c..9ca66ed 100644 --- a/compiler/template.tmpl +++ b/compiler/template.tmpl @@ -1784,28 +1784,6 @@ FUNC fn_sys_fwrite -;; Read an ASCII character from STDIN, return NIL on failure. -FUNC fn_sys_getc - mov rax, SYS_read - mov rdi, 0 ; STDIN - mov rsi, random_buffer - mov rdx, 1 ; 1 byte - syscall - - cmp rax, 1 - jne .getc_failed - - mov al, byte [random_buffer] - and rax, 0xFF ; Mask the value to 0-255. - TAG_INTEGER_REG rax - ret -.getc_failed: - xor rax, rax - TAG_INTEGER_REG rax - ret - - - ;; join a character list to a string. FUNC fn_sys_implode mov rbx,rdi @@ -2379,21 +2357,6 @@ FUNC fn_sys_packages ret -;; Write the given ASCII character to STDOUT -FUNC fn_sys_putc - mov rax, rdi - push rax - UNTAG_REG rax - mov rsi, random_buffer ; destination - mov [rsi], al ; store character - mov rax, SYS_write - mov rdi, 1 ; STDOUT - mov rdx, 1 ; 1 byte - syscall - pop rax ; This is the tagged input value - ret - - ;; system helper FUNC fn_sys_run mov rbx, rdi ; type check diff --git a/inception.lisp b/inception.lisp index 0de4047..a50ea81 100644 --- a/inception.lisp +++ b/inception.lisp @@ -313,7 +313,6 @@ (register-builtin "sys_fopen" (lambda (args) (sys_fopen (car args) (cadr args)))) (register-builtin "sys_fread" (lambda (args) (sys_fread (car args)))) (register-builtin "sys_fwrite" (lambda (args) (sys_fwrite (car args) (cadr args) (caddr args)))) - (register-builtin "sys_getc" (lambda (args) (sys_getc))) (register-builtin "sys_implode" (lambda (args) (sys_implode (car args)))) (register-builtin "sys_int" (lambda (args) (sys_int (car args)))) (register-builtin "sys_isqrt" (lambda (args) (sys_isqrt (car args)))) @@ -329,7 +328,6 @@ (register-builtin "sys_package" (lambda (args) (sys_package (car args)))) (register-builtin "sys_packages" (lambda (args) (sys_packages ))) (register-builtin "sys_plus" (lambda (args) (sys_plus (car args) (cadr args)))) - (register-builtin "sys_putc" (lambda (args) (sys_putc (car args)))) (register-builtin "sys_run" (lambda (args) (sys_run (car args) (cadr args)))) (register-builtin "sys_split" (lambda (args) (sys_split (car args) (cadr args)))) (register-builtin "sys_sqrt" (lambda (args) (sys_sqrt (car args)))) diff --git a/stdlib.slisp b/stdlib.slisp index 75932b3..6e1ce1a 100644 --- a/stdlib.slisp +++ b/stdlib.slisp @@ -122,10 +122,6 @@ It is assumed the filehandle came from fopen, but nil is also accepted." It is assumed the filehandle came from fopen, but nil is also accepted." (sys_fwrite handle data len)) -(defun getc () - "Read a single character from STDIN, and return it." - (sys_getc)) - (defun implode (xs) "Convert a list of characters to a string." (sys_implode xs)) @@ -170,10 +166,6 @@ It is assumed the filehandle came from fopen, but nil is also accepted." "Return the names of all embedded packages." (sys_packages)) -(defun putc (c) - "Write the single specified character to STDOUT." - (sys_putc c)) - ;; NOP: This is a special form in our compiler ;; However if we make this then we can pretend ;; we load packages. @@ -1015,6 +1007,15 @@ Incrementing by the given step each time." ;; These are functions which are designed to interface with the ;; system environment more than just with File I/O +(defconst SYS_read 0) + +(defun getc () + "Read a single character from STDIN, and return it." + (let ((str "s")) + (if (> (syscall SYS_read 0 str 1) 0) + (strat str 0) + 0))) + (defun getenv (name) "Return the contents of a given environmental variable. @@ -1032,6 +1033,13 @@ Uses (environment) to get all environmental variables, and filters." nil)) +(defun putc (c) + "Write the single specified character to STDOUT." + (let ((lst (list #\x))) + (nth! lst 0 c) + (let ((str (implode lst))) + (syscall 1 1 str 1)))) + (defconst SYS_getrandom 318) (defun random (n) From 6f825b38727005d5b8858025211080423ad95152 Mon Sep 17 00:00:00 2001 From: Steve Kemp Date: Sun, 27 Sep 2026 19:10:19 +0300 Subject: [PATCH 2/2] Correctly handle different types in putc. --- stdlib.slisp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/stdlib.slisp b/stdlib.slisp index 6e1ce1a..a5aba16 100644 --- a/stdlib.slisp +++ b/stdlib.slisp @@ -1035,10 +1035,11 @@ Uses (environment) to get all environmental variables, and filters." (defun putc (c) "Write the single specified character to STDOUT." - (let ((lst (list #\x))) - (nth! lst 0 c) - (let ((str (implode lst))) - (syscall 1 1 str 1)))) + (cond + ((str? c) (syscall 1 1 (substr c 0 1) 1)) + ((char? c) (syscall 1 1 (string c) 1)) + ((int? c) (syscall 1 1 (string (chr (& 255 c))) 1)) + (t (do (println "putc called with bogus arg") (exit 1))))) (defconst SYS_getrandom 318)