From 252b9af3587ce29ea36d57f661d9dadaedb52a42 Mon Sep 17 00:00:00 2001 From: Scott Richmond Date: Thu, 30 Nov 2023 13:22:38 -0500 Subject: [PATCH] Add `use` to language --- src/ludus/grammar.cljc | 2 +- src/ludus/interpreter.cljc | 47 ++++++++++++++++++++++++++++++++++++++ src/ludus/scanner.cljc | 1 + 3 files changed, 49 insertions(+), 1 deletion(-) diff --git a/src/ludus/grammar.cljc b/src/ludus/grammar.cljc index d1f15d2..eb083b3 100644 --- a/src/ludus/grammar.cljc +++ b/src/ludus/grammar.cljc @@ -251,7 +251,7 @@ (zero+ struct-entry) (quiet :rbrace)]) -(defp use-expr group order-1 [:use :word]) +(defp use-expr group order-1 [(quiet :use) :word]) (defp toplevel flat choice [import-expr ns-expr diff --git a/src/ludus/interpreter.cljc b/src/ludus/interpreter.cljc index 19a100b..cd907ef 100644 --- a/src/ludus/interpreter.cljc +++ b/src/ludus/interpreter.cljc @@ -613,6 +613,27 @@ ; interpret-result)) ; )))) +(defn- kw->str [kw] (apply str (rest (str kw)))) + +(defn- str->word [wordstr] {:type :word :data [wordstr]}) + +(defn- interpret-use [ast ctx] + (let [data (:data ast) + word (first data) + ns (resolve-word word ctx)] + (println "use: " ns) + (if (not (= (::data/type ns) ::data/ns)) + (throw (ex-info (str "`use` may only use namespaces; " (-> word :data first) " is not a namespace") {:ast ast})) + (let [ns-entries (dissoc ns ::data/type ::data/name ::data/struct) + ns-keys (map kw->str (keys ns-entries)) + ns-words (map str->word ns-keys) + implied-pattern {:type :struct-pattern :data ns-words} + sugared-let {:type :let-expr :data [implied-pattern ns]}] + (interpret-let sugared-let ctx) + ) + ) + )) + (defn- interpret-ref [ast ctx] (let [data (:data ast) name (-> data first :data first) @@ -779,6 +800,8 @@ :ns-expr (interpret-ns ast ctx) + :use-expr (interpret-use ast ctx) + ;; :import-expr (interpret-import ast ctx) :ref-expr (interpret-ref ast ctx) @@ -885,3 +908,27 @@ (println "Ludus panicked!") (println (ex-message e)) {:result :error :ctx (volatile! orig-ctx)}))))) + +(defn interpret-safe [source parsed ctx] + (try + (let [base-ctx (volatile! {::parent (volatile! (merge prelude/prelude ctx))})] + (interpret-ast parsed base-ctx)) + (catch Throwable e + (println "Ludus panicked!") + (println "On line" (get-in (ex-data e) [:ast :token :line])) + (println ">>> " (get-line source (get-in (ex-data e) [:ast :token :line]))) + (println (ex-message e)) + (pp/pprint (ex-data e) + )))) + +;; repl +(do + + (def source "@{foo}") + + (def tokens (-> source scanner/scan :tokens)) + + (def ast (p/apply-parser g/struct-pattern tokens)) + (println ast) + ;; (interpret-safe source ast {}) + ) \ No newline at end of file diff --git a/src/ludus/scanner.cljc b/src/ludus/scanner.cljc index 8095cfb..29dad67 100644 --- a/src/ludus/scanner.cljc +++ b/src/ludus/scanner.cljc @@ -25,6 +25,7 @@ "ref" :ref ;; impl "then" :then ;; impl "true" :true ;; impl -> literal word + "use" :use ;; wip "with" :with ;; impl "when" :when ;; impl, replaces cond