aboutsummaryrefslogtreecommitdiff
path: root/luxc/src/lux/repl.clj
diff options
context:
space:
mode:
authorEduardo Julian2016-12-01 11:00:44 -0400
committerEduardo Julian2016-12-01 11:00:44 -0400
commit7f66c54f4c9753b94dbf46ec50b8b16549daf324 (patch)
tree1b5b896cfba870a66a99a03315b09df842eb5737 /luxc/src/lux/repl.clj
parent9c30546af022f8fe36b73e7e93414257ff28ee75 (diff)
- Collected the Lux compiler's repo, the Standard Library's, the Leiningen plugin's and the Emacs mode's into a big monorepo, to keep development unified.
Diffstat (limited to 'luxc/src/lux/repl.clj')
-rw-r--r--luxc/src/lux/repl.clj89
1 files changed, 89 insertions, 0 deletions
diff --git a/luxc/src/lux/repl.clj b/luxc/src/lux/repl.clj
new file mode 100644
index 000000000..195f3dc3e
--- /dev/null
+++ b/luxc/src/lux/repl.clj
@@ -0,0 +1,89 @@
+;; Copyright (c) Eduardo Julian. All rights reserved.
+;; This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
+;; If a copy of the MPL was not distributed with this file,
+;; You can obtain one at http://mozilla.org/MPL/2.0/.
+
+(ns lux.repl
+ (:require clojure.core.match
+ clojure.core.match.array
+ (lux [base :as & :refer [|let |do return* return fail fail* |case]]
+ [type :as &type]
+ [analyser :as &analyser]
+ [optimizer :as &optimizer]
+ [compiler :as &compiler])
+ [lux.compiler.cache :as &cache]
+ [lux.analyser.base :as &a-base]
+ [lux.analyser.lux :as &a-lux]
+ [lux.analyser.module :as &module])
+ (:import (java.io InputStreamReader
+ BufferedReader)))
+
+;; [Utils]
+(def ^:private repl-module "REPL")
+
+(defn ^:private repl-cursor [repl-line]
+ (&/T [repl-module repl-line 0]))
+
+(defn ^:private init [source-dirs]
+ (do (&compiler/init!)
+ (|case ((|do [_ (&compiler/compile-module source-dirs "lux")
+ _ (&cache/delete repl-module)
+ _ (&module/create-module repl-module 0)
+ _ (fn [?state]
+ (return* (&/set$ &/$source
+ (&/|list (&/T [(repl-cursor -1) "(;import lux)"]))
+ ?state)
+ nil))
+ analysed-tokens (&analyser/repl-analyse &optimizer/optimize &compiler/eval! (partial &compiler/compile-module source-dirs) &compiler/all-compilers)
+ eval-values (->> analysed-tokens (&/|map &optimizer/optimize) (&/map% &compiler/eval!))]
+ (return nil))
+ (&/init-state &/$REPL))
+ (&/$Right ?state _)
+ (do (println)
+ (println "Welcome to the REPL!")
+ (println "Type \"exit\" to leave.")
+ (println)
+ ?state)
+
+ (&/$Left ?message)
+ (assert false ?message))
+ ))
+
+;; [Values]
+(defn repl [source-dirs]
+ (with-open [input (->> System/in (new InputStreamReader) (new BufferedReader))]
+ (loop [state (init source-dirs)
+ repl-line 0
+ multi-line? false]
+ (let [_ (if (not multi-line?)
+ (.print System/out "> ")
+ (.print System/out " "))
+ line (.readLine input)]
+ (if (= "exit" line)
+ (println "Till next time...")
+ (let [line* (&/|list (&/T [(repl-cursor repl-line) line]))
+ state* (&/update$ &/$source
+ (fn [_source] (&/|++ _source line*))
+ state)]
+ (|case ((|do [analysed-tokens (&analyser/repl-analyse &optimizer/optimize &compiler/eval! (partial &compiler/compile-module source-dirs) &compiler/all-compilers)
+ eval-values (->> analysed-tokens (&/|map &optimizer/optimize) (&/map% &compiler/eval!))
+ :let [outputs (map (fn [analysis value]
+ (|let [[[_type _cursor] _term] analysis]
+ [_type value]))
+ (&/->seq analysed-tokens)
+ (&/->seq eval-values))]]
+ (return outputs))
+ state*)
+ (&/$Right state** outputs)
+ (do (doseq [[_type _value] outputs]
+ (.println System/out (str "=> " (pr-str _value) "\n:: " (&type/show-type _type)"\n")))
+ (recur state** (inc repl-line) false))
+
+ (&/$Left ^String ?message)
+ (if (or (= "[Reader Error] EOF" ?message)
+ (.contains ?message "[Parser Error] Unbalanced "))
+ (recur state* (inc repl-line) true)
+ (do (println ?message)
+ (recur state (inc repl-line) false)))
+ ))))
+ )))