|
67 | 67 | ;;; This is incomplete, it disallows unicode |
68 | 68 | (boolean (re-matches #"[_$\p{Alpha}][.\w]*" (str sym)))) |
69 | 69 |
|
| 70 | +;; TODO: move to context argument |
| 71 | +(def ^:dynamic *imported-core-vars* (atom #{})) |
| 72 | + |
70 | 73 | (defmethod emit clojure.lang.Keyword [expr] |
71 | 74 | (when-not (valid-symbol? (name expr)) |
72 | 75 | (#'throwf "%s is not a valid javascript symbol" expr)) |
73 | | - (str (name expr))) |
| 76 | + (swap! *imported-core-vars* conj 'keyword) |
| 77 | + (str (format "keyword(%s)" (pr-str (subs (str expr) 1))))) |
74 | 78 |
|
75 | 79 | (defmethod emit clojure.lang.Symbol [expr] |
76 | 80 | (let [expr (if (and (qualified-symbol? expr) |
77 | 81 | (= "js" (namespace expr))) |
78 | 82 | (name expr) |
79 | | - expr)] |
| 83 | + expr) |
| 84 | + expr (symbol (munge expr))] |
80 | 85 | (when-not (valid-symbol? (str expr)) |
81 | 86 | (#' throwf "%s is not a valid javascript symbol" expr)) |
82 | 87 | (str expr))) |
|
89 | 94 |
|
90 | 95 | (def special-forms (set ['var '. '.. 'if 'funcall 'fn 'quote 'set! |
91 | 96 | 'return 'delete 'new 'do 'aget 'while 'doseq |
92 | | - 'str 'inc! 'dec! 'dec 'inc 'defined? 'and 'or |
| 97 | + 'inc! 'dec! 'dec 'inc 'defined? 'and 'or |
93 | 98 | '? 'try 'break |
94 | 99 | 'await 'const 'defn 'let 'ns 'def])) |
95 | 100 |
|
| 101 | +(def core-vars (set '[map assoc str keyword symbol |
| 102 | + dissoc conj vector clj->js js->clj get])) |
| 103 | + |
| 104 | +(def core->js '{clj->js toJs |
| 105 | + js->cljs toCljs}) |
| 106 | + |
96 | 107 | (def prefix-unary-operators (set ['!])) |
97 | 108 |
|
98 | 109 | (def suffix-unary-operators (set ['++ '--])) |
|
183 | 194 | ;; TODO |
184 | 195 | ) |
185 | 196 |
|
186 | | -(defmethod emit-special 'funcall [type [name & args]] |
| 197 | +(defmethod emit-special 'funcall [_type [name & args]] |
187 | 198 | (str (if (and (list? name) (= 'fn (first name))) ; function literal call |
188 | 199 | (str "(" (emit name) ")") |
189 | | - (emit name)) |
| 200 | + (let [name |
| 201 | + (if (contains? core-vars name) |
| 202 | + (let [name (get core->js name name)] |
| 203 | + (swap! *imported-core-vars* conj name) |
| 204 | + name) |
| 205 | + name)] |
| 206 | + (emit name))) |
190 | 207 | (comma-list (map emit args)))) |
191 | 208 |
|
192 | 209 | (defmethod emit-special 'str [type [str & args]] |
|
484 | 501 | (recur (str transpiled next-js)))))))) |
485 | 502 |
|
486 | 503 | (defn transpile-file [{:keys [in-file out-file]}] |
487 | | - (let [out-file (or out-file |
488 | | - (str/replace in-file #".cljs$" ".mjs"))] |
489 | | - (spit out-file (transpile-string (slurp in-file))) |
490 | | - {:out-file out-file})) |
| 504 | + (let [core-vars (atom #{})] |
| 505 | + (binding [*imported-core-vars* core-vars] |
| 506 | + (let [out-file (or out-file |
| 507 | + (str/replace in-file #".cljs$" ".mjs")) |
| 508 | + transpiled (transpile-string (slurp in-file)) |
| 509 | + transpiled (if-let [core-vars (seq @core-vars)] |
| 510 | + (str (format "import { %s } from 'cherry-cljs/cljs.core.js'\n\n" |
| 511 | + (str/join ", " core-vars)) |
| 512 | + transpiled) |
| 513 | + transpiled)] |
| 514 | + (spit out-file transpiled) |
| 515 | + {:out-file out-file})))) |
0 commit comments