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:
M | fisl.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]")))))