|
139 | 139 | (str "Could not resolve symbol: " sym "\nks:" (keys (:bindings ctx)))
|
140 | 140 | sym))))
|
141 | 141 |
|
142 |
| -(defn parse-libspec [libspec] |
143 |
| - (cond |
144 |
| - (sequential? libspec) |
145 |
| - (let [[lib-name & opts] libspec] |
146 |
| - (loop [ret {:lib-name lib-name} |
147 |
| - [opt-name fst-opt & rst-opts] opts] |
148 |
| - (if-not opt-name ret |
149 |
| - (case opt-name |
150 |
| - :as (recur (assoc ret :as fst-opt) |
151 |
| - rst-opts) |
152 |
| - (:reload :reload-all :verbose) (recur |
153 |
| - (assoc ret :reload true) |
154 |
| - (cons fst-opt rst-opts)) |
155 |
| - (:refer :rename :exclude :only) (recur (assoc ret opt-name fst-opt) |
156 |
| - rst-opts))))) |
157 |
| - (symbol? libspec) {:lib-name libspec} |
158 |
| - :else (throw (new #?(:clj Exception :cljs js/Error) |
159 |
| - (str "Invalid libspec: " libspec))))) |
160 |
| - |
161 | 142 | (declare eval-string*)
|
162 | 143 |
|
163 | 144 | (defn handle-refer-all [the-current-ns the-loaded-ns include-sym? rename-sym only]
|
|
172 | 153 | the-loaded-ns)))
|
173 | 154 |
|
174 | 155 | (defn handle-require-libspec-env
|
175 |
| - [ctx env use? current-ns the-loaded-ns lib-name |
176 |
| - {:keys [:as :refer :rename :exclude :only] :as _parsed-libspec}] |
| 156 | + [ctx env current-ns the-loaded-ns lib-name |
| 157 | + {:keys [:as :refer :rename :exclude :only :use] :as _parsed-libspec}] |
177 | 158 | (let [the-current-ns (get-in env [:namespaces current-ns]) ;; = ns-data?
|
178 | 159 | the-current-ns (if as (assoc-in the-current-ns [:aliases as] lib-name)
|
179 | 160 | the-current-ns)
|
|
187 | 168 | the-current-ns
|
188 | 169 | (cond refer
|
189 | 170 | (cond (or (kw-identical? :all refer)
|
190 |
| - use?) |
| 171 | + use) |
191 | 172 | (handle-refer-all the-current-ns the-loaded-ns include-sym? rename-sym nil)
|
192 | 173 | (sequential? refer)
|
193 | 174 | (reduce (fn [ns sym]
|
|
203 | 184 | refer)
|
204 | 185 | :else (throw (new #?(:clj Exception :cljs js/Error)
|
205 | 186 | (str ":refer value must be a sequential collection of symbols"))))
|
206 |
| - use? (handle-refer-all the-current-ns the-loaded-ns include-sym? rename-sym only) |
| 187 | + use (handle-refer-all the-current-ns the-loaded-ns include-sym? rename-sym only) |
207 | 188 | :else the-current-ns)
|
208 | 189 | env (assoc-in env [:namespaces current-ns] the-current-ns)]
|
209 | 190 | (when-let [on-loaded (some-> the-loaded-ns :obj meta :sci.impl/required-fn)]
|
210 | 191 | (on-loaded {}))
|
211 | 192 | env))
|
212 | 193 |
|
213 | 194 | (defn handle-require-libspec
|
214 |
| - [ctx libspec use?] |
215 |
| - (let [{:keys [:lib-name :reload] :as parsed-libspec} (parse-libspec libspec) |
| 195 | + [ctx lib opts] |
| 196 | + (let [{:keys [:reload]} opts |
216 | 197 | env* (:env ctx)
|
217 | 198 | env @env* ;; NOTE: loading namespaces is not (yet) thread-safe
|
218 | 199 | cnn (vars/current-ns-name)
|
219 | 200 | namespaces (get env :namespaces)
|
220 | 201 | uberscript (:uberscript ctx)
|
221 | 202 | reload* (or reload uberscript)]
|
222 |
| - (if-let [the-loaded-ns (when-not reload* (get namespaces lib-name))] |
223 |
| - (reset! env* (handle-require-libspec-env ctx env use? cnn the-loaded-ns lib-name parsed-libspec)) |
| 203 | + (if-let [the-loaded-ns (when-not reload* (get namespaces lib))] |
| 204 | + (reset! env* (handle-require-libspec-env ctx env cnn the-loaded-ns lib opts)) |
224 | 205 | (if-let [load-fn (:load-fn env)]
|
225 |
| - (if-let [{:keys [:file :source]} (load-fn {:namespace lib-name |
| 206 | + (if-let [{:keys [:file :source]} (load-fn {:namespace lib |
226 | 207 | :reload reload})]
|
227 | 208 | (do
|
228 | 209 | (try (vars/with-bindings
|
229 | 210 | {vars/current-ns @vars/current-ns
|
230 | 211 | vars/current-file file}
|
231 | 212 | (eval-string* (assoc ctx :bindings {}) source))
|
232 | 213 | (catch #?(:clj Exception :cljs js/Error) e
|
233 |
| - (swap! env* update :namespaces dissoc lib-name) |
| 214 | + (swap! env* update :namespaces dissoc lib) |
234 | 215 | (throw e)))
|
235 | 216 | (swap! env* (fn [env]
|
236 | 217 | (let [namespaces (get env :namespaces)
|
237 |
| - the-loaded-ns (get namespaces lib-name)] |
238 |
| - (handle-require-libspec-env ctx env use? cnn |
| 218 | + the-loaded-ns (get namespaces lib)] |
| 219 | + (handle-require-libspec-env ctx env cnn |
239 | 220 | the-loaded-ns
|
240 |
| - lib-name parsed-libspec))))) |
| 221 | + lib opts))))) |
241 | 222 | (or (when reload*
|
242 |
| - (when-let [the-loaded-ns (get namespaces lib-name)] |
243 |
| - (reset! env* (handle-require-libspec-env ctx env use? cnn the-loaded-ns lib-name parsed-libspec)))) |
| 223 | + (when-let [the-loaded-ns (get namespaces lib)] |
| 224 | + (reset! env* (handle-require-libspec-env ctx env cnn the-loaded-ns lib opts)))) |
244 | 225 | (throw (new #?(:clj Exception :cljs js/Error)
|
245 |
| - (str "Could not find namespace: " lib-name "."))))) |
| 226 | + (str "Could not find namespace: " lib "."))))) |
246 | 227 | (throw (new #?(:clj Exception :cljs js/Error)
|
247 |
| - (str "Could not find namespace " lib-name "."))))))) |
248 |
| - |
249 |
| -(defn eval-require* |
250 |
| - [ctx args use?] |
251 |
| - (loop [libspecs [] |
252 |
| - current-libspec nil |
253 |
| - args args] |
254 |
| - (if args |
255 |
| - (let [ret (interpret ctx (first args))] |
256 |
| - (cond |
257 |
| - (symbol? ret) |
258 |
| - (recur (cond-> libspecs |
259 |
| - current-libspec (conj current-libspec)) |
260 |
| - [ret] |
261 |
| - (next args)) |
262 |
| - (keyword? ret) |
263 |
| - (recur (conj libspecs (conj current-libspec ret)) |
264 |
| - nil |
265 |
| - (next args)) |
266 |
| - :else |
267 |
| - (recur (cond-> libspecs |
268 |
| - current-libspec (conj current-libspec)) |
269 |
| - ret |
270 |
| - (next args)))) |
271 |
| - (let [libspecs (cond-> libspecs |
272 |
| - current-libspec (conj current-libspec))] |
273 |
| - (run! #(handle-require-libspec ctx % use?) libspecs))))) |
| 228 | + |
| 229 | + (str "Could not find namespace " lib "."))))))) |
| 230 | + |
| 231 | +(defn load-lib [ctx prefix lib & options] |
| 232 | + (when (and prefix (pos? (.indexOf (name lib) #?(:clj (int \.) |
| 233 | + :cljs \.)))) |
| 234 | + (throw-error-with-location (str "Found lib name '" (name lib) "' containing period with prefix '" |
| 235 | + prefix "'. lib names inside prefix lists must not contain periods") |
| 236 | + lib)) |
| 237 | + (let [lib (if prefix (symbol (str prefix \. lib)) lib) |
| 238 | + opts (apply hash-map options)] |
| 239 | + (handle-require-libspec ctx lib opts))) |
| 240 | + |
| 241 | +(defn- prependss |
| 242 | + "Prepends a symbol or a seq to coll" |
| 243 | + [x coll] |
| 244 | + (if (symbol? x) |
| 245 | + (cons x coll) |
| 246 | + (concat x coll))) |
| 247 | + |
| 248 | +(defn- libspec? |
| 249 | + "Returns true if x is a libspec" |
| 250 | + [x] |
| 251 | + (or (symbol? x) |
| 252 | + (and (vector? x) |
| 253 | + (or |
| 254 | + (nil? (second x)) |
| 255 | + (keyword? (second x)))))) |
| 256 | + |
| 257 | +(defn- load-libs |
| 258 | + "Loads libs, interpreting libspecs, prefix lists, and flags for |
| 259 | + forwarding to load-lib" |
| 260 | + [ctx kw args] |
| 261 | + (let [args* (cons kw args) |
| 262 | + flags (filter keyword? args*) |
| 263 | + opts (interleave flags (repeat true)) |
| 264 | + args* (filter (complement keyword?) args*)] |
| 265 | + ;; check for unsupported options |
| 266 | + (let [supported #{:as :reload :reload-all :require :use :verbose :refer} |
| 267 | + unsupported (seq (remove supported flags))] |
| 268 | + (when unsupported |
| 269 | + (throw-error-with-location (apply str "Unsupported option(s) supplied: " |
| 270 | + (interpose \, unsupported)) |
| 271 | + ;; best effort location |
| 272 | + args))) |
| 273 | + ;; check a load target was specified |
| 274 | + (when-not (seq args*) |
| 275 | + (throw-error-with-location "Nothing specified to load" |
| 276 | + args)) |
| 277 | + (doseq [arg args*] |
| 278 | + (if (libspec? arg) |
| 279 | + (apply load-lib ctx nil (prependss arg opts)) |
| 280 | + (let [[prefix & args*] arg] |
| 281 | + (when (nil? prefix) |
| 282 | + (throw-error-with-location "prefix cannot be nil" |
| 283 | + args)) |
| 284 | + (doseq [arg args*] |
| 285 | + (apply load-lib ctx prefix (prependss arg opts)))))))) |
274 | 286 |
|
275 | 287 | (defn eval-require
|
276 | 288 | [ctx & args]
|
277 |
| - (eval-require* ctx args false)) |
| 289 | + (load-libs ctx :require args)) |
278 | 290 |
|
279 | 291 | (vreset! utils/eval-require-state eval-require)
|
280 | 292 |
|
281 | 293 | (defn eval-use
|
282 | 294 | [ctx & args]
|
283 |
| - (eval-require* ctx args true)) |
| 295 | + (load-libs ctx :use args)) |
284 | 296 |
|
285 | 297 | (vreset! utils/eval-use-state eval-use)
|
286 | 298 |
|
|
567 | 579 | in-ns (eval-in-ns ctx expr)
|
568 | 580 | set! (eval-set! ctx expr)
|
569 | 581 | refer (apply eval-refer ctx (rest expr))
|
570 |
| - require (apply eval-require ctx (rest expr)) |
571 |
| - use (apply eval-use ctx (rest expr)) |
| 582 | + require (apply eval-require ctx (with-meta (rest expr) |
| 583 | + (meta expr))) |
| 584 | + use (apply eval-use ctx (with-meta (rest expr) |
| 585 | + (meta expr))) |
572 | 586 | resolve (eval-resolve ctx (second expr))
|
573 | 587 | macroexpand-1 (macroexpand-1 ctx (interpret ctx (second expr)))
|
574 | 588 | macroexpand (macroexpand ctx (interpret ctx (second expr)))
|
|
0 commit comments