stdio.fnl 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657
  1. (require "love.event")
  2. (local fennel (require "lib.fennel"))
  3. (local view (require "lib.fennelview"))
  4. ;; This module exists in order to expose stdio over a channel so that it
  5. ;; can be used in a non-blocking way from another thread.
  6. (local (event channel) ...)
  7. (defn display [s]
  8. (io.write s)
  9. (io.flush))
  10. (defn prompt []
  11. (display "\n>> "))
  12. (defn read-chunk []
  13. (let [input (io.read)]
  14. (when input
  15. (.. input "\n"))))
  16. (var input "")
  17. (when channel
  18. (let [(bytestream clearstream) (fennel.granulate read-chunk)
  19. read (fennel.parser
  20. (fn []
  21. (let [c (or (bytestream) 10)]
  22. (set input (.. input (string.char c)))
  23. c)))]
  24. (while true
  25. (prompt)
  26. (set input "")
  27. (let [(ok ast) (pcall read)]
  28. (if (not ok)
  29. (do
  30. (display (.. "Parse error:" ast "\n"))
  31. ;; fixme: not sure why the following fails
  32. ;; (clearstream)
  33. )
  34. (do
  35. (love.event.push event input)
  36. (display (: channel :demand))))))))
  37. {:start (fn start-repl []
  38. (let [code (love.filesystem.read "stdio.fnl")
  39. lua (if code
  40. (love.filesystem.newFileData
  41. (fennel.compileString code) "io")
  42. (love.filesystem.read "lib/stdio.lua"))
  43. thread (love.thread.newThread lua)
  44. io-channel (love.thread.newChannel)]
  45. ;; this thread will send "eval" events for us to consume:
  46. (: thread :start "eval" io-channel)
  47. (set love.handlers.eval
  48. (fn [input]
  49. (let [(ok val) (pcall fennel.eval input)]
  50. (: io-channel :push (if ok (view val) val)))))))}