From 86fc8288aa24e6bb4e5fda03f9536c92b666170b Mon Sep 17 00:00:00 2001 From: Steve Kemp Date: Sat, 4 Jul 2026 19:58:27 +0300 Subject: [PATCH] Implement `mkdir` and `rmdir`. This closes #121, and adds a simple test-case too. --- PRIMITIVES.md | 4 ++++ README.md | 2 +- compiler/template.tmpl | 43 ++++++++++++++++++++++++++++++++++ test/mkdir-rmdir.lisp | 6 +++++ test/mkdir-rmdir.test.expected | 2 ++ 5 files changed, 56 insertions(+), 1 deletion(-) create mode 100644 test/mkdir-rmdir.lisp create mode 100644 test/mkdir-rmdir.test.expected diff --git a/PRIMITIVES.md b/PRIMITIVES.md index 7e9e184..dc1b6a3 100644 --- a/PRIMITIVES.md +++ b/PRIMITIVES.md @@ -111,6 +111,8 @@ Note that functions have their names mangled a little bit ("-" is converted to " * `int` * Convert the given float, or character, to an integer. * Anything else becomes zero. + * `mkdir` + * Create the named directory. **NOTE**: Mode is fixed at 0755, and parent directories must exist. * `newline` * Print a newline. * `not` @@ -129,6 +131,8 @@ Note that functions have their names mangled a little bit ("-" is converted to " * Print the given string. * `random` * Return a random integer between zero and N. + * `rmdir` + * Remove the named directory. * `setnth` * Update the Nth item in the given list with the specified value. * The list is updated in-place. diff --git a/README.md b/README.md index 9625c47..03432ae 100644 --- a/README.md +++ b/README.md @@ -64,7 +64,7 @@ It should be noted that we prepend a standard library of functions to all user p * File I/O operations: * `fopen`, `fclose`, `fread`, and `fwrite`. * Filesystem primitive: - * `dir?`, `entries`, `exists?`, `file?`, `stat`, `unlink` and `which`. + * `dir?`, `entries`, `exists?`, `file?`, `mkdir`, `rmdir`, `stat`, `unlink` and `which`. * Comparison operations: * `=`, `<`, `<=`, `>=`, `>`, and `!` to invert a result. * Special forms diff --git a/compiler/template.tmpl b/compiler/template.tmpl index a5c32a9..7b0cf1b 100644 --- a/compiler/template.tmpl +++ b/compiler/template.tmpl @@ -37,6 +37,8 @@ SYS_close equ 3 SYS_stat equ 4 SYS_lseek equ 8 SYS_exit equ 60 +SYS_mkdir equ 83 +SYS_rmdir equ 84 SYS_unlink equ 87 SYS_getdents64 equ 217 SYS_getrandom equ 318 @@ -1423,6 +1425,27 @@ FUNC fn_int ret +;; Make a directory, mode is fixed +FUNC fn_mkdir + mov rbx, rdi + GET_TAG_BITS rbx + cmp rbx, TAG_ID_STRING + jne type_error + + UNTAG_REG rdi + mov rax, SYS_mkdir + mov rsi, 0o755 ; mode in octal + syscall + test rax,rax + js .failure + TAG_INTEGER_REG rax + ret +.failure: + xor rax,rax + TAG_NIL_REG rax + ret + + ;; A nil becomes 1, anything else becomes nil. FUNC fn_not mov rax, rdi @@ -1535,6 +1558,26 @@ FUNC fn_random +;; Remove a directory, mode is fixed +FUNC fn_rmdir + mov rbx, rdi + GET_TAG_BITS rbx + cmp rbx, TAG_ID_STRING + jne type_error + + UNTAG_REG rdi + mov rax, SYS_rmdir + syscall + test rax,rax + js .failure + TAG_INTEGER_REG rax + ret +.failure: + xor rax,rax + TAG_NIL_REG rax + ret + + ;; Update the Nth list item, leaving everything else as-is. FUNC fn_setnth mov rbx,rdi ; arg1: list diff --git a/test/mkdir-rmdir.lisp b/test/mkdir-rmdir.lisp new file mode 100644 index 0000000..fb0fc07 --- /dev/null +++ b/test/mkdir-rmdir.lisp @@ -0,0 +1,6 @@ +(defun main () + (mkdir "foo") + (println "Does foo/ exist:" (dir? "foo")) + (rmdir "foo") + (println "Does foo/ exist:" (dir? "foo")) + ) diff --git a/test/mkdir-rmdir.test.expected b/test/mkdir-rmdir.test.expected new file mode 100644 index 0000000..63e86f0 --- /dev/null +++ b/test/mkdir-rmdir.test.expected @@ -0,0 +1,2 @@ +Does foo/ exist:1 +Does foo/ exist: