fisl

fisl is scheme lox
git clone git://git.alexkarle.com.com/fisl
Log | Files | Refs | README | LICENSE

commit 3e6652310186a1debf0710fa1d071a4a7c876deb (patch)
parent 517e4a7c97715986f72c5902c8162b95b9c21c5b
Author: Alex Karle <alex@alexkarle.com>
Date:   Tue,  8 Nov 2022 23:14:50 -0500

repl: Add threads and nrepl for live image updates

This was a deep rabbit hole, mostly because (read-line) is blocking I/O
and _all_ threads block when blocking I/O is hit (except tcp). This was
counterintuitive (isn't the whole point of threads to swap when on I/O?)
but nevertheless, I got it to work!

Here's my setup:

1. Start the CHICKEN interpreter via the executable (drops into Lox
   interpreter):

$ ./fisl.scm
> print 1 + 1;
2
>

2. In another tmux split, create a fifo and connect to the 1234 nrepl
   port (credit: http://www.foldling.org/hacking.html#2012-08-05):

$ mkfifo repl
$ cat > repl & nc localhost 1234 < repl

3. Lastly, in Vim, run the following to send the current paragraph to
   the repl on C-c C-c:

:nnoremap <C-c><C-c> vap:w >> repl<CR>

---

Demo:

* Go to (prompt), update s/display "> "/display ">> "/
* C-c C-c
* Hit enter in fisl -- notice prompt is changed!

Diffstat:
Mfisl.scm | 35++++++++++++++++++++++++++---------
1 file changed, 26 insertions(+), 9 deletions(-)

diff --git a/fisl.scm b/fisl.scm @@ -1,6 +1,9 @@ #!/usr/local/bin/chicken-csi -ss ;; fisl -- fisl is scheme lox -(import (chicken io) +(import srfi-18 + nrepl + (chicken io) + (chicken repl) (chicken base) (chicken format)) @@ -16,14 +19,25 @@ (if stmts (interpret stmts)))))) -(define (run-prompt) +(define (prompt) + ;; HACK: srfi-18 blocks for IO, so having run-prompt + ;; use read-line means that nrepl just doesn't work :( + ;; the "solution" is to set the i/o to non-blocking + ;; (adapted from the srfi-18 egg itself) (display "> ") - (let ((l (read-line))) - (if (not (or (eof-object? l) (equal? l ",q"))) - (begin - (run l "repl") - (clear-err!) - (run-prompt))))) + (flush-output) + (##sys#thread-block-for-i/o! ##sys#current-thread 0 #:input) + (thread-yield!)) + +(define (run-prompt) + (parameterize ((repl-prompt "> ")) + (prompt) + (let ((l (read-line))) + (if (not (or (eof-object? l) (equal? l ",q"))) + (begin + (run l "repl") + (clear-err!) + (run-prompt)))))) (define (run-file fname) (call-with-input-file fname (lambda (p) @@ -33,6 +47,9 @@ (define (main args) (let ((argc (length args))) (cond - ((eq? argc 0) (run-prompt) (exit 0)) + ((eq? argc 0) + (thread-start! (lambda () (run-prompt) (exit 0))) + (print "starting the repl") + (nrepl 1234)) ((eq? argc 1) (run-file (car args))) (else (die "Too many arguments. Usage: fisl [FILE]")))))