|
7 | 7 | ; You must not remove this notice, or any other, from this software. |
8 | 8 |
|
9 | 9 | (ns cljs.js |
10 | | - (:refer-clojure :exclude [require]) |
| 10 | + (:refer-clojure :exclude [require eval]) |
11 | 11 | (:require-macros [cljs.js :refer [dump-core]] |
12 | 12 | [cljs.env.macros :as env]) |
13 | 13 | (:require [clojure.string :as string] |
|
786 | 786 | ;; ----------------------------------------------------------------------------- |
787 | 787 | ;; Eval |
788 | 788 |
|
| 789 | +(declare clear-fns!) |
| 790 | + |
789 | 791 | (defn- eval* [bound-vars form opts cb] |
790 | 792 | (let [the-ns (or (:ns opts) 'cljs.user) |
791 | 793 | bound-vars (cond-> (merge bound-vars {:*cljs-ns* the-ns}) |
792 | 794 | (:source-map opts) (assoc :*sm-data* (sm-data)))] |
| 795 | + (clear-fns!) |
793 | 796 | (binding [env/*compiler* (:*compiler* bound-vars) |
794 | 797 | *eval-fn* (:*eval-fn* bound-vars) |
795 | 798 | ana/*cljs-ns* (:*cljs-ns* bound-vars) |
|
1037 | 1040 | (:source-map opts) (assoc :*sm-data* (sm-data))) |
1038 | 1041 | aname (cond-> name (:macros-ns opts) ana/macro-ns-name)] |
1039 | 1042 | (when (:verbose opts) (debug-prn "Evaluating" name)) |
| 1043 | + (clear-fns!) |
1040 | 1044 | (trampoline |
1041 | 1045 | (fn compile-loop [ns] |
1042 | 1046 | (binding [env/*compiler* (:*compiler* bound-vars) |
|
1193 | 1197 | :*eval-fn* (or (:eval opts) *eval-fn*)} |
1194 | 1198 | source name opts cb))) |
1195 | 1199 |
|
| 1200 | +;;; Support for cljs.core/eval |
| 1201 | + |
| 1202 | +;; The following volatiles and fns set up a scheme to |
| 1203 | +;; emit function values into JavaScript as numeric |
| 1204 | +;; references that are looked up. Needed to implement eval. |
| 1205 | + |
| 1206 | +(defonce ^:private fn-index (volatile! 0)) |
| 1207 | +(defonce ^:private fn-refs (volatile! {})) |
| 1208 | + |
| 1209 | +(defn- clear-fns! |
| 1210 | + "Clears saved functions." |
| 1211 | + [] |
| 1212 | + (vreset! fn-refs {})) |
| 1213 | + |
| 1214 | +(defn- put-fn |
| 1215 | + "Saves a function, returning a numeric representation." |
| 1216 | + [f] |
| 1217 | + (let [n (vswap! fn-index inc)] |
| 1218 | + (vswap! fn-refs assoc n f) |
| 1219 | + n)) |
| 1220 | + |
| 1221 | +(defn- get-fn |
| 1222 | + "Gets a function, given its numeric representation." |
| 1223 | + [n] |
| 1224 | + (get @fn-refs n)) |
| 1225 | + |
| 1226 | +(defn- emit-fn [f] |
| 1227 | + (print "cljs.js.get_fn(" (put-fn f) ")")) |
| 1228 | + |
| 1229 | +(defmethod comp/emit-constant js/Function |
| 1230 | + [f] |
| 1231 | + (emit-fn f)) |
| 1232 | + |
| 1233 | +(defmethod comp/emit-constant cljs.core/Var |
| 1234 | + [f] |
| 1235 | + (emit-fn f)) |
| 1236 | + |
| 1237 | +(defn- eval-impl |
| 1238 | + ([form] |
| 1239 | + (eval-impl form (.-name *ns*))) |
| 1240 | + ([form ns] |
| 1241 | + (let [result (atom nil)] |
| 1242 | + (let [st env/*compiler*] |
| 1243 | + (eval st form |
| 1244 | + {:ns ns |
| 1245 | + :context :expr |
| 1246 | + :def-emits-var true} |
| 1247 | + (fn [{:keys [value error]}] |
| 1248 | + (if error |
| 1249 | + (throw error) |
| 1250 | + (reset! result value))))) |
| 1251 | + @result))) |
| 1252 | + |
| 1253 | +(set! *eval* eval-impl) |
| 1254 | + |
1196 | 1255 | (comment |
1197 | 1256 | (require '[cljs.js :as cljs] |
1198 | 1257 | '[cljs.analyzer :as ana]) |
|
0 commit comments