Skip to content

Commit

Permalink
Factor out common REPL code to cljs/cljs/repl.cljs
Browse files Browse the repository at this point in the history
Also get nodecljs.cljs working using repl.cljs and add example
shebang.cljs which can be executed directly.
  • Loading branch information
kanaka committed Feb 17, 2013
1 parent 1c1496a commit dd3c876
Show file tree
Hide file tree
Showing 6 changed files with 96 additions and 172 deletions.
10 changes: 10 additions & 0 deletions node/shebang.cljs
@@ -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
48 changes: 48 additions & 0 deletions src/cljs/cljs/repl.cljs
@@ -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")))

38 changes: 11 additions & 27 deletions src/cljs/nodecljs.cljs
@@ -1,37 +1,21 @@
(ns nodecljs (ns nodecljs
(:require [cljs.core] (:require [cljs.repl :as repl]))
[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))))))


(defn -main [file & args] (defn -main [file & args]
(repl/init)

;; Setup the print function ;; Setup the print function
(set! *out* (.-write (.-stdout js/process))) (set! *out* #(.write (.-stdout js/process) %))
(set! *err* (.-write (.-stderr js/process))) (set! *rtn* identity)
(set! *err* #(.write (.-stderr js/process) %))
(set! *print-fn* #(*out* %1)) (set! *print-fn* #(*out* %1))


;; Bootstrap an empty version of the cljs.user namespace ;(set! repl/*debug* true)
(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))
(let [fs (js/require "fs") (let [fs (js/require "fs")
text (.toString (.readFileSync fs file))] text (.toString (.readFileSync fs file))
(ep text))) res (repl/eval-print text)
ret (:value res)]
(.exit js/process (if (number? ret) ret 0))))


(set! *main-cli-fn* -main) (set! *main-cli-fn* -main)


56 changes: 11 additions & 45 deletions src/cljs/noderepl.cljs
@@ -1,53 +1,17 @@
(ns noderepl (ns noderepl
(:require [cljs.core] (:require [cljs.repl :as repl]))
[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))))


(defn pep [text] (defn pep [text]
(postexpr text) (println (str (repl/prompt) text))
(ep text)) (repl/eval-print text)
(println))


(defn -main [& args] (defn -main [& args]
;; Bootstrap an empty version of the cljs.user namespace (repl/init)
(swap! comp/*emitted-provides* conj (symbol "cljs.user"))
(.provide js/goog "cljs.user")
(set! cljs.core/*ns-sym* (symbol "cljs.user"))


;; Setup the print function ;; Setup the print function
(set! *out* #(.write (.-stdout js/process) %)) (set! *out* #(.write (.-stdout js/process) %))
(set! *rtn* #(.write (.-stdout js/process) %))
(set! *err* #(.write (.-stderr js/process) %)) (set! *err* #(.write (.-stderr js/process) %))
(set! *print-fn* #(*out* %)) (set! *print-fn* #(*out* %))


Expand All @@ -59,14 +23,16 @@
(pep "(sqr 8)") (pep "(sqr 8)")
(pep "(defmacro unless [pred a b] `(if (not ~pred) ~a ~b))") (pep "(defmacro unless [pred a b] `(if (not ~pred) ~a ~b))")
(pep "(unless false :yep :nope)") (pep "(unless false :yep :nope)")

(let [readline (js/require "readline") (let [readline (js/require "readline")
rl (.createInterface readline js/process.stdin js/process.stdout)] rl (.createInterface readline js/process.stdin js/process.stdout)]
(.setPrompt rl (prompt)) (.setPrompt rl (repl/prompt))
(.prompt rl) (.prompt rl)
(.on rl "line" (fn [line] (.on rl "line" (fn [line]
(when (seq (filter #(not= " " %) line)) (when (seq (filter #(not= " " %) line))
(ep line)) (repl/eval-print line)
(.setPrompt rl (prompt)) (println))
(.setPrompt rl (repl/prompt))
(.prompt rl))) (.prompt rl)))
(.on rl "close" (fn [] (.exit js/process 0))))) (.on rl "close" (fn [] (.exit js/process 0)))))


Expand Down
58 changes: 11 additions & 47 deletions src/cljs/webrepl.cljs
@@ -1,13 +1,5 @@
(ns webrepl (ns webrepl
(:require [cljs.core] (:require [cljs.repl :as repl]))
[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* "=> "))


(def append-dom) (def append-dom)


Expand Down Expand Up @@ -38,45 +30,20 @@
line])) line]))
(set! (.-scrollTop log) (.-scrollHeight log))) (set! (.-scrollTop log) (.-scrollHeight log)))


(defn- read-next-form [text]
(binding [*ns-sym* *ns-sym*]
(reader/read-string text)))

(defn postexpr [log text] (defn postexpr [log text]
(append-dom log (append-dom log
[:table [:table
[:tbody [:tbody
[:tr [:tr
[:td {:class "cg"} (prompt)] [:td {:class "cg"} (repl/prompt)]
[:td (.replace text #"\n$" "")]]]])) [: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] (defn pep [log text]
(postexpr log text) (postexpr log text)
(ep text)) (repl/eval-print text))


(set! (.-onload js/window) (fn [] (set! (.-onload js/window) (fn []
;; Bootstrap an empty version of the cljs.user namespace (repl/init)
(swap! comp/*emitted-provides* conj (symbol "cljs.user"))
(.provide js/goog "cljs.user")
(set! cljs.core/*ns-sym* (symbol "cljs.user"))


(let [log (.getElementById js/document "log") (let [log (.getElementById js/document "log")
input (.getElementById js/document "input") input (.getElementById js/document "input")
Expand Down Expand Up @@ -105,19 +72,16 @@
(set! (.-onkeypress input) (set! (.-onkeypress input)
(fn [ev] (fn [ev]
(when (== (.-keyCode (or ev event)) 13) (when (== (.-keyCode (or ev event)) 13)
(try (let [line (.-value input)]
(let [form (reader/read-string (.-value input))] (if (repl/complete-form? line)
(do (do
(pep log (.-value input)) (pep log line)
(js/setTimeout #(set! (.-value input) "") 0) (js/setTimeout #(set! (.-value input) "") 0)
(set! (.-visibility (.-style status1)) "visible") (set! (.-visibility (.-style status1)) "visible")
(set! (.-visibility (.-style status2)) "hidden") (set! (.-visibility (.-style status2)) "hidden")
(set! (.-innerText (.getElementById js/document "ns")) (prompt)))) (set! (.-innerText (.getElementById js/document "ns")) (repl/prompt)))
(catch js/Error e (do
(if (re-find #"EOF while reading" (.-message e)) (set! (.-visibility (.-style status1)) "hidden")
(do (set! (.-visibility (.-style status2)) "visible")))))))
(set! (.-visibility (.-style status1)) "hidden")
(set! (.-visibility (.-style status2)) "visible"))
(repl-print log e "err")))))))


(.focus input)))) (.focus input))))
58 changes: 5 additions & 53 deletions src/cljs/webrepl2.cljs
@@ -1,70 +1,22 @@
(ns webrepl (ns webrepl
(:require [cljs.analyzer :as ana] (:require [cljs.repl :as repl]))
[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))))))


(defn start-prompt [] (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) " ")) continue-label (str (apply str (repeat (- (count prompt-label) 5) " "))
"... ")] "... ")]
(.SetPromptLabel js/jqconsole prompt-label continue-label) (.SetPromptLabel js/jqconsole prompt-label continue-label)
(.Prompt js/jqconsole "true" (.Prompt js/jqconsole "true"
(fn [input] (fn [input]
(handle-input input) (repl/eval-print input)
(start-prompt)) (start-prompt))
#(if (complete-form? %) #(if (repl/complete-form? %)
false false
0)))) 0))))


(.ready (js/jQuery js/document) (.ready (js/jQuery js/document)
(fn [] (fn []
;; Bootstrap an empty version of the cljs.user namespace (repl/init)
(swap! comp/*emitted-provides* conj (symbol "cljs.user"))
(.provide js/goog "cljs.user")
(set! cljs.core/*ns-sym* (symbol "cljs.user"))


;; setup the REPL console ;; setup the REPL console
(set! js/jqconsole (set! js/jqconsole
Expand Down

0 comments on commit dd3c876

Please sign in to comment.