|
6 | 6 | [sci.impl.functions :as f]
|
7 | 7 | [clojure.string :as str]))
|
8 | 8 |
|
9 |
| -(def macros '#{do if when and or -> ->> as-> quote let fn def defn}) |
| 9 | +(def macros '#{do if when and or -> ->> as-> quote quote* let fn def defn}) |
10 | 10 |
|
11 | 11 | (defn lookup [{:keys [:env :bindings]} sym]
|
12 |
| - (when-let [[k v :as kv] |
13 |
| - (or (when-let [v (get macros sym)] |
14 |
| - [v v]) |
15 |
| - (find bindings sym) |
16 |
| - (find @env sym) |
17 |
| - (find f/functions sym) |
18 |
| - (when-let [ns (namespace sym)] |
19 |
| - (when (or (= "clojure.core" ns) |
20 |
| - (= "cljs.core" ns)) |
21 |
| - (find f/functions (symbol (name sym))))))] |
22 |
| - (if-let [m (meta k)] |
23 |
| - (if (:sci/deref! m) |
24 |
| - ;; the evaluation of this expression has been delayed by |
25 |
| - ;; the caller and now is the time to deref it |
26 |
| - [k @v] kv) |
27 |
| - kv))) |
| 12 | + (let [res (or (when-let [v (get macros sym)] |
| 13 | + [v v]) |
| 14 | + (when-let [[k _v] |
| 15 | + (find bindings sym)] |
| 16 | + ;; never inline a binding at macro time! |
| 17 | + [k nil]) |
| 18 | + (find @env sym) |
| 19 | + (find f/functions sym) |
| 20 | + (when-let [ns (namespace sym)] |
| 21 | + (when (or (= "clojure.core" ns) |
| 22 | + (= "cljs.core" ns)) |
| 23 | + (find f/functions (symbol (name sym))))))] |
| 24 | + ;; (prn 'lookup sym '-> res) |
| 25 | + res)) |
28 | 26 |
|
29 | 27 | (defn resolve-symbol [ctx expr]
|
30 |
| - ;; (prn "resolve sym" expr) |
31 |
| - (second |
32 |
| - (or |
33 |
| - (lookup ctx expr) |
34 |
| - ;; TODO: check if symbol is in macros and then emit an error: cannot take |
35 |
| - ;; the value of a macro |
36 |
| - (let [n (name expr)] |
37 |
| - (if (str/starts-with? n "'") |
38 |
| - (let [v (symbol (subs n 1))] |
39 |
| - [v v]) |
40 |
| - (throw (new #?(:clj Exception |
41 |
| - :cljs js/Error) |
42 |
| - (str "Could not resolve symbol: " (str expr) |
43 |
| - (keys (:bindings expr)))))))))) |
| 28 | + (let [res (second |
| 29 | + (or |
| 30 | + (lookup ctx expr) |
| 31 | + ;; TODO: check if symbol is in macros and then emit an error: cannot take |
| 32 | + ;; the value of a macro |
| 33 | + (let [n (name expr)] |
| 34 | + (if (str/starts-with? n "'") |
| 35 | + (let [v (symbol (subs n 1))] |
| 36 | + [v v]) |
| 37 | + (throw (new #?(:clj Exception |
| 38 | + :cljs js/Error) |
| 39 | + (str "Could not resolve symbol: " (str expr) |
| 40 | + (keys (:bindings expr)))))))))] |
| 41 | + ;; (prn 'resolve expr '-> res) |
| 42 | + res)) |
44 | 43 |
|
45 | 44 | (declare macroexpand macroexpand-1)
|
46 | 45 |
|
|
202 | 201 | (swap! (:env ctx) assoc var-name :sci/var.unbound)
|
203 | 202 | (list 'def var-name init)))
|
204 | 203 |
|
205 |
| - |
206 | 204 | (defn expand-defn [ctx [_defn fn-name docstring? & body]]
|
207 | 205 | (let [docstring (when (string? docstring?) docstring?)
|
208 | 206 | body (if docstring body (cons docstring? body))
|
|
218 | 216 | (:sci/fn expr) expr
|
219 | 217 | (symbol? expr)
|
220 | 218 | (or (let [v (resolve-symbol ctx expr)]
|
221 |
| - (when-not (identical? :sci/var.unbound v))) |
| 219 | + (when-not (identical? :sci/var.unbound v) |
| 220 | + v)) |
222 | 221 | expr)
|
223 | 222 | (map? expr)
|
224 | 223 | (zipmap (map #(macroexpand ctx %) (keys expr))
|
|
227 | 226 | (into (empty expr) (map #(macroexpand ctx %) expr))
|
228 | 227 | (seq? expr)
|
229 | 228 | (if-let [f (first expr)]
|
230 |
| - (case f |
231 |
| - do expr ;; do will call macroexpand on every subsequent expression |
232 |
| - let |
233 |
| - (expand-let ctx expr) |
234 |
| - (fn fn*) (expand-fn ctx expr) |
235 |
| - quote expr |
236 |
| - def (expand-def ctx expr) |
237 |
| - defn (expand-defn ctx expr) |
238 |
| - -> (expand-> ctx (rest expr)) |
239 |
| - ->> (expand->> ctx (rest expr)) |
240 |
| - as-> (expand-as-> ctx expr) |
241 |
| - ;; else: |
| 229 | + (if (symbol? f) |
| 230 | + (let [f (if-let [ns (namespace f)] |
| 231 | + (if (or (= "clojure.core" ns) |
| 232 | + (= "cljs.core" ns)) |
| 233 | + (symbol (name f)) |
| 234 | + f) |
| 235 | + f)] |
| 236 | + (case f |
| 237 | + do expr ;; do will call macroexpand on every subsequent expression |
| 238 | + let |
| 239 | + (expand-let ctx expr) |
| 240 | + (fn fn*) (expand-fn ctx expr) |
| 241 | + quote expr |
| 242 | + def (expand-def ctx expr) |
| 243 | + defn (expand-defn ctx expr) |
| 244 | + -> (expand-> ctx (rest expr)) |
| 245 | + ->> (expand->> ctx (rest expr)) |
| 246 | + as-> (expand-as-> ctx expr) |
| 247 | + ;; else: |
| 248 | + (doall (map #(macroexpand ctx %) expr)))) |
242 | 249 | (doall (map #(macroexpand ctx %) expr)))
|
243 | 250 | expr)
|
244 | 251 | :else expr)]
|
245 |
| - ;; (prn expr (meta expr) '-> res) |
246 | 252 | res))
|
247 | 253 |
|
248 | 254 | ;;;; Scratch
|
|
0 commit comments