|
123 | 123 | (throw (ex-info "EvalReader not allowed when *read-eval* is false." |
124 | 124 | {:type :sci.error/parse}))) |
125 | 125 |
|
126 | | -(defn auto-resolve [ctx opts] |
127 | | - (or (:auto-resolve opts) |
128 | | - (let [env (:env ctx) |
129 | | - env-val @env |
130 | | - current-ns (utils/current-ns-name) |
131 | | - the-current-ns (get-in env-val [:namespaces current-ns]) |
132 | | - aliases (:aliases the-current-ns) |
133 | | - auto-resolve (assoc aliases :current current-ns)] |
134 | | - auto-resolve))) |
135 | | - |
136 | 126 | (defn get-line-number [reader] |
137 | 127 | (rt/get-line-number reader)) |
138 | 128 |
|
139 | 129 | (defn get-column-number [reader] |
140 | 130 | (rt/get-column-number reader)) |
141 | 131 |
|
| 132 | +(defn current-ns-auto-resolve [ctx] |
| 133 | + (fn [alias] |
| 134 | + (let [current-ns (utils/current-ns-name)] |
| 135 | + (if (utils/kw-identical? :current alias) |
| 136 | + current-ns |
| 137 | + (get-in @(:env ctx) [:namespaces current-ns :aliases alias]))))) |
| 138 | + |
| 139 | +;; The options only close over ctx: the current namespace, *read-eval* and |
| 140 | +;; the readers are read when edamame needs them, so one set of options serves |
| 141 | +;; every form of a load. |
| 142 | +(defn parse-opts [ctx opts] |
| 143 | + (cond-> (assoc default-opts |
| 144 | + :features (:features ctx) |
| 145 | + :auto-resolve (current-ns-auto-resolve ctx) |
| 146 | + :syntax-quote {:resolve-symbol #(fully-qualify ctx %)} |
| 147 | + :readers (fn [t] |
| 148 | + (let [readers (:readers ctx) |
| 149 | + readers (if (utils/var? readers) @readers readers)] |
| 150 | + (or (and readers (readers t)) |
| 151 | + (@data-readers t) |
| 152 | + (some-> (@utils/eval-resolve-state ctx {} t) |
| 153 | + meta |
| 154 | + :sci.impl.record/map-constructor) |
| 155 | + (when-let [f @default-data-reader-fn] |
| 156 | + (fn [form] |
| 157 | + (f t form)))))) |
| 158 | + :read-eval (fn [x] |
| 159 | + (if @read-eval |
| 160 | + (utils/eval ctx x) |
| 161 | + (throw-eval-read x)))) |
| 162 | + opts (merge opts))) |
| 163 | + |
| 164 | +(defn parse-next* |
| 165 | + "Parses the next form from r with options made by parse-opts." |
| 166 | + [r edamame-opts] |
| 167 | + (try (let [v (edamame/parse-next r edamame-opts)] |
| 168 | + (if (utils/kw-identical? v :edamame.core/eof) |
| 169 | + eof |
| 170 | + (if (and (symbol? v) |
| 171 | + (rt/indexing-reader? r)) |
| 172 | + (vary-meta v assoc |
| 173 | + :line (get-line-number r) |
| 174 | + :column (- (get-column-number r) |
| 175 | + #?(:cljd (.-length (str v)) |
| 176 | + :clj (.length (str v)) |
| 177 | + :cljs (.-length (str v))))) |
| 178 | + v))) |
| 179 | + (catch #?(:cljd cljd.core/ExceptionInfo |
| 180 | + :clj clojure.lang.ExceptionInfo |
| 181 | + :cljs cljs.core/ExceptionInfo) e |
| 182 | + (throw (ex-info #?(:cljd (ex-message e) |
| 183 | + :clj (.getMessage e) |
| 184 | + :cljs (.-message e)) |
| 185 | + (assoc (ex-data e) |
| 186 | + :type :sci.error/parse |
| 187 | + :phase "parse" |
| 188 | + :file @utils/current-file) |
| 189 | + e))))) |
| 190 | + |
142 | 191 | (defn parse-next |
143 | 192 | ([ctx r] |
144 | 193 | (parse-next ctx r nil)) |
145 | 194 | ([ctx r opts] |
146 | | - (let [features (:features ctx) |
147 | | - readers (:readers ctx) |
148 | | - readers (if (utils/var? readers) @readers readers) |
149 | | - auto-resolve (auto-resolve ctx opts) |
150 | | - parse-opts (cond-> (assoc default-opts |
151 | | - :features features |
152 | | - :auto-resolve auto-resolve |
153 | | - :syntax-quote {:resolve-symbol #(fully-qualify ctx %)} |
154 | | - :readers (fn [t] |
155 | | - (or (and readers (readers t)) |
156 | | - (@data-readers t) |
157 | | - (some-> (@utils/eval-resolve-state ctx {} t) |
158 | | - meta |
159 | | - :sci.impl.record/map-constructor) |
160 | | - (when-let [f @default-data-reader-fn] |
161 | | - (fn [form] |
162 | | - (f t form))))) |
163 | | - :read-eval (if @read-eval |
164 | | - (fn [x] |
165 | | - (utils/eval ctx x)) |
166 | | - throw-eval-read)) |
167 | | - opts (merge opts)) |
168 | | - ret (try (let [v (edamame/parse-next r parse-opts)] |
169 | | - (if (utils/kw-identical? v :edamame.core/eof) |
170 | | - eof |
171 | | - (if (and (symbol? v) |
172 | | - (rt/indexing-reader? r)) |
173 | | - (vary-meta v assoc |
174 | | - :line (get-line-number r) |
175 | | - :column (- (get-column-number r) |
176 | | - #?(:cljd (.-length (str v)) |
177 | | - :clj (.length (str v)) |
178 | | - :cljs (.-length (str v))))) |
179 | | - v))) |
180 | | - (catch #?(:cljd cljd.core/ExceptionInfo |
181 | | - :clj clojure.lang.ExceptionInfo |
182 | | - :cljs cljs.core/ExceptionInfo) e |
183 | | - (throw (ex-info #?(:cljd (ex-message e) |
184 | | - :clj (.getMessage e) |
185 | | - :cljs (.-message e)) |
186 | | - (assoc (ex-data e) |
187 | | - :type :sci.error/parse |
188 | | - :phase "parse" |
189 | | - :file @utils/current-file) |
190 | | - e))))] |
191 | | - ret))) |
| 195 | + (parse-next* r (parse-opts ctx opts)))) |
192 | 196 |
|
193 | 197 | (defn reader [x] |
194 | 198 | (edamame/reader x)) |
|
0 commit comments