Permalink
Browse files

Factor out common REPL code to cljs/cljs/repl.cljs

Also get nodecljs.cljs working using repl.cljs and add example
shebang.cljs which can be executed directly.
  • Loading branch information...
1 parent 1c1496a commit dd3c8769a6c6f65acf4e5561af9bbdc1cca083dc @kanaka committed Feb 17, 2013
Showing with 96 additions and 172 deletions.
  1. +10 −0 node/shebang.cljs
  2. +48 −0 src/cljs/cljs/repl.cljs
  3. +11 −27 src/cljs/nodecljs.cljs
  4. +11 −45 src/cljs/noderepl.cljs
  5. +11 −47 src/cljs/webrepl.cljs
  6. +5 −53 src/cljs/webrepl2.cljs
View
@@ -0,0 +1,10 @@
+#!./run.js nodecljs.js
+
+(ns shebang-test)
+
+(def dbl (fn* [x] (* 2 x)))
+
+(println "Hello World UNIX World.")
+(println "(dbl 16) is:" (dbl 16))
+
+8
@@ -0,0 +1,48 @@
+(ns cljs.repl
+ (:require [cljs.analyzer :as ana]
+ [cljs.compiler :as comp]
+ [cljs.reader :as reader]))
+
+(def ^:dynamic *debug* false)
+(def ^:dynamic *e nil)
+
+(defn prompt [] (str *ns-sym* "=> "))
+
+(defn read-forms [text]
+ ;; Save and restore *ns-sym*
+ (binding [*ns-sym* *ns-sym*]
+ (reader/read-string (str "(do " text ")"))))
+
+(defn eval-print [text]
+ (try
+ (let [env (assoc (ana/empty-env) :context :expr)
+ forms (read-forms text)
+ _ (when *debug* (println "READ:" (pr-str forms)))
+ body (ana/analyze env forms)
+ _ (when *debug* (println "ANALYZED:" (pr-str (:form body))))
+ res (comp/emit-str body)
+ _ (when *debug* (println "EMITTED:" (pr-str res)))
+ value (js/eval res)]
+ (set! *3 *2)
+ (set! *2 *1)
+ (set! *1 value)
+ (binding [*out* *rtn*] (print (pr-str value))
+ {:value value :js res}))
+ (catch js/Error e
+ (set! *e e)
+ (binding [*out* *err*] (print (.-stack e)))
+ {:error (.-stack e)})))
+
+(defn complete-form? [text]
+ (try
+ (reader/read-string text)
+ true
+ (catch js/Error e
+ (not (re-find #"EOF while reading" (.-message e))))))
+
+(defn init []
+ ;; Bootstrap an empty version of the cljs.user namespace
+ (swap! comp/*emitted-provides* conj (symbol "cljs.user"))
+ (.provide js/goog "cljs.user")
+ (set! cljs.core/*ns-sym* (symbol "cljs.user")))
+
@@ -1,37 +1,21 @@
(ns nodecljs
- (:require [cljs.core]
- [cljs.analyzer :as ana]
- [cljs.compiler :as comp]
- [cljs.reader :as reader]))
-
-(defn ep [text]
- (let [r (reader/push-back-reader text)]
- (loop [str (reader/read r false :eof false)]
- (when (not= str :eof)
- (try
- (let [env (ana/empty-env)
- res (comp/emit-str (ana/analyze env str))]
- (js/eval res))
- (catch js/Error e
- (println e)
- #_(set! *e e)))
- (recur (reader/read r false :eof false))))))
+ (:require [cljs.repl :as repl]))
(defn -main [file & args]
+ (repl/init)
+
;; Setup the print function
- (set! *out* (.-write (.-stdout js/process)))
- (set! *err* (.-write (.-stderr js/process)))
+ (set! *out* #(.write (.-stdout js/process) %))
+ (set! *rtn* identity)
+ (set! *err* #(.write (.-stderr js/process) %))
(set! *print-fn* #(*out* %1))
- ;; Bootstrap an empty version of the cljs.user namespace
- (swap! cljs.compiler/*emitted-provides* conj (symbol "cljs.user"))
- (.provide js/goog "cljs.user")
- (set! cljs.core/*ns-sym* (symbol "cljs.user"))
-
- ;(set! js/env (assoc js/env :context :expr))
+ ;(set! repl/*debug* true)
(let [fs (js/require "fs")
- text (.toString (.readFileSync fs file))]
- (ep text)))
+ text (.toString (.readFileSync fs file))
+ res (repl/eval-print text)
+ ret (:value res)]
+ (.exit js/process (if (number? ret) ret 0))))
(set! *main-cli-fn* -main)
@@ -1,53 +1,17 @@
(ns noderepl
- (:require [cljs.core]
- [cljs.analyzer :as ana]
- [cljs.compiler :as comp]
- [cljs.reader :as reader]))
-
-(def ^:dynamic *debug* false)
-(def ^:dynamic *e nil)
-
-(defn prompt [] (str *ns-sym* "=> "))
-
-(defn repl-print [text cls]
- (doseq [line (.split (str text) #"\n")]
- (when (= "err" cls)
- (print "ERR: "))
- (println line)))
-
-(defn- read-next-form [text]
- (binding [*ns-sym* *ns-sym*]
- (reader/read-string text)))
-
-(defn postexpr [text]
- (println (str (prompt) text)))
-
-(defn ep [text]
- (try
- (let [env (assoc (ana/empty-env) :context :expr)
- form (read-next-form text)
- _ (when *debug* (println "READ:" (pr-str form)))
- body (ana/analyze env form)
- _ (when *debug* (println "ANALYZED:" (pr-str (:form body))))
- res (comp/emit-str body)
- _ (when *debug* (println "EMITTED:" (pr-str res)))]
- (repl-print (pr-str (js/eval res)) "rtn"))
- (catch js/Error e
- (repl-print (.-stack e) "err")
- (set! *e e))))
+ (:require [cljs.repl :as repl]))
(defn pep [text]
- (postexpr text)
- (ep text))
+ (println (str (repl/prompt) text))
+ (repl/eval-print text)
+ (println))
(defn -main [& args]
- ;; Bootstrap an empty version of the cljs.user namespace
- (swap! comp/*emitted-provides* conj (symbol "cljs.user"))
- (.provide js/goog "cljs.user")
- (set! cljs.core/*ns-sym* (symbol "cljs.user"))
+ (repl/init)
;; Setup the print function
(set! *out* #(.write (.-stdout js/process) %))
+ (set! *rtn* #(.write (.-stdout js/process) %))
(set! *err* #(.write (.-stderr js/process) %))
(set! *print-fn* #(*out* %))
@@ -59,14 +23,16 @@
(pep "(sqr 8)")
(pep "(defmacro unless [pred a b] `(if (not ~pred) ~a ~b))")
(pep "(unless false :yep :nope)")
+
(let [readline (js/require "readline")
rl (.createInterface readline js/process.stdin js/process.stdout)]
- (.setPrompt rl (prompt))
+ (.setPrompt rl (repl/prompt))
(.prompt rl)
(.on rl "line" (fn [line]
(when (seq (filter #(not= " " %) line))
- (ep line))
- (.setPrompt rl (prompt))
+ (repl/eval-print line)
+ (println))
+ (.setPrompt rl (repl/prompt))
(.prompt rl)))
(.on rl "close" (fn [] (.exit js/process 0)))))
View
@@ -1,13 +1,5 @@
(ns webrepl
- (:require [cljs.core]
- [cljs.analyzer :as ana]
- [cljs.compiler :as comp]
- [cljs.reader :as reader]))
-
-(def ^:dynamic *debug* false)
-(def ^:dynamic *e nil)
-
-(defn prompt [] (str *ns-sym* "=> "))
+ (:require [cljs.repl :as repl]))
(def append-dom)
@@ -38,45 +30,20 @@
line]))
(set! (.-scrollTop log) (.-scrollHeight log)))
-(defn- read-next-form [text]
- (binding [*ns-sym* *ns-sym*]
- (reader/read-string text)))
-
(defn postexpr [log text]
(append-dom log
[:table
[:tbody
[:tr
- [:td {:class "cg"} (prompt)]
+ [:td {:class "cg"} (repl/prompt)]
[:td (.replace text #"\n$" "")]]]]))
-(defn ep [text]
- (try
- (let [env (assoc (ana/empty-env) :context :expr)
- form (read-next-form text)
- _ (when *debug* (println "READ:" (pr-str form)))
- body (ana/analyze env form)
- _ (when *debug* (println "ANALYZED:" (pr-str (:form body))))
- res (comp/emit-str body)
- _ (when *debug* (println "EMITTED:" (pr-str res)))
- value (js/eval res)]
- (set! *3 *2)
- (set! *2 *1)
- (set! *1 value)
- (binding [*out* *rtn*] (print (pr-str value))))
- (catch js/Error e
- (binding [*out* *err*] (print (.-stack e)))
- (set! *e e))))
-
(defn pep [log text]
(postexpr log text)
- (ep text))
+ (repl/eval-print text))
(set! (.-onload js/window) (fn []
- ;; Bootstrap an empty version of the cljs.user namespace
- (swap! comp/*emitted-provides* conj (symbol "cljs.user"))
- (.provide js/goog "cljs.user")
- (set! cljs.core/*ns-sym* (symbol "cljs.user"))
+ (repl/init)
(let [log (.getElementById js/document "log")
input (.getElementById js/document "input")
@@ -105,19 +72,16 @@
(set! (.-onkeypress input)
(fn [ev]
(when (== (.-keyCode (or ev event)) 13)
- (try
- (let [form (reader/read-string (.-value input))]
+ (let [line (.-value input)]
+ (if (repl/complete-form? line)
(do
- (pep log (.-value input))
+ (pep log line)
(js/setTimeout #(set! (.-value input) "") 0)
(set! (.-visibility (.-style status1)) "visible")
(set! (.-visibility (.-style status2)) "hidden")
- (set! (.-innerText (.getElementById js/document "ns")) (prompt))))
- (catch js/Error e
- (if (re-find #"EOF while reading" (.-message e))
- (do
- (set! (.-visibility (.-style status1)) "hidden")
- (set! (.-visibility (.-style status2)) "visible"))
- (repl-print log e "err")))))))
+ (set! (.-innerText (.getElementById js/document "ns")) (repl/prompt)))
+ (do
+ (set! (.-visibility (.-style status1)) "hidden")
+ (set! (.-visibility (.-style status2)) "visible")))))))
(.focus input))))
@@ -1,70 +1,22 @@
(ns webrepl
- (:require [cljs.analyzer :as ana]
- [cljs.compiler :as comp]
- [cljs.reader :as reader]))
-
-(def ^:dynamic *debug* false)
-(def ^:dynamic *e nil)
-
-(defn prompt [] (str *ns-sym* "=> "))
-
-(defn- read-next-form [text]
- (binding [*ns-sym* *ns-sym*]
- (reader/read-string text)))
-
-(defn evaluate-code [text]
- (try
- (let [env (assoc (ana/empty-env) :context :expr)
- form (read-next-form text)
- _ (when *debug* (println "READ:" (pr-str form)))
- body (ana/analyze env form)
- _ (when *debug* (println "ANALYZED:" (pr-str (:form body))))
- res (comp/emit-str body)
- _ (when *debug* (println "EMITTED:" (pr-str res)))
- value (js/eval res)]
- (set! *3 *2)
- (set! *2 *1)
- (set! *1 value)
- {:value value :js res})
- (catch js/Error e
- (set! *e e)
- {:error (.-stack e)})))
-
-(defn handle-input [input]
- (let [evaluated (evaluate-code input)]
- (if-let [err (and evaluated (:error evaluated))]
- (binding [*out* *err*] (print "Compilation error:" err))
- (try
- (binding [*out* *rtn*] (print (pr-str (:value evaluated))))
- (catch js/Error e
- (binding [*out* *err*] (println "Error:" err)))))))
-
-(defn complete-form? [text]
- (try
- (reader/read-string text)
- true
- (catch js/Error e
- (not (re-find #"EOF while reading" (.-message e))))))
+ (:require [cljs.repl :as repl]))
(defn start-prompt []
- (let [prompt-label (str "\n" (prompt))
+ (let [prompt-label (str "\n" (repl/prompt))
continue-label (str (apply str (repeat (- (count prompt-label) 5) " "))
"... ")]
(.SetPromptLabel js/jqconsole prompt-label continue-label)
(.Prompt js/jqconsole "true"
(fn [input]
- (handle-input input)
+ (repl/eval-print input)
(start-prompt))
- #(if (complete-form? %)
+ #(if (repl/complete-form? %)
false
0))))
(.ready (js/jQuery js/document)
(fn []
- ;; Bootstrap an empty version of the cljs.user namespace
- (swap! comp/*emitted-provides* conj (symbol "cljs.user"))
- (.provide js/goog "cljs.user")
- (set! cljs.core/*ns-sym* (symbol "cljs.user"))
+ (repl/init)
;; setup the REPL console
(set! js/jqconsole

0 comments on commit dd3c876

Please sign in to comment.