Add basic repl session management

This commit is contained in:
Scott Richmond 2022-05-26 20:24:41 -04:00
parent 059fc16df2
commit a57446db93

View File

@ -4,7 +4,10 @@
[ludus.parser :as parser] [ludus.parser :as parser]
[ludus.interpreter :as interpreter] [ludus.interpreter :as interpreter]
[ludus.prelude :as prelude] [ludus.prelude :as prelude]
[ludus.show :as show])) [ludus.show :as show]
[ludus.data :as data]))
(declare repl-prelude new-session)
(def sessions (atom {})) (def sessions (atom {}))
@ -12,31 +15,71 @@
(def prompt "=> ") (def prompt "=> ")
(def base-ctx (merge prelude/prelude
{::repl true "foo" :bar
"repl"
{
::data/struct true
::data/type ::data/ns
::data/name "repl"
:flush
{:name "flush"
::data/type ::data/clj
:body (fn []
(let [session @current-session]
(swap! session #(assoc % :ctx (volatile! base-ctx)))
:ok))}
:new
{:name "new"
::data/type ::data/clj
:body (fn [name]
(let [session (new-session name)]
(reset! current-session session)
:ok))}
:swap
{:name "swap"
::data/type ::data/clj
:body (fn [name]
(if-let [session (get @sessions name)]
(do
(reset! current-session session)
:ok)
(do
(println "No session named" name)
:error)))}
}}))
(defn- new-session [name] (defn- new-session [name]
(let [session (atom { (let [session (atom {
:name name :name name
:ctx (volatile! (merge prelude/prelude {::repl true})) :ctx (volatile! base-ctx)
:history []})] :history []})]
(swap! sessions #(assoc % name session)) (swap! sessions #(assoc % name session))
session)) session))
(defn repl-loop [session-atom] (defn repl-loop []
(let [session @session-atom] (let [session-atom @current-session
session @session-atom
orig-ctx (:ctx session)]
(print (str (:name session) prompt)) (print (str (:name session) prompt))
(flush) (flush)
(let [input (read-line) (let [input (read-line)
parsed (-> input (scanner/scan) (parser/parse)) parsed (-> input (scanner/scan) (parser/parse))
{result :result ctx :ctx} (interpreter/interpret-repl parsed (:ctx session))] {result :result ctx :ctx} (interpreter/interpret-repl parsed (:ctx session))]
(if (= result ::interpreter/error) (if (= result ::interpreter/error)
(repl-loop session-atom) (repl-loop)
(do (do
(println (show/show result)) (println (show/show result))
(swap! session-atom #(assoc % :ctx ctx)) (when (not (= @ctx @orig-ctx))
(repl-loop session-atom)))))) (swap! session-atom #(assoc % :ctx ctx)))
(repl-loop))))))
(defn launch [] (defn launch []
(println "Welcome to Ludus (v. 0.1.0-alpha)") (println "Welcome to Ludus (v. 0.1.0-alpha)")
(let [session (new-session "ludus")] (let [session (new-session "ludus")]
(reset! current-session session) (reset! current-session session)
(repl-loop session))) (repl-loop)))