001  (ns beowulf.core
002    (:require [beowulf.bootstrap :refer [EVAL oblist *options*]]
003              [beowulf.read :refer [READ]]
004              [clojure.java.io :as io]
005              [clojure.pprint :refer [pprint]]
006              [clojure.tools.cli :refer [parse-opts]]
007              [environ.core :refer [env]])
008    (:gen-class))
009  
010  (def cli-options
011    [["-h" "--help"]
012     ["-p PROMPT" "--prompt PROMPT" "Set the REPL prompt to PROMPT"
013      :default "Sprecan::"]
014     ["-r INITFILE" "--read INITFILE" "Read Lisp functions from the file INITFILE"
015      :validate [#(and
016                    (.exists (io/file %))
017                    (.canRead (io/file %)))
018                 "Could not find initfile"]]
019     ["-s" "--strict" "Strictly interpret the Lisp 1.5 language, without extensions."]
020     ["-t" "--trace" "Trace Lisp evaluation."]])
021  
022  (defn repl
023    "Read/eval/print loop."
024    [prompt]
025    (loop []
026      (print prompt)
027      (flush)
028      (try
029        (let [input (read-line)]
030          (cond
031            (= input "quit") (throw (ex-info "\nFærwell!" {:cause :quit}))
032            input (println (str ">  " (print-str (EVAL (READ input) @oblist))))
033            :else (println)))
034        (catch
035          Exception
036          e
037          (let [data (ex-data e)]
038            (println (.getMessage e))
039            (if
040              data
041              (case (:cause data)
042                :parse-failure (println (:failure data))
043                :strict nil ;; the message, which has already been printed, is enough.
044                :quit (throw e)
045                ;; default
046                (pprint data))))))
047      (recur)))
048  
049  (defn -main
050    [& opts]
051    (let [args (parse-opts opts cli-options)]
052      (println
053        (str
054          "\nHider wilcuman. Béowulf is mín nama.\n"
055          (if
056            (System/getProperty "beowulf.version")
057            (str "Síðe " (System/getProperty "beowulf.version") "\n"))
058          (if
059            (:help (:options args))
060            (:summary args))
061          (if (:errors args)
062            (apply str (interpose "; " (:errors args))))
063          "\nSprecan 'quit' tó laéfan\n"))
064      (binding [*options* (:options args)]
065        (try
066          (repl (str (:prompt (:options args)) " "))
067          (catch
068            Exception
069            e
070            (let [data (ex-data e)]
071              (if
072                data
073                (case (:cause data)
074                  :quit nil
075                  ;; default
076                  (pprint data))
077                (println e))))))))