Rewrite stdio repl to simplify secondary thread.
It should be doing solely two tasks: reading and writing. Nothing else.
This commit is contained in:
parent
0b04501302
commit
078ffc1e83
|
@ -1,29 +1,24 @@
|
|||
(require "love.event")
|
||||
(local {: view} (require :lib.fennel))
|
||||
|
||||
;; This module exists in order to expose stdio over a channel so that it
|
||||
;; can be used in a non-blocking way from another thread.
|
||||
|
||||
(local (event channel) ...)
|
||||
(fn prompt [cont?]
|
||||
(io.write (if cont? ".." ">> ")) (io.flush) (.. (io.read) "\n"))
|
||||
|
||||
(fn prompt [next-line?]
|
||||
(io.write (if next-line? ".." ">> ")) (io.flush) (.. (io.read) "\n"))
|
||||
;; This module is loaded twice: initially in the main thread where ... is nil,
|
||||
;; and then again in a separate thread where ... contains the channel used to
|
||||
;; communicate with the main thread.
|
||||
|
||||
(when channel
|
||||
((fn looper [input]
|
||||
(when input
|
||||
;; This is consumed by love.handlers[event]
|
||||
(love.event.push event input)
|
||||
(let [output (: channel :demand)
|
||||
next-line (and (. output 2) (= "next-line" (. output 2)))]
|
||||
;; There is probably a more efficient way of determining an error
|
||||
(if next-line :ok
|
||||
(and (. output 2) (= "Error:" (. output 2)))
|
||||
(print (view output))
|
||||
(each [_ ret (ipairs output)]
|
||||
(print ret)))
|
||||
(io.flush)
|
||||
(looper (prompt next-line))))) (prompt)))
|
||||
(fn looper [event channel]
|
||||
(match (channel:demand)
|
||||
[:write vals] (do (io.write (table.concat vals "\t"))
|
||||
(io.write "\n"))
|
||||
[:read cont?] (love.event.push event (prompt cont?)))
|
||||
(looper event channel))
|
||||
|
||||
(match ...
|
||||
(event channel) (looper event channel))
|
||||
|
||||
{:start (fn start-repl []
|
||||
(let [code (love.filesystem.read "lib/stdio.fnl")
|
||||
|
@ -34,19 +29,17 @@
|
|||
thread (love.thread.newThread luac)
|
||||
io-channel (love.thread.newChannel)
|
||||
coro (coroutine.create fennel.repl)
|
||||
out (fn [val]
|
||||
(: io-channel :push val))
|
||||
options {:readChunk (fn [parser-state]
|
||||
(when (> parser-state.stack-size 0)
|
||||
(: io-channel :push ["next-line" "next-line"]))
|
||||
options {:readChunk (fn [{: stack-size}]
|
||||
(io-channel:push [:read (< 0 stack-size)])
|
||||
(coroutine.yield))
|
||||
:onValues out
|
||||
:onError (fn [kind ...] (out [kind "Error:" ...]))
|
||||
:pp view
|
||||
:onValues (fn [vals]
|
||||
(io-channel:push [:write vals]))
|
||||
:onError (fn [errtype err]
|
||||
(io-channel:push [:write [err]]))
|
||||
:moduleName "lib.fennel"}]
|
||||
;; this thread will send "eval" events for us to consume:
|
||||
(coroutine.resume coro options)
|
||||
(: thread :start "eval" io-channel)
|
||||
(thread:start "eval" io-channel)
|
||||
(set love.handlers.eval
|
||||
(fn [input]
|
||||
(coroutine.resume coro input)))))}
|
||||
(coroutine.resume coro input)))))}
|
||||
|
|
Loading…
Reference in a new issue