clementine 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (139) hide show
  1. data/.gitignore +1 -0
  2. data/Gemfile +4 -2
  3. data/LICENSE.txt +22 -0
  4. data/README.md +11 -6
  5. data/Rakefile +22 -0
  6. data/clementine.gemspec +2 -1
  7. data/ext/clojure-clojurescript-bef56a7/.gitignore +13 -0
  8. data/ext/clojure-clojurescript-bef56a7/Clojurescript.iml +12 -0
  9. data/ext/clojure-clojurescript-bef56a7/README.md +29 -0
  10. data/ext/clojure-clojurescript-bef56a7/benchmark/cljs/benchmark_runner.cljs +155 -0
  11. data/ext/clojure-clojurescript-bef56a7/bin/cljsc +21 -0
  12. data/ext/clojure-clojurescript-bef56a7/bin/cljsc.bat +18 -0
  13. data/{vendor/assets → ext/clojure-clojurescript-bef56a7}/bin/cljsc.clj +0 -0
  14. data/ext/clojure-clojurescript-bef56a7/devnotes/README.org +35 -0
  15. data/ext/clojure-clojurescript-bef56a7/devnotes/bcrepl.org +13 -0
  16. data/ext/clojure-clojurescript-bef56a7/devnotes/cljs.org +500 -0
  17. data/ext/clojure-clojurescript-bef56a7/devnotes/corelib.org +583 -0
  18. data/ext/clojure-clojurescript-bef56a7/devnotes/day1.org +203 -0
  19. data/ext/clojure-clojurescript-bef56a7/devnotes/day2.org +44 -0
  20. data/ext/clojure-clojurescript-bef56a7/devnotes/talk.org +126 -0
  21. data/ext/clojure-clojurescript-bef56a7/devnotes/testing +13 -0
  22. data/ext/clojure-clojurescript-bef56a7/devnotes/todo.org +121 -0
  23. data/ext/clojure-clojurescript-bef56a7/epl-v10.html +261 -0
  24. data/ext/clojure-clojurescript-bef56a7/pom.template.xml +88 -0
  25. data/ext/clojure-clojurescript-bef56a7/samples/dom/.gitignore +2 -0
  26. data/ext/clojure-clojurescript-bef56a7/samples/dom/src/dom/test.cljs +48 -0
  27. data/ext/clojure-clojurescript-bef56a7/samples/dom/test.html +30 -0
  28. data/ext/clojure-clojurescript-bef56a7/samples/hello-js/.gitignore +2 -0
  29. data/ext/clojure-clojurescript-bef56a7/samples/hello-js/README.md +53 -0
  30. data/ext/clojure-clojurescript-bef56a7/samples/hello-js/externed-lib.js +7 -0
  31. data/ext/clojure-clojurescript-bef56a7/samples/hello-js/externs.js +3 -0
  32. data/ext/clojure-clojurescript-bef56a7/samples/hello-js/hello-extern.html +14 -0
  33. data/ext/clojure-clojurescript-bef56a7/samples/hello-js/hello-js-dev.html +18 -0
  34. data/ext/clojure-clojurescript-bef56a7/samples/hello-js/hello-js.html +17 -0
  35. data/ext/clojure-clojurescript-bef56a7/samples/hello-js/my-external-lib.js +3 -0
  36. data/ext/clojure-clojurescript-bef56a7/samples/hello-js/src/hello-js/core.cljs +9 -0
  37. data/ext/clojure-clojurescript-bef56a7/samples/hello-js/src/hello-js/extern-example.cljs +5 -0
  38. data/ext/clojure-clojurescript-bef56a7/samples/hello/.gitignore +2 -0
  39. data/ext/clojure-clojurescript-bef56a7/samples/hello/README.md +34 -0
  40. data/ext/clojure-clojurescript-bef56a7/samples/hello/hello-dev.html +18 -0
  41. data/ext/clojure-clojurescript-bef56a7/samples/hello/hello.html +13 -0
  42. data/ext/clojure-clojurescript-bef56a7/samples/hello/src/hello/core.cljs +8 -0
  43. data/ext/clojure-clojurescript-bef56a7/samples/hello/src/hello/foo/bar.cljs +4 -0
  44. data/ext/clojure-clojurescript-bef56a7/samples/nodehello.cljs +18 -0
  45. data/ext/clojure-clojurescript-bef56a7/samples/nodels.cljs +17 -0
  46. data/ext/clojure-clojurescript-bef56a7/samples/repl/.gitignore +2 -0
  47. data/ext/clojure-clojurescript-bef56a7/samples/repl/README.md +101 -0
  48. data/ext/clojure-clojurescript-bef56a7/samples/repl/index.html +27 -0
  49. data/ext/clojure-clojurescript-bef56a7/samples/repl/src/repl/test.cljs +73 -0
  50. data/ext/clojure-clojurescript-bef56a7/samples/twitterbuzz/.gitignore +2 -0
  51. data/ext/clojure-clojurescript-bef56a7/samples/twitterbuzz/README.md +42 -0
  52. data/ext/clojure-clojurescript-bef56a7/samples/twitterbuzz/index-advanced.html +80 -0
  53. data/ext/clojure-clojurescript-bef56a7/samples/twitterbuzz/index.html +88 -0
  54. data/ext/clojure-clojurescript-bef56a7/samples/twitterbuzz/reset.css +48 -0
  55. data/ext/clojure-clojurescript-bef56a7/samples/twitterbuzz/src/twitterbuzz/anneal.cljs +66 -0
  56. data/ext/clojure-clojurescript-bef56a7/samples/twitterbuzz/src/twitterbuzz/core.cljs +307 -0
  57. data/ext/clojure-clojurescript-bef56a7/samples/twitterbuzz/src/twitterbuzz/dom-helpers.cljs +95 -0
  58. data/ext/clojure-clojurescript-bef56a7/samples/twitterbuzz/src/twitterbuzz/layout.cljs +100 -0
  59. data/ext/clojure-clojurescript-bef56a7/samples/twitterbuzz/src/twitterbuzz/leaderboard.cljs +40 -0
  60. data/ext/clojure-clojurescript-bef56a7/samples/twitterbuzz/src/twitterbuzz/radial.cljs +91 -0
  61. data/ext/clojure-clojurescript-bef56a7/samples/twitterbuzz/src/twitterbuzz/showgraph.cljs +121 -0
  62. data/ext/clojure-clojurescript-bef56a7/samples/twitterbuzz/src/twitterbuzz/timeline.cljs +39 -0
  63. data/ext/clojure-clojurescript-bef56a7/samples/twitterbuzz/style.css +301 -0
  64. data/ext/clojure-clojurescript-bef56a7/samples/twitterbuzz/test_data.txt +1 -0
  65. data/ext/clojure-clojurescript-bef56a7/samples/twitterbuzz/tweet_maps.txt +1 -0
  66. data/ext/clojure-clojurescript-bef56a7/script/benchmark +30 -0
  67. data/ext/clojure-clojurescript-bef56a7/script/bootstrap +70 -0
  68. data/ext/clojure-clojurescript-bef56a7/script/browser-repl +16 -0
  69. data/ext/clojure-clojurescript-bef56a7/script/build +59 -0
  70. data/ext/clojure-clojurescript-bef56a7/script/clean +5 -0
  71. data/ext/clojure-clojurescript-bef56a7/script/closure-library-release/google-closure-library-third-party.pom.template +59 -0
  72. data/ext/clojure-clojurescript-bef56a7/script/closure-library-release/google-closure-library.pom.template +54 -0
  73. data/ext/clojure-clojurescript-bef56a7/script/closure-library-release/make-closure-library-jars.sh +87 -0
  74. data/ext/clojure-clojurescript-bef56a7/script/compile +41 -0
  75. data/ext/clojure-clojurescript-bef56a7/script/repl +13 -0
  76. data/ext/clojure-clojurescript-bef56a7/script/repl.bat +13 -0
  77. data/ext/clojure-clojurescript-bef56a7/script/repljs +15 -0
  78. data/ext/clojure-clojurescript-bef56a7/script/repljs.bat +14 -0
  79. data/ext/clojure-clojurescript-bef56a7/script/test +38 -0
  80. data/ext/clojure-clojurescript-bef56a7/script/test-compile +30 -0
  81. data/ext/clojure-clojurescript-bef56a7/src/clj/cljs/analyzer.clj +975 -0
  82. data/{vendor/assets → ext/clojure-clojurescript-bef56a7}/src/clj/cljs/closure.clj +173 -73
  83. data/ext/clojure-clojurescript-bef56a7/src/clj/cljs/compiler.clj +1081 -0
  84. data/ext/clojure-clojurescript-bef56a7/src/clj/cljs/core.clj +1158 -0
  85. data/{vendor/assets → ext/clojure-clojurescript-bef56a7}/src/clj/cljs/repl.clj +51 -25
  86. data/ext/clojure-clojurescript-bef56a7/src/clj/cljs/repl/browser.clj +258 -0
  87. data/ext/clojure-clojurescript-bef56a7/src/clj/cljs/repl/reflect.clj +75 -0
  88. data/{vendor/assets → ext/clojure-clojurescript-bef56a7}/src/clj/cljs/repl/rhino.clj +6 -5
  89. data/ext/clojure-clojurescript-bef56a7/src/clj/cljs/repl/server.clj +173 -0
  90. data/ext/clojure-clojurescript-bef56a7/src/clj/cljs/tagged_literals.clj +30 -0
  91. data/ext/clojure-clojurescript-bef56a7/src/cljs/cljs/core.cljs +7197 -0
  92. data/{vendor/assets → ext/clojure-clojurescript-bef56a7}/src/cljs/cljs/nodejs.cljs +1 -1
  93. data/{vendor/assets → ext/clojure-clojurescript-bef56a7}/src/cljs/cljs/nodejs_externs.js +0 -0
  94. data/{vendor/assets → ext/clojure-clojurescript-bef56a7}/src/cljs/cljs/nodejscli.cljs +1 -1
  95. data/ext/clojure-clojurescript-bef56a7/src/cljs/cljs/reader.cljs +551 -0
  96. data/{vendor/assets → ext/clojure-clojurescript-bef56a7}/src/cljs/clojure/browser/dom.cljs +59 -13
  97. data/{vendor/assets → ext/clojure-clojurescript-bef56a7}/src/cljs/clojure/browser/event.cljs +0 -0
  98. data/{vendor/assets → ext/clojure-clojurescript-bef56a7}/src/cljs/clojure/browser/net.cljs +8 -7
  99. data/{vendor/assets → ext/clojure-clojurescript-bef56a7}/src/cljs/clojure/browser/repl.cljs +2 -2
  100. data/ext/clojure-clojurescript-bef56a7/src/cljs/clojure/core/reducers.cljs +298 -0
  101. data/ext/clojure-clojurescript-bef56a7/src/cljs/clojure/data.cljs +162 -0
  102. data/ext/clojure-clojurescript-bef56a7/src/cljs/clojure/reflect.cljs +48 -0
  103. data/{vendor/assets → ext/clojure-clojurescript-bef56a7}/src/cljs/clojure/set.cljs +0 -0
  104. data/{vendor/assets → ext/clojure-clojurescript-bef56a7}/src/cljs/clojure/string.cljs +4 -10
  105. data/{vendor/assets → ext/clojure-clojurescript-bef56a7}/src/cljs/clojure/walk.cljs +0 -0
  106. data/{vendor/assets → ext/clojure-clojurescript-bef56a7}/src/cljs/clojure/zip.cljs +0 -0
  107. data/ext/clojure-clojurescript-bef56a7/test/cljs/cljs/binding_test.cljs +7 -0
  108. data/ext/clojure-clojurescript-bef56a7/test/cljs/cljs/binding_test_other_ns.cljs +3 -0
  109. data/ext/clojure-clojurescript-bef56a7/test/cljs/cljs/core_test.cljs +1678 -0
  110. data/ext/clojure-clojurescript-bef56a7/test/cljs/cljs/import_test.cljs +11 -0
  111. data/ext/clojure-clojurescript-bef56a7/test/cljs/cljs/import_test/foo.cljs +5 -0
  112. data/ext/clojure-clojurescript-bef56a7/test/cljs/cljs/letfn_test.cljs +19 -0
  113. data/ext/clojure-clojurescript-bef56a7/test/cljs/cljs/macro_test.cljs +6 -0
  114. data/ext/clojure-clojurescript-bef56a7/test/cljs/cljs/macro_test/macros.clj +5 -0
  115. data/ext/clojure-clojurescript-bef56a7/test/cljs/cljs/ns_test.cljs +14 -0
  116. data/ext/clojure-clojurescript-bef56a7/test/cljs/cljs/ns_test/bar.cljs +3 -0
  117. data/ext/clojure-clojurescript-bef56a7/test/cljs/cljs/ns_test/foo.cljs +7 -0
  118. data/ext/clojure-clojurescript-bef56a7/test/cljs/cljs/reader_test.cljs +124 -0
  119. data/ext/clojure-clojurescript-bef56a7/test/cljs/clojure/data_test.cljs +22 -0
  120. data/ext/clojure-clojurescript-bef56a7/test/cljs/clojure/string_test.cljs +97 -0
  121. data/ext/clojure-clojurescript-bef56a7/test/cljs/foo/ns_shadow_test.cljs +9 -0
  122. data/ext/clojure-clojurescript-bef56a7/test/cljs/test_runner.cljs +26 -0
  123. data/lib/clementine.rb +3 -24
  124. data/lib/clementine/clojurescript_engine.rb +9 -48
  125. data/lib/clementine/clojurescript_engine/base.rb +15 -0
  126. data/lib/clementine/clojurescript_engine/jruby.rb +46 -0
  127. data/lib/clementine/{clojurescript_engine_mri.rb → clojurescript_engine/mri.rb} +17 -10
  128. data/lib/clementine/version.rb +1 -1
  129. data/test/clojurescript_engine_test.rb +36 -14
  130. metadata +177 -83
  131. data/vendor/assets/lib/clojure.jar +0 -0
  132. data/vendor/assets/lib/compiler.jar +0 -0
  133. data/vendor/assets/lib/goog.jar +0 -0
  134. data/vendor/assets/lib/js.jar +0 -0
  135. data/vendor/assets/src/clj/cljs/compiler.clj +0 -1341
  136. data/vendor/assets/src/clj/cljs/core.clj +0 -702
  137. data/vendor/assets/src/clj/cljs/repl/browser.clj +0 -341
  138. data/vendor/assets/src/cljs/cljs/core.cljs +0 -3330
  139. data/vendor/assets/src/cljs/cljs/reader.cljs +0 -360
Binary file
Binary file
Binary file
Binary file
@@ -1,1341 +0,0 @@
1
- ; Copyright (c) Rich Hickey. All rights reserved.
2
- ; The use and distribution terms for this software are covered by the
3
- ; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)
4
- ; which can be found in the file epl-v10.html at the root of this distribution.
5
- ; By using this software in any fashion, you are agreeing to be bound by
6
- ; the terms of this license.
7
- ; You must not remove this notice, or any other, from this software.
8
-
9
- (set! *warn-on-reflection* true)
10
-
11
- (ns cljs.compiler
12
- (:refer-clojure :exclude [munge macroexpand-1])
13
- (:require [clojure.java.io :as io]
14
- [clojure.string :as string]))
15
-
16
- (declare resolve-var)
17
- (require 'cljs.core)
18
-
19
- (def js-reserved
20
- #{"abstract" "boolean" "break" "byte" "case"
21
- "catch" "char" "class" "const" "continue"
22
- "debugger" "default" "delete" "do" "double"
23
- "else" "enum" "export" "extends" "final"
24
- "finally" "float" "for" "function" "goto" "if"
25
- "implements" "import" "in" "instanceof" "int"
26
- "interface" "let" "long" "native" "new"
27
- "package" "private" "protected" "public"
28
- "return" "short" "static" "super" "switch"
29
- "synchronized" "this" "throw" "throws"
30
- "transient" "try" "typeof" "var" "void"
31
- "volatile" "while" "with" "yield" "methods"})
32
-
33
- (defonce namespaces (atom '{cljs.core {:name cljs.core}
34
- cljs.user {:name cljs.user}}))
35
-
36
- (def ^:dynamic *cljs-ns* 'cljs.user)
37
- (def ^:dynamic *cljs-warn-on-undeclared* false)
38
-
39
- (defn munge [s]
40
- (let [ss (str s)
41
- ms (if (.contains ss "]")
42
- (let [idx (inc (.lastIndexOf ss "]"))]
43
- (str (subs ss 0 idx)
44
- (clojure.lang.Compiler/munge (subs ss idx))))
45
- (clojure.lang.Compiler/munge ss))
46
- ms (if (js-reserved ms) (str ms "$") ms)]
47
- (if (symbol? s)
48
- (symbol ms)
49
- ms)))
50
-
51
- (defn confirm-var-exists [env prefix suffix]
52
- (when *cljs-warn-on-undeclared*
53
- (let [crnt-ns (-> env :ns :name)]
54
- (when (= prefix crnt-ns)
55
- (when-not (-> @namespaces crnt-ns :defs suffix)
56
- (binding [*out* *err*]
57
- (println
58
- (str "WARNING: Use of undeclared Var " prefix "/" suffix
59
- (when (:line env)
60
- (str " at line " (:line env)))))))))))
61
-
62
- (defn resolve-ns-alias [env name]
63
- (let [sym (symbol name)]
64
- (get (:requires (:ns env)) sym sym)))
65
-
66
- (defn core-name?
67
- "Is sym visible from core in the current compilation namespace?"
68
- [env sym]
69
- (and (get (:defs (@namespaces 'cljs.core)) sym)
70
- (not (contains? (-> env :ns :excludes) sym))))
71
-
72
- (defn js-var [sym]
73
- (let [parts (string/split (name sym) #"\.")
74
- first (first parts)
75
- step (fn [part] (str "['" part "']"))]
76
- (apply str first (map step (rest parts)))))
77
-
78
- (defn resolve-existing-var [env sym]
79
- (if (= (namespace sym) "js")
80
- {:name (js-var sym)}
81
- (let [s (str sym)
82
- lb (-> env :locals sym)
83
- nm
84
- (cond
85
- lb (:name lb)
86
-
87
- (namespace sym)
88
- (let [ns (namespace sym)
89
- ns (if (= "clojure.core" ns) "cljs.core" ns)
90
- full-ns (resolve-ns-alias env ns)]
91
- (confirm-var-exists env full-ns (symbol (name sym)))
92
- (symbol (str full-ns "." (munge (name sym)))))
93
-
94
- (.contains s ".")
95
- (munge (let [idx (.indexOf s ".")
96
- prefix (symbol (subs s 0 idx))
97
- suffix (subs s idx)
98
- lb (-> env :locals prefix)]
99
- (if lb
100
- (symbol (str (:name lb) suffix))
101
- (do
102
- (confirm-var-exists env prefix (symbol suffix))
103
- sym))))
104
-
105
- (get-in @namespaces [(-> env :ns :name) :uses sym])
106
- (symbol (str (get-in @namespaces [(-> env :ns :name) :uses sym]) "." (munge (name sym))))
107
-
108
- :else
109
- (let [full-ns (if (core-name? env sym)
110
- 'cljs.core
111
- (-> env :ns :name))]
112
- (confirm-var-exists env full-ns sym)
113
- (munge (symbol (str full-ns "." (munge (name sym)))))))]
114
- {:name nm})))
115
-
116
- (defn resolve-var [env sym]
117
- (if (= (namespace sym) "js")
118
- {:name (js-var sym)}
119
- (let [s (str sym)
120
- lb (-> env :locals sym)
121
- nm
122
- (cond
123
- lb (:name lb)
124
-
125
- (namespace sym)
126
- (let [ns (namespace sym)
127
- ns (if (= "clojure.core" ns) "cljs.core" ns)]
128
- (symbol (str (resolve-ns-alias env ns) "." (munge (name sym)))))
129
-
130
- (.contains s ".")
131
- (munge (let [idx (.indexOf s ".")
132
- prefix (symbol (subs s 0 idx))
133
- suffix (subs s idx)
134
- lb (-> env :locals prefix)]
135
- (if lb
136
- (symbol (str (:name lb) suffix))
137
- sym)))
138
-
139
- :else
140
- (munge (symbol (str
141
- (if (core-name? env sym)
142
- 'cljs.core
143
- (-> env :ns :name))
144
- "." (munge (name sym))))))]
145
- {:name nm})))
146
-
147
- (defn- comma-sep [xs]
148
- (apply str (interpose "," xs)))
149
-
150
- (defmulti emit-constant class)
151
- (defmethod emit-constant nil [x] (print "null"))
152
- (defmethod emit-constant Long [x] (print x))
153
- (defmethod emit-constant Integer [x] (print x)) ; reader puts Integers in metadata
154
- (defmethod emit-constant Double [x] (print x))
155
- (defmethod emit-constant String [x] (pr x))
156
- (defmethod emit-constant Boolean [x] (print (if x "true" "false")))
157
- (defmethod emit-constant Character [x] (pr (str x)))
158
-
159
- (defmethod emit-constant java.util.regex.Pattern [x]
160
- (let [[_ flags pattern] (re-find #"^(?:\(\?([idmsux]*)\))?(.*)" (str x))]
161
- (print (str \/ (.replaceAll (re-matcher #"/" pattern) "\\\\/") \/ flags))))
162
-
163
- (defmethod emit-constant clojure.lang.Keyword [x]
164
- (pr (str \uFDD0 \'
165
- (if (namespace x)
166
- (str (namespace x) "/") "")
167
- (name x))))
168
-
169
- (defmethod emit-constant clojure.lang.Symbol [x]
170
- (pr (str \uFDD1 \'
171
- (if (namespace x)
172
- (str (namespace x) "/") "")
173
- (name x))))
174
-
175
- (defn- emit-meta-constant [x string]
176
- (if (meta x)
177
- (do
178
- (print (str "cljs.core.with_meta(" string ","))
179
- (emit-constant (meta x))
180
- (print ")"))
181
- (print string)))
182
-
183
- (defmethod emit-constant clojure.lang.PersistentList$EmptyList [x]
184
- (emit-meta-constant x "cljs.core.List.EMPTY"))
185
-
186
- (defmethod emit-constant clojure.lang.PersistentList [x]
187
- (emit-meta-constant x
188
- (str "cljs.core.list("
189
- (comma-sep (map #(with-out-str (emit-constant %)) x))
190
- ")")))
191
-
192
- (defmethod emit-constant clojure.lang.Cons [x]
193
- (emit-meta-constant x
194
- (str "cljs.core.list("
195
- (comma-sep (map #(with-out-str (emit-constant %)) x))
196
- ")")))
197
-
198
- (defmethod emit-constant clojure.lang.IPersistentVector [x]
199
- (emit-meta-constant x
200
- (str "(new cljs.core.Vector(null, ["
201
- (comma-sep (map #(with-out-str (emit-constant %)) x))
202
- "]))")))
203
-
204
- (defmethod emit-constant clojure.lang.IPersistentMap [x]
205
- (emit-meta-constant x
206
- (str "cljs.core.hash_map("
207
- (comma-sep (map #(with-out-str (emit-constant %))
208
- (apply concat x)))
209
- ")")))
210
-
211
- (defmethod emit-constant clojure.lang.PersistentHashSet [x]
212
- (emit-meta-constant x
213
- (str "cljs.core.set(["
214
- (comma-sep (map #(with-out-str (emit-constant %)) x))
215
- "])")))
216
-
217
- (defmulti emit :op)
218
-
219
- (defn ^String emits [expr]
220
- (with-out-str (emit expr)))
221
-
222
- (defn emit-block
223
- [context statements ret]
224
- (if statements
225
- (let [body (str (apply str (map emits statements)) (emits ret))]
226
- (print body))
227
- (emit ret)))
228
-
229
- (defmacro emit-wrap [env & body]
230
- `(let [env# ~env]
231
- (when (= :return (:context env#)) (print "return "))
232
- ~@body
233
- (when-not (= :expr (:context env#)) (print ";\n"))))
234
-
235
- (defmethod emit :var
236
- [{:keys [info env] :as arg}]
237
- (emit-wrap env (print (munge (:name info)))))
238
-
239
- (defmethod emit :meta
240
- [{:keys [expr meta env]}]
241
- (emit-wrap env
242
- (print (str "cljs.core.with_meta(" (emits expr) "," (emits meta) ")"))))
243
-
244
- (defmethod emit :map
245
- [{:keys [children env simple-keys? keys vals]}]
246
- (emit-wrap env
247
- (if simple-keys?
248
- (print (str "cljs.core.ObjMap.fromObject(["
249
- (comma-sep (map emits keys)) ; keys
250
- "],{"
251
- (comma-sep (map (fn [k v] (str (emits k) ":" (emits v)))
252
- keys vals)) ; js obj
253
- "})"))
254
- (print (str "cljs.core.HashMap.fromArrays(["
255
- (comma-sep (map emits keys))
256
- "],["
257
- (comma-sep (map emits vals))
258
- "])")))))
259
-
260
- (defmethod emit :vector
261
- [{:keys [children env]}]
262
- (emit-wrap env
263
- (print (str "cljs.core.Vector.fromArray(["
264
- (comma-sep (map emits children)) "])"))))
265
-
266
- (defmethod emit :set
267
- [{:keys [children env]}]
268
- (emit-wrap env
269
- (print (str "cljs.core.set(["
270
- (comma-sep (map emits children)) "])"))))
271
-
272
- (defmethod emit :constant
273
- [{:keys [form env]}]
274
- (when-not (= :statement (:context env))
275
- (emit-wrap env (emit-constant form))))
276
-
277
- (defmethod emit :if
278
- [{:keys [test then else env]}]
279
- (let [context (:context env)]
280
- (if (= :expr context)
281
- (print (str "(cljs.core.truth_(" (emits test) ")?" (emits then) ":" (emits else) ")"))
282
- (print (str "if(cljs.core.truth_(" (emits test) "))\n{" (emits then) "} else\n{" (emits else) "}\n")))))
283
-
284
- (defmethod emit :throw
285
- [{:keys [throw env]}]
286
- (if (= :expr (:context env))
287
- (print (str "(function(){throw " (emits throw) "})()"))
288
- (print (str "throw " (emits throw) ";\n"))))
289
-
290
- (defn emit-comment
291
- "Emit a nicely formatted comment string."
292
- [doc jsdoc]
293
- (let [docs (when doc [doc])
294
- docs (if jsdoc (concat docs jsdoc) docs)
295
- docs (remove nil? docs)]
296
- (letfn [(print-comment-lines [e] (doseq [next-line (string/split-lines e)]
297
- (println "*" (string/trim next-line))))]
298
- (when (seq docs)
299
- (println "/**")
300
- (doseq [e docs]
301
- (when e
302
- (print-comment-lines e)))
303
- (println "*/")))))
304
-
305
- (defmethod emit :def
306
- [{:keys [name init env doc export]}]
307
- (when init
308
- (emit-comment doc (:jsdoc init))
309
- (print name)
310
- (print (str " = " (emits init)))
311
- (when-not (= :expr (:context env)) (print ";\n"))
312
- (when export
313
- (println (str "goog.exportSymbol('" export "', " name ");")))))
314
-
315
- (defn emit-apply-to
316
- [{:keys [name params env]}]
317
- (let [arglist (gensym "arglist__")
318
- delegate-name (str name "__delegate")]
319
- (println (str "(function (" arglist "){"))
320
- (doseq [[i param] (map-indexed vector (butlast params))]
321
- (print (str "var " param " = cljs.core.first("))
322
- (dotimes [_ i] (print "cljs.core.next("))
323
- (print (str arglist ")"))
324
- (dotimes [_ i] (print ")"))
325
- (println ";"))
326
- (if (< 1 (count params))
327
- (do
328
- (print (str "var " (last params) " = cljs.core.rest("))
329
- (dotimes [_ (- (count params) 2)] (print "cljs.core.next("))
330
- (print arglist)
331
- (dotimes [_ (- (count params) 2)] (print ")"))
332
- (println ");")
333
- (println (str "return " delegate-name ".call(" (string/join ", " (cons "this" params)) ");")))
334
- (do
335
- (print (str "var " (last params) " = "))
336
- (print "cljs.core.seq(" arglist ");")
337
- (println ";")
338
- (println (str "return " delegate-name ".call(" (string/join ", " (cons "this" params)) ");"))))
339
- (print "})")))
340
-
341
- (defn emit-fn-method
342
- [{:keys [gthis name variadic params statements ret env recurs max-fixed-arity]}]
343
- (emit-wrap env
344
- (print (str "(function " name "(" (comma-sep params) "){\n"))
345
- (when gthis
346
- (println (str "var " gthis " = this;")))
347
- (when recurs (print "while(true){\n"))
348
- (emit-block :return statements ret)
349
- (when recurs (print "break;\n}\n"))
350
- (print "})")))
351
-
352
- (defn emit-variadic-fn-method
353
- [{:keys [gthis name variadic params statements ret env recurs max-fixed-arity] :as f}]
354
- (emit-wrap env
355
- (let [name (or name (gensym))
356
- delegate-name (str name "__delegate")]
357
- (println "(function() { ")
358
- (println (str "var " delegate-name " = function (" (comma-sep params) "){"))
359
- (when recurs (print "while(true){\n"))
360
- (emit-block :return statements ret)
361
- (when recurs (print "break;\n}\n"))
362
- (println "};")
363
-
364
- (print (str "var " name " = function (" (comma-sep
365
- (if variadic
366
- (concat (butlast params) ['var_args])
367
- params)) "){\n"))
368
- (when gthis
369
- (println (str "var " gthis " = this;")))
370
- (when variadic
371
- (println (str "var " (last params) " = null;"))
372
- (println (str "if (goog.isDef(var_args)) {"))
373
- (println (str " " (last params) " = cljs.core.array_seq(Array.prototype.slice.call(arguments, " (dec (count params)) "),0);"))
374
- (println (str "} ")))
375
- (println (str "return " delegate-name ".call(" (string/join ", " (cons "this" params)) ");"))
376
- (println "};")
377
-
378
- (println (str name ".cljs$lang$maxFixedArity = " max-fixed-arity ";"))
379
- (println (str name ".cljs$lang$applyTo = "
380
- (with-out-str
381
- (emit-apply-to (assoc f :name name)))
382
- ";"))
383
- (println (str "return " name ";"))
384
- (println "})()"))))
385
-
386
- (defmethod emit :fn
387
- [{:keys [name env methods max-fixed-arity variadic recur-frames]}]
388
- ;;fn statements get erased, serve no purpose and can pollute scope if named
389
- (when-not (= :statement (:context env))
390
- (let [loop-locals (seq (mapcat :names (filter #(and % @(:flag %)) recur-frames)))]
391
- (when loop-locals
392
- (when (= :return (:context env))
393
- (print "return "))
394
- (println (str "((function (" (comma-sep loop-locals) "){"))
395
- (when-not (= :return (:context env))
396
- (print "return ")))
397
- (if (= 1 (count methods))
398
- (if variadic
399
- (emit-variadic-fn-method (assoc (first methods) :name name))
400
- (emit-fn-method (assoc (first methods) :name name)))
401
- (let [name (or name (gensym))
402
- maxparams (apply max-key count (map :params methods))
403
- mmap (zipmap (repeatedly #(gensym (str name "__"))) methods)
404
- ms (sort-by #(-> % second :params count) (seq mmap))]
405
- (when (= :return (:context env))
406
- (print "return "))
407
- (println "(function() {")
408
- (println (str "var " name " = null;"))
409
- (doseq [[n meth] ms]
410
- (println (str "var " n " = " (with-out-str (if (:variadic meth)
411
- (emit-variadic-fn-method meth)
412
- (emit-fn-method meth))) ";")))
413
- (println (str name " = function(" (comma-sep (if variadic
414
- (concat (butlast maxparams) ['var_args])
415
- maxparams)) "){"))
416
- (when variadic
417
- (println (str "var " (last maxparams) " = var_args;")))
418
- (println "switch(arguments.length){")
419
- (doseq [[n meth] ms]
420
- (if (:variadic meth)
421
- (do (println "default:")
422
- (println (str "return " n ".apply(this,arguments);")))
423
- (let [pcnt (count (:params meth))]
424
- (println "case " pcnt ":")
425
- (println (str "return " n ".call(this" (if (zero? pcnt) nil
426
- (str "," (comma-sep (take pcnt maxparams)))) ");")))))
427
- (println "}")
428
- (println "throw('Invalid arity: ' + arguments.length);")
429
- (println "};")
430
- (when variadic
431
- (println (str name ".cljs$lang$maxFixedArity = " max-fixed-arity ";"))
432
- (println (str name ".cljs$lang$applyTo = " (some #(let [[n m] %] (when (:variadic m) n)) ms) ".cljs$lang$applyTo;")))
433
- (println (str "return " name ";"))
434
- (println "})()")))
435
- (when loop-locals
436
- (println (str ";})(" (comma-sep loop-locals) "))"))))))
437
-
438
- (defmethod emit :do
439
- [{:keys [statements ret env]}]
440
- (let [context (:context env)]
441
- (when (and statements (= :expr context)) (print "(function (){"))
442
- ;(when statements (print "{\n"))
443
- (emit-block context statements ret)
444
- ;(when statements (print "}"))
445
- (when (and statements (= :expr context)) (print "})()"))))
446
-
447
- (defmethod emit :try*
448
- [{:keys [env try catch name finally]}]
449
- (let [context (:context env)
450
- subcontext (if (= :expr context) :return context)]
451
- (if (or name finally)
452
- (do
453
- (when (= :expr context) (print "(function (){"))
454
- (print "try{")
455
- (let [{:keys [statements ret]} try]
456
- (emit-block subcontext statements ret))
457
- (print "}")
458
- (when name
459
- (print (str "catch (" name "){"))
460
- (when catch
461
- (let [{:keys [statements ret]} catch]
462
- (emit-block subcontext statements ret)))
463
- (print "}"))
464
- (when finally
465
- (let [{:keys [statements ret]} finally]
466
- (assert (not= :constant (:op ret)) "finally block cannot contain constant")
467
- (print "finally {")
468
- (emit-block subcontext statements ret)
469
- (print "}")))
470
- (when (= :expr context) (print "})()")))
471
- (let [{:keys [statements ret]} try]
472
- (when (and statements (= :expr context)) (print "(function (){"))
473
- (emit-block subcontext statements ret)
474
- (when (and statements (= :expr context)) (print "})()"))))))
475
-
476
- (defmethod emit :let
477
- [{:keys [bindings statements ret env loop]}]
478
- (let [context (:context env)
479
- bs (map (fn [{:keys [name init]}]
480
- (str "var " name " = " (emits init) ";\n"))
481
- bindings)]
482
- (when (= :expr context) (print "(function (){"))
483
- (print (str (apply str bs) "\n"))
484
- (when loop (print "while(true){\n"))
485
- (emit-block (if (= :expr context) :return context) statements ret)
486
- (when loop (print "break;\n}\n"))
487
- ;(print "}")
488
- (when (= :expr context) (print "})()"))))
489
-
490
- (defmethod emit :recur
491
- [{:keys [frame exprs env]}]
492
- (let [temps (vec (take (count exprs) (repeatedly gensym)))
493
- names (:names frame)]
494
- (print "{\n")
495
- (dotimes [i (count exprs)]
496
- (print (str "var " (temps i) " = " (emits (exprs i)) ";\n")))
497
- (dotimes [i (count exprs)]
498
- (print (str (names i) " = " (temps i) ";\n")))
499
- (print "continue;\n")
500
- (print "}\n")))
501
-
502
- (defmethod emit :invoke
503
- [{:keys [f args env]}]
504
- (emit-wrap env
505
- (print (str (emits f) ".call("
506
- (comma-sep (cons "null" (map emits args)))
507
- ")"))))
508
-
509
- (defmethod emit :new
510
- [{:keys [ctor args env]}]
511
- (emit-wrap env
512
- (print (str "(new " (emits ctor) "("
513
- (comma-sep (map emits args))
514
- "))"))))
515
-
516
- (defmethod emit :set!
517
- [{:keys [target val env]}]
518
- (emit-wrap env (print (str (emits target) " = "(emits val)))))
519
-
520
- (defmethod emit :ns
521
- [{:keys [name requires uses requires-macros env]}]
522
- (println (str "goog.provide('" (munge name) "');"))
523
- (when-not (= name 'cljs.core)
524
- (println (str "goog.require('cljs.core');")))
525
- (doseq [lib (into (vals requires) (vals uses))]
526
- (println (str "goog.require('" (munge lib) "');"))))
527
-
528
- (defmethod emit :deftype*
529
- [{:keys [t fields]}]
530
- (let [fields (map munge fields)]
531
- (println "\n/**\n* @constructor\n*/")
532
- (println (str t " = (function (" (comma-sep (map str fields)) "){"))
533
- (doseq [fld fields]
534
- (println (str "this." fld " = " fld ";")))
535
- (println "})")))
536
-
537
- (defmethod emit :defrecord*
538
- [{:keys [t fields]}]
539
- (let [fields (map munge fields)]
540
- (println "\n/**\n* @constructor")
541
- (doseq [fld fields]
542
- (println (str "* @param {*} " fld)))
543
- (println "* @param {*=} __meta \n* @param {*=} __extmap\n*/")
544
- (println (str t " = (function (" (comma-sep (map str fields)) ", __meta, __extmap){"))
545
- (doseq [fld fields]
546
- (println (str "this." fld " = " fld ";")))
547
- (println (str "if(arguments.length>" (count fields) "){"))
548
- ;; (println (str "this.__meta = arguments[" (count fields) "];"))
549
- ;; (println (str "this.__extmap = arguments[" (inc (count fields)) "];"))
550
- (println (str "this.__meta = __meta;"))
551
- (println (str "this.__extmap = __extmap;"))
552
- (println "} else {")
553
- (print (str "this.__meta="))
554
- (emit-constant nil)
555
- (println ";")
556
- (print (str "this.__extmap="))
557
- (emit-constant nil)
558
- (println ";")
559
- (println "}")
560
- (println "})")))
561
-
562
- (defmethod emit :dot
563
- [{:keys [target field method args env]}]
564
- (emit-wrap env
565
- (if field
566
- (print (str (emits target) "." field))
567
- (print (str (emits target) "." method "("
568
- (comma-sep (map emits args))
569
- ")")))))
570
-
571
- (defmethod emit :js
572
- [{:keys [env code segs args]}]
573
- (emit-wrap env
574
- (if code
575
- (print code)
576
- (print (apply str (interleave (concat segs (repeat nil))
577
- (concat (map emits args) [nil])))))))
578
-
579
- (declare analyze analyze-symbol analyze-seq)
580
-
581
- (def specials '#{if def fn* do let* loop* throw try* recur new set! ns deftype* defrecord* . js* & quote})
582
-
583
- (def ^:dynamic *recur-frames* nil)
584
-
585
- (defmacro disallowing-recur [& body]
586
- `(binding [*recur-frames* (cons nil *recur-frames*)] ~@body))
587
-
588
- (defn analyze-block
589
- "returns {:statements .. :ret .. :children ..}"
590
- [env exprs]
591
- (let [statements (disallowing-recur
592
- (seq (map #(analyze (assoc env :context :statement) %) (butlast exprs))))
593
- ret (if (<= (count exprs) 1)
594
- (analyze env (first exprs))
595
- (analyze (assoc env :context (if (= :statement (:context env)) :statement :return)) (last exprs)))]
596
- {:statements statements :ret ret :children (vec (cons ret statements))}))
597
-
598
- (defmulti parse (fn [op & rest] op))
599
-
600
- (defmethod parse 'if
601
- [op env [_ test then else :as form] name]
602
- (let [test-expr (disallowing-recur (analyze (assoc env :context :expr) test))
603
- then-expr (analyze env then)
604
- else-expr (analyze env else)]
605
- {:env env :op :if :form form
606
- :test test-expr :then then-expr :else else-expr
607
- :children [test-expr then-expr else-expr]}))
608
-
609
- (defmethod parse 'throw
610
- [op env [_ throw :as form] name]
611
- (let [throw-expr (disallowing-recur (analyze (assoc env :context :expr) throw))]
612
- {:env env :op :throw :form form
613
- :throw throw-expr
614
- :children [throw-expr]}))
615
-
616
- (defmethod parse 'try*
617
- [op env [_ & body :as form] name]
618
- (let [body (vec body)
619
- catchenv (update-in env [:context] #(if (= :expr %) :return %))
620
- tail (peek body)
621
- fblock (when (and (seq? tail) (= 'finally (first tail)))
622
- (rest tail))
623
- finally (when fblock
624
- (analyze-block
625
- (assoc env :context :statement)
626
- fblock))
627
- body (if finally (pop body) body)
628
- tail (peek body)
629
- cblock (when (and (seq? tail)
630
- (= 'catch (first tail)))
631
- (rest tail))
632
- name (first cblock)
633
- locals (:locals catchenv)
634
- mname (when name (munge name))
635
- locals (if name
636
- (assoc locals name {:name mname})
637
- locals)
638
- catch (when cblock
639
- (analyze-block (assoc catchenv :locals locals) (rest cblock)))
640
- body (if name (pop body) body)
641
- try (when body
642
- (analyze-block (if (or name finally) catchenv env) body))]
643
- (when name (assert (not (namespace name)) "Can't qualify symbol in catch"))
644
- {:env env :op :try* :form form
645
- :try try
646
- :finally finally
647
- :name mname
648
- :catch catch
649
- :children [try {:name mname} catch finally]}))
650
-
651
- (defmethod parse 'def
652
- [op env form name]
653
- (let [pfn (fn ([_ sym] {:sym sym})
654
- ([_ sym init] {:sym sym :init init})
655
- ([_ sym doc init] {:sym sym :doc doc :init init}))
656
- args (apply pfn form)
657
- sym (:sym args)]
658
- (assert (not (namespace sym)) "Can't def ns-qualified name")
659
- (let [name (munge (:name (resolve-var (dissoc env :locals) sym)))
660
- init-expr (when (contains? args :init) (disallowing-recur
661
- (analyze (assoc env :context :expr) (:init args) sym)))
662
- export-as (when-let [export-val (-> sym meta :export)]
663
- (if (= true export-val) name export-val))
664
- doc (or (:doc args) (-> sym meta :doc))]
665
- (swap! namespaces assoc-in [(-> env :ns :name) :defs sym] name)
666
- (merge {:env env :op :def :form form
667
- :name name :doc doc :init init-expr}
668
- (when init-expr {:children [init-expr]})
669
- (when export-as {:export export-as})))))
670
-
671
- (defn- analyze-fn-method [env locals meth]
672
- (let [params (first meth)
673
- fields (-> params meta ::fields)
674
- variadic (boolean (some '#{&} params))
675
- params (remove '#{&} params)
676
- fixed-arity (count (if variadic (butlast params) params))
677
- body (next meth)
678
- gthis (and fields (gensym "this__"))
679
- locals (reduce (fn [m fld] (assoc m fld {:name (symbol (str gthis "." (munge fld)))})) locals fields)
680
- locals (reduce (fn [m name] (assoc m name {:name (munge name)})) locals params)
681
- recur-frame {:names (vec (map munge params)) :flag (atom nil)}
682
- block (binding [*recur-frames* (cons recur-frame *recur-frames*)]
683
- (analyze-block (assoc env :context :return :locals locals) body))]
684
-
685
- (merge {:env env :variadic variadic :params (map munge params) :max-fixed-arity fixed-arity :gthis gthis :recurs @(:flag recur-frame)} block)))
686
-
687
- (defmethod parse 'fn*
688
- [op env [_ & args] name]
689
- (let [[name meths] (if (symbol? (first args))
690
- [(first args) (next args)]
691
- [name (seq args)])
692
- ;;turn (fn [] ...) into (fn ([]...))
693
- meths (if (vector? (first meths)) (list meths) meths)
694
- mname (when name (munge name))
695
- locals (:locals env)
696
- locals (if name (assoc locals name {:name mname}) locals)
697
- menv (if (> (count meths) 1) (assoc env :context :expr) env)
698
- methods (map #(analyze-fn-method menv locals %) meths)
699
- max-fixed-arity (apply max (map :max-fixed-arity methods))
700
- variadic (boolean (some :variadic methods))]
701
- ;;(assert (= 1 (count methods)) "Arity overloading not yet supported")
702
- ;;todo - validate unique arities, at most one variadic, variadic takes max required args
703
- {:env env :op :fn :name mname :methods methods :variadic variadic :recur-frames *recur-frames*
704
- :jsdoc [(when variadic "@param {...*} var_args")]
705
- :max-fixed-arity max-fixed-arity}))
706
-
707
- (defmethod parse 'do
708
- [op env [_ & exprs] _]
709
- (merge {:env env :op :do} (analyze-block env exprs)))
710
-
711
- (defn analyze-let
712
- [encl-env [_ bindings & exprs :as form] is-loop]
713
- (assert (and (vector? bindings) (even? (count bindings))) "bindings must be vector of even number of elements")
714
- (let [context (:context encl-env)
715
- [bes env]
716
- (disallowing-recur
717
- (loop [bes []
718
- env (assoc encl-env :context :expr)
719
- bindings (seq (partition 2 bindings))]
720
- (if-let [[name init] (first bindings)]
721
- (do
722
- (assert (not (or (namespace name) (.contains (str name) "."))) (str "Invalid local name: " name))
723
- (let [init-expr (analyze env init)
724
- be {:name (gensym (str (munge name) "__")) :init init-expr}]
725
- (recur (conj bes be)
726
- (assoc-in env [:locals name] be)
727
- (next bindings))))
728
- [bes env])))
729
- recur-frame (when is-loop {:names (vec (map :name bes)) :flag (atom nil)})
730
- {:keys [statements ret children]}
731
- (binding [*recur-frames* (if recur-frame (cons recur-frame *recur-frames*) *recur-frames*)]
732
- (analyze-block (assoc env :context (if (= :expr context) :return context)) exprs))]
733
- {:env encl-env :op :let :loop is-loop
734
- :bindings bes :statements statements :ret ret :form form :children (into [children] (map :init bes))}))
735
-
736
- (defmethod parse 'let*
737
- [op encl-env form _]
738
- (analyze-let encl-env form false))
739
-
740
- (defmethod parse 'loop*
741
- [op encl-env form _]
742
- (analyze-let encl-env form true))
743
-
744
- (defmethod parse 'recur
745
- [op env [_ & exprs] _]
746
- (let [context (:context env)
747
- frame (first *recur-frames*)]
748
- (assert frame "Can't recur here")
749
- (assert (= (count exprs) (count (:names frame))) "recur argument count mismatch")
750
- (reset! (:flag frame) true)
751
- (assoc {:env env :op :recur}
752
- :frame frame
753
- :exprs (disallowing-recur (vec (map #(analyze (assoc env :context :expr) %) exprs))))))
754
-
755
- (defmethod parse 'quote
756
- [_ env [_ x] _]
757
- {:op :constant :env env :form x})
758
-
759
- (defmethod parse 'new
760
- [_ env [_ ctor & args] _]
761
- (disallowing-recur
762
- (let [enve (assoc env :context :expr)
763
- ctorexpr (analyze enve ctor)
764
- argexprs (vec (map #(analyze enve %) args))]
765
- {:env env :op :new :ctor ctorexpr :args argexprs :children (conj argexprs ctorexpr)})))
766
-
767
- (defmethod parse 'set!
768
- [_ env [_ target val] _]
769
- (disallowing-recur
770
- (let [enve (assoc env :context :expr)
771
- targetexpr (if (symbol? target)
772
- (do
773
- (assert (nil? (-> env :locals target))
774
- "Can't set! local var")
775
- (analyze-symbol enve target))
776
- (when (seq? target)
777
- (let [targetexpr (analyze-seq enve target nil)]
778
- (when (:field targetexpr)
779
- targetexpr))))
780
- valexpr (analyze enve val)]
781
- (assert targetexpr "set! target must be a field or a symbol naming a var")
782
- {:env env :op :set! :target targetexpr :val valexpr :children [targetexpr valexpr]})))
783
-
784
- (defmethod parse 'ns
785
- [_ env [_ name & args] _]
786
- (let [excludes
787
- (reduce (fn [s [k exclude xs]]
788
- (if (= k :refer-clojure)
789
- (do
790
- (assert (= exclude :exclude) "Only [:refer-clojure :exclude [names]] form supported")
791
- (into s xs))
792
- s))
793
- #{} args)
794
- {uses :use requires :require uses-macros :use-macros requires-macros :require-macros :as params}
795
- (reduce (fn [m [k & libs]]
796
- (assert (#{:use :use-macros :require :require-macros} k)
797
- "Only :refer-clojure, :require, :require-macros, :use and :use-macros libspecs supported")
798
- (assoc m k (into {}
799
- (mapcat (fn [[lib kw expr]]
800
- (case k
801
- (:require :require-macros)
802
- (do (assert (and expr (= :as kw))
803
- "Only (:require [lib.ns :as alias]*) form of :require / :require-macros is supported")
804
- [[expr lib]])
805
- (:use :use-macros)
806
- (do (assert (and expr (= :only kw))
807
- "Only (:use [lib.ns :only [names]]*) form of :use / :use-macros is supported")
808
- (map vector expr (repeat lib)))))
809
- libs))))
810
- {} (remove (fn [[r]] (= r :refer-clojure)) args))]
811
- (set! *cljs-ns* name)
812
- (require 'cljs.core)
813
- (doseq [nsym (concat (vals requires-macros) (vals uses-macros))]
814
- (clojure.core/require nsym))
815
- (swap! namespaces #(-> %
816
- (assoc-in [name :name] name)
817
- (assoc-in [name :excludes] excludes)
818
- (assoc-in [name :uses] uses)
819
- (assoc-in [name :requires] requires)
820
- (assoc-in [name :uses-macros] uses-macros)
821
- (assoc-in [name :requires-macros]
822
- (into {} (map (fn [[alias nsym]]
823
- [alias (find-ns nsym)])
824
- requires-macros)))))
825
- {:env env :op :ns :name name :uses uses :requires requires
826
- :uses-macros uses-macros :requires-macros requires-macros :excludes excludes}))
827
-
828
- (defmethod parse 'deftype*
829
- [_ env [_ tsym fields] _]
830
- (let [t (munge (:name (resolve-var (dissoc env :locals) tsym)))]
831
- (swap! namespaces assoc-in [(-> env :ns :name) :defs tsym] t)
832
- {:env env :op :deftype* :t t :fields fields}))
833
-
834
- (defmethod parse 'defrecord*
835
- [_ env [_ tsym fields] _]
836
- (let [t (munge (:name (resolve-var (dissoc env :locals) tsym)))]
837
- (swap! namespaces assoc-in [(-> env :ns :name) :defs tsym] t)
838
- {:env env :op :defrecord* :t t :fields fields}))
839
-
840
- (defmethod parse '.
841
- [_ env [_ target & member+] _]
842
- (disallowing-recur
843
- (let [enve (assoc env :context :expr)
844
- targetexpr (analyze enve target)
845
- children [enve]]
846
- (if (and (symbol? (first member+)) (nil? (next member+))) ;;(. target field)
847
- {:env env :op :dot :target targetexpr :field (munge (first member+)) :children children}
848
- (let [[method args]
849
- (if (symbol? (first member+))
850
- [(first member+) (next member+)]
851
- [(ffirst member+) (nfirst member+)])
852
- argexprs (map #(analyze enve %) args)]
853
- {:env env :op :dot :target targetexpr :method (munge method) :args argexprs :children (into children argexprs)})))))
854
-
855
- (defmethod parse 'js*
856
- [op env [_ form & args] _]
857
- (assert (string? form))
858
- (if args
859
- (disallowing-recur
860
- (let [seg (fn seg [^String s]
861
- (let [idx (.indexOf s "~{")]
862
- (if (= -1 idx)
863
- (list s)
864
- (let [end (.indexOf s "}" idx)]
865
- (cons (subs s 0 idx) (seg (subs s (inc end))))))))
866
- enve (assoc env :context :expr)
867
- argexprs (vec (map #(analyze enve %) args))]
868
- {:env env :op :js :segs (seg form) :args argexprs :children argexprs}))
869
- (let [interp (fn interp [^String s]
870
- (let [idx (.indexOf s "~{")]
871
- (if (= -1 idx)
872
- (list s)
873
- (let [end (.indexOf s "}" idx)
874
- inner (:name (resolve-existing-var env (symbol (subs s (+ 2 idx) end))))]
875
- (cons (subs s 0 idx) (cons inner (interp (subs s (inc end)))))))))]
876
- {:env env :op :js :code (apply str (interp form))})))
877
-
878
- (defn parse-invoke
879
- [env [f & args]]
880
- (disallowing-recur
881
- (let [enve (assoc env :context :expr)
882
- fexpr (analyze enve f)
883
- argexprs (vec (map #(analyze enve %) args))]
884
- {:env env :op :invoke :f fexpr :args argexprs :children (conj argexprs fexpr)})))
885
-
886
- (defn analyze-symbol
887
- "Finds the var associated with sym"
888
- [env sym]
889
- (let [ret {:env env :form sym}
890
- lb (-> env :locals sym)]
891
- (if lb
892
- (assoc ret :op :var :info lb)
893
- (assoc ret :op :var :info (resolve-existing-var env sym)))))
894
-
895
- (defn get-expander [sym env]
896
- (let [mvar
897
- (when-not (-> env :locals sym) ;locals hide macros
898
- (if-let [nstr (namespace sym)]
899
- (when-let [ns (cond
900
- (= "clojure.core" nstr) (find-ns 'cljs.core)
901
- (.contains nstr ".") (find-ns (symbol nstr))
902
- :else
903
- (-> env :ns :requires-macros (get (symbol nstr))))]
904
- (.findInternedVar ^clojure.lang.Namespace ns (symbol (name sym))))
905
- (if-let [nsym (-> env :ns :uses-macros sym)]
906
- (.findInternedVar ^clojure.lang.Namespace (find-ns nsym) sym)
907
- (.findInternedVar ^clojure.lang.Namespace (find-ns 'cljs.core) sym))))]
908
- (when (and mvar (.isMacro ^clojure.lang.Var mvar))
909
- @mvar)))
910
-
911
- (defn macroexpand-1 [env form]
912
- (let [op (first form)]
913
- (if (specials op)
914
- form
915
- (if-let [mac (and (symbol? op) (get-expander op env))]
916
- (apply mac form env (rest form))
917
- (if (symbol? op)
918
- (let [opname (str op)]
919
- (cond
920
- (= (first opname) \.) (let [[target & args] (next form)]
921
- (list* '. target (symbol (subs opname 1)) args))
922
- (= (last opname) \.) (list* 'new (symbol (subs opname 0 (dec (count opname)))) (next form))
923
- :else form))
924
- form)))))
925
-
926
- (defn analyze-seq
927
- [env form name]
928
- (let [env (assoc env :line (-> form meta :line))]
929
- (let [op (first form)]
930
- (assert (not (nil? op)) "Can't call nil")
931
- (let [mform (macroexpand-1 env form)]
932
- (if (identical? form mform)
933
- (if (specials op)
934
- (parse op env form name)
935
- (parse-invoke env form))
936
- (analyze env mform name))))))
937
-
938
- (declare analyze-wrap-meta)
939
-
940
- (defn analyze-map
941
- [env form name]
942
- (let [expr-env (assoc env :context :expr)
943
- simple-keys? (every? #(or (string? %) (keyword? %))
944
- (keys form))
945
- ks (disallowing-recur (vec (map #(analyze expr-env % name) (keys form))))
946
- vs (disallowing-recur (vec (map #(analyze expr-env % name) (vals form))))]
947
- (analyze-wrap-meta {:op :map :env env :form form :children (vec (concat ks vs))
948
- :keys ks :vals vs :simple-keys? simple-keys?}
949
- name)))
950
-
951
- (defn analyze-vector
952
- [env form name]
953
- (let [expr-env (assoc env :context :expr)
954
- items (disallowing-recur (vec (map #(analyze expr-env % name) form)))]
955
- (analyze-wrap-meta {:op :vector :env env :form form :children items} name)))
956
-
957
- (defn analyze-set
958
- [env form name]
959
- (let [expr-env (assoc env :context :expr)
960
- items (disallowing-recur (vec (map #(analyze expr-env % name) form)))]
961
- (analyze-wrap-meta {:op :set :env env :form form :children items} name)))
962
-
963
- (defn analyze-wrap-meta [expr name]
964
- (let [form (:form expr)]
965
- (if (meta form)
966
- (let [env (:env expr) ; take on expr's context ourselves
967
- expr (assoc-in expr [:env :context] :expr) ; change expr to :expr
968
- meta-expr (analyze-map (:env expr) (meta form) name)]
969
- {:op :meta :env env :form form :children [meta-expr expr]
970
- :meta meta-expr :expr expr})
971
- expr)))
972
-
973
- (defn analyze
974
- "Given an environment, a map containing {:locals (mapping of names to bindings), :context
975
- (one of :statement, :expr, :return), :ns (a symbol naming the
976
- compilation ns)}, and form, returns an expression object (a map
977
- containing at least :form, :op and :env keys). If expr has any (immediately)
978
- nested exprs, must have :children [exprs...] entry. This will
979
- facilitate code walking without knowing the details of the op set."
980
- ([env form] (analyze env form nil))
981
- ([env form name]
982
- (let [form (if (instance? clojure.lang.LazySeq form)
983
- (or (seq form) ())
984
- form)]
985
- (cond
986
- (symbol? form) (analyze-symbol env form)
987
- (and (seq? form) (seq form)) (analyze-seq env form name)
988
- (map? form) (analyze-map env form name)
989
- (vector? form) (analyze-vector env form name)
990
- (set? form) (analyze-set env form name)
991
- :else {:op :constant :env env :form form}))))
992
-
993
- (defn analyze-file
994
- [f]
995
- (binding [*cljs-ns* 'cljs.user]
996
- (let [res (if (= \/ (first f)) f (io/resource f))]
997
- (assert res (str "Can't find " f " in classpath"))
998
- (with-open [r (io/reader res)]
999
- (let [env {:ns (@namespaces *cljs-ns*) :context :statement :locals {}}
1000
- pbr (clojure.lang.LineNumberingPushbackReader. r)
1001
- eof (Object.)]
1002
- (loop [r (read pbr false eof false)]
1003
- (let [env (assoc env :ns (@namespaces *cljs-ns*))]
1004
- (when-not (identical? eof r)
1005
- (analyze env r)
1006
- (recur (read pbr false eof false))))))))))
1007
-
1008
- (defn forms-seq
1009
- "Seq of forms in a Clojure or ClojureScript file."
1010
- ([f]
1011
- (forms-seq f (java.io.PushbackReader. (io/reader f))))
1012
- ([f ^java.io.PushbackReader rdr]
1013
- (if-let [form (read rdr nil nil)]
1014
- (lazy-seq (cons form (forms-seq f rdr)))
1015
- (.close rdr))))
1016
-
1017
- (defn rename-to-js
1018
- "Change the file extension from .cljs to .js. Takes a File or a
1019
- String. Always returns a String."
1020
- [file-str]
1021
- (clojure.string/replace file-str #".cljs$" ".js"))
1022
-
1023
- (defn mkdirs
1024
- "Create all parent directories for the passed file."
1025
- [^java.io.File f]
1026
- (.mkdirs (.getParentFile (.getCanonicalFile f))))
1027
-
1028
- (defmacro with-core-cljs
1029
- "Ensure that core.cljs has been loaded."
1030
- [& body]
1031
- `(do (when-not (:defs (get @namespaces 'cljs.core))
1032
- (analyze-file "cljs/core.cljs"))
1033
- ~@body))
1034
-
1035
- (defn compile-file* [src dest]
1036
- (with-core-cljs
1037
- (with-open [out ^java.io.Writer (io/make-writer dest {})]
1038
- (binding [*out* out
1039
- *cljs-ns* 'cljs.user]
1040
- (loop [forms (forms-seq src)
1041
- ns-name nil
1042
- deps nil]
1043
- (if (seq forms)
1044
- (let [env {:ns (@namespaces *cljs-ns*) :context :statement :locals {}}
1045
- ast (analyze env (first forms))]
1046
- (do (emit ast)
1047
- (if (= (:op ast) :ns)
1048
- (recur (rest forms) (:name ast) (merge (:uses ast) (:requires ast)))
1049
- (recur (rest forms) ns-name deps))))
1050
- {:ns (or ns-name 'cljs.user)
1051
- :provides [ns-name]
1052
- :requires (if (= ns-name 'cljs.core) (set (vals deps)) (conj (set (vals deps)) 'cljs.core))
1053
- :file dest}))))))
1054
-
1055
- (defn requires-compilation?
1056
- "Return true if the src file requires compilation."
1057
- [^java.io.File src ^java.io.File dest]
1058
- (or (not (.exists dest))
1059
- (> (.lastModified src) (.lastModified dest))))
1060
-
1061
- (defn compile-file
1062
- "Compiles src to a file of the same name, but with a .js extension,
1063
- in the src file's directory.
1064
-
1065
- With dest argument, write file to provided location. If the dest
1066
- argument is a file outside the source tree, missing parent
1067
- directories will be created. The src file will only be compiled if
1068
- the dest file has an older modification time.
1069
-
1070
- Both src and dest may be either a String or a File.
1071
-
1072
- Returns a map containing {:ns .. :provides .. :requires .. :file ..}.
1073
- If the file was not compiled returns only {:file ...}"
1074
- ([src]
1075
- (let [dest (rename-to-js src)]
1076
- (compile-file src dest)))
1077
- ([src dest]
1078
- (let [src-file (io/file src)
1079
- dest-file (io/file dest)]
1080
- (if (.exists src-file)
1081
- (if (requires-compilation? src-file dest-file)
1082
- (do (mkdirs dest-file)
1083
- (compile-file* src-file dest-file))
1084
- {:file dest-file})
1085
- (throw (java.io.FileNotFoundException. (str "The file " src " does not exist.")))))))
1086
-
1087
- (comment
1088
- ;; flex compile-file
1089
- (do
1090
- (compile-file "/tmp/hello.cljs" "/tmp/something.js")
1091
- (slurp "/tmp/hello.js")
1092
-
1093
- (compile-file "/tmp/somescript.cljs")
1094
- (slurp "/tmp/somescript.js")))
1095
-
1096
- (defn path-seq
1097
- [file-str]
1098
- (->> java.io.File/separator
1099
- java.util.regex.Pattern/quote
1100
- re-pattern
1101
- (string/split file-str)))
1102
-
1103
- (defn to-path
1104
- ([parts]
1105
- (to-path parts java.io.File/separator))
1106
- ([parts sep]
1107
- (apply str (interpose sep parts))))
1108
-
1109
- (defn to-target-file
1110
- "Given the source root directory, the output target directory and
1111
- file under the source root, produce the target file."
1112
- [^java.io.File dir ^String target ^java.io.File file]
1113
- (let [dir-path (path-seq (.getAbsolutePath dir))
1114
- file-path (path-seq (.getAbsolutePath file))
1115
- relative-path (drop (count dir-path) file-path)
1116
- parents (butlast relative-path)
1117
- parent-file (java.io.File. ^String (to-path (cons target parents)))]
1118
- (java.io.File. parent-file ^String (rename-to-js (last relative-path)))))
1119
-
1120
- (defn cljs-files-in
1121
- "Return a sequence of all .cljs files in the given directory."
1122
- [dir]
1123
- (filter #(let [name (.getName ^java.io.File %)]
1124
- (and (.endsWith name ".cljs")
1125
- (not= \. (first name))))
1126
- (file-seq dir)))
1127
-
1128
- (defn compile-root
1129
- "Looks recursively in src-dir for .cljs files and compiles them to
1130
- .js files. If target-dir is provided, output will go into this
1131
- directory mirroring the source directory structure. Returns a list
1132
- of maps containing information about each file which was compiled
1133
- in dependency order."
1134
- ([src-dir]
1135
- (compile-root src-dir "out"))
1136
- ([src-dir target-dir]
1137
- (let [src-dir-file (io/file src-dir)]
1138
- (loop [cljs-files (cljs-files-in src-dir-file)
1139
- output-files []]
1140
- (if (seq cljs-files)
1141
- (let [cljs-file (first cljs-files)
1142
- output-file ^java.io.File (to-target-file src-dir-file target-dir cljs-file)
1143
- ns-info (compile-file cljs-file output-file)]
1144
- (recur (rest cljs-files) (conj output-files (assoc ns-info :file-name (.getPath output-file)))))
1145
- output-files)))))
1146
-
1147
- (comment
1148
- ;; compile-root
1149
- ;; If you have a standard project layout with all file in src
1150
- (compile-root "src")
1151
- ;; will produce a mirrored directory structure under "out" but all
1152
- ;; files will be compiled to js.
1153
- )
1154
-
1155
- (comment
1156
-
1157
- ;;the new way - use the REPL!!
1158
- (require '[cljs.compiler :as comp])
1159
- (def repl-env (comp/repl-env))
1160
- (comp/repl repl-env)
1161
- ;having problems?, try verbose mode
1162
- (comp/repl repl-env :verbose true)
1163
- ;don't forget to check for uses of undeclared vars
1164
- (comp/repl repl-env :warn-on-undeclared true)
1165
-
1166
- (test-stuff)
1167
- (+ 1 2 3)
1168
- ([ 1 2 3 4] 2)
1169
- ({:a 1 :b 2} :a)
1170
- ({1 1 2 2} 1)
1171
- (#{1 2 3} 2)
1172
- (:b {:a 1 :b 2})
1173
- ('b '{:a 1 b 2})
1174
-
1175
- (extend-type number ISeq (-seq [x] x))
1176
- (seq 42)
1177
- ;(aset cljs.core.ISeq "number" true)
1178
- ;(aget cljs.core.ISeq "number")
1179
- (satisfies? ISeq 42)
1180
- (extend-type nil ISeq (-seq [x] x))
1181
- (satisfies? ISeq nil)
1182
- (seq nil)
1183
-
1184
- (extend-type default ISeq (-seq [x] x))
1185
- (satisfies? ISeq true)
1186
- (seq true)
1187
-
1188
- (test-stuff)
1189
-
1190
- (array-seq [])
1191
- (defn f [& etc] etc)
1192
- (f)
1193
-
1194
- (in-ns 'cljs.core)
1195
- ;;hack on core
1196
-
1197
-
1198
- (deftype Foo [a] IMeta (-meta [_] (fn [] a)))
1199
- ((-meta (Foo. 42)))
1200
-
1201
- ;;OLD way, don't you want to use the REPL?
1202
- (in-ns 'cljs.compiler)
1203
- (import '[javax.script ScriptEngineManager])
1204
- (def jse (-> (ScriptEngineManager.) (.getEngineByName "JavaScript")))
1205
- (.eval jse cljs.compiler/bootjs)
1206
- (def envx {:ns (@namespaces 'cljs.user) :context :expr :locals '{ethel {:name ethel__123 :init nil}}})
1207
- (analyze envx nil)
1208
- (analyze envx 42)
1209
- (analyze envx "foo")
1210
- (analyze envx 'fred)
1211
- (analyze envx 'fred.x)
1212
- (analyze envx 'ethel)
1213
- (analyze envx 'ethel.x)
1214
- (analyze envx 'my.ns/fred)
1215
- (analyze envx 'your.ns.fred)
1216
- (analyze envx '(if test then else))
1217
- (analyze envx '(if test then))
1218
- (analyze envx '(and fred ethel))
1219
- (analyze (assoc envx :context :statement) '(def test "fortytwo" 42))
1220
- (analyze (assoc envx :context :expr) '(fn* ^{::fields [a b c]} [x y] a y x))
1221
- (analyze (assoc envx :context :statement) '(let* [a 1 b 2] a))
1222
- (analyze (assoc envx :context :statement) '(defprotocol P (bar [a]) (baz [b c])))
1223
- (analyze (assoc envx :context :statement) '(. x y))
1224
- (analyze envx '(fn foo [x] (let [x 42] (js* "~{x}['foobar']"))))
1225
-
1226
- (analyze envx '(ns fred (:require [your.ns :as yn]) (:require-macros [clojure.core :as core])))
1227
- (defmacro js [form]
1228
- `(emit (analyze {:ns (@namespaces 'cljs.user) :context :statement :locals {}} '~form)))
1229
-
1230
- (defn jseval [form]
1231
- (let [js (emits (analyze {:ns (@namespaces 'cljs.user) :context :expr :locals {}}
1232
- form))]
1233
- ;;(prn js)
1234
- (.eval jse (str "print(" js ")"))))
1235
-
1236
- (defn jscapture [form]
1237
- "just grabs the js, doesn't print it"
1238
- (emits (analyze {:ns (@namespaces 'cljs.user) :context :expr :locals {}} form)))
1239
-
1240
- ;; from closure.clj
1241
- (optimize (jscapture '(defn foo [x y] (if true 46 (recur 1 x)))))
1242
-
1243
- (js (if a b c))
1244
- (js (def x 42))
1245
- (js (defn foo [a b] a))
1246
- (js (do 1 2 3))
1247
- (js (let [a 1 b 2 a b] a))
1248
-
1249
- (js (ns fred (:require [your.ns :as yn]) (:require-macros [cljs.core :as core])))
1250
-
1251
- (js (def foo? (fn* ^{::fields [a? b c]} [x y] (if true a? (recur 1 x)))))
1252
- (js (def foo (fn* ^{::fields [a b c]} [x y] (if true a (recur 1 x)))))
1253
- (js (defn foo [x y] (if true x y)))
1254
- (jseval '(defn foo [x y] (if true x y)))
1255
- (js (defn foo [x y] (if true 46 (recur 1 x))))
1256
- (jseval '(defn foo [x y] (if true 46 (recur 1 x))))
1257
- (jseval '(foo 1 2))
1258
- (js (and fred ethel))
1259
- (jseval '(ns fred (:require [your.ns :as yn]) (:require-macros [cljs.core :as core])))
1260
- (js (def x 42))
1261
- (jseval '(def x 42))
1262
- (jseval 'x)
1263
- (jseval '(if 42 1 2))
1264
- (jseval '(or 1 2))
1265
- (jseval '(fn* [x y] (if true 46 (recur 1 x))))
1266
- (.eval jse "print(test)")
1267
- (.eval jse "print(cljs.user.Foo)")
1268
- (.eval jse "print(cljs.user.Foo = function (){\n}\n)")
1269
- (js (def fred 42))
1270
- (js (deftype* Foo [a b-foo c]))
1271
- (jseval '(deftype* Foo [a b-foo c]))
1272
- (jseval '(. (new Foo 1 2 3) b-foo))
1273
- (js (. (new Foo 1 2 3) b))
1274
- (.eval jse "print(new cljs.user.Foo(1, 42, 3).b)")
1275
- (.eval jse "(function (x, ys){return Array.prototype.slice.call(arguments, 1);})(1,2)[0]")
1276
-
1277
- (macroexpand-1 '(cljs.core/deftype Foo [a b c] Fred (fred [x] a) (fred [x y] b) (ethel [x] c) Ethel (foo [] d)))
1278
- (-> (macroexpand-1 '(cljs.core/deftype Foo [a b c] Fred (fred [x] a) (fred [x y] b) (ethel [x] c) Ethel (foo [] d)))
1279
- last last last first meta)
1280
-
1281
- (macroexpand-1 '(cljs.core/extend-type Foo Fred (fred ([x] a) ([x y] b)) (ethel ([x] c)) Ethel (foo ([] d))))
1282
- (js (new foo.Bar 65))
1283
- (js (defprotocol P (bar [a]) (baz [b c])))
1284
- (js (. x y))
1285
- (js (. "fred" (y)))
1286
- (js (. x y 42 43))
1287
- (js (.. a b c d))
1288
- (js (. x (y 42 43)))
1289
- (js (fn [x] x))
1290
- (js (fn ([t] t) ([x y] y) ([ a b & zs] b)))
1291
-
1292
- (js (. (fn foo ([t] t) ([x y] y) ([a b & zs] b)) call nil 1 2))
1293
- (js (fn foo
1294
- ([t] t)
1295
- ([x y] y)
1296
- ([ a b & zs] b)))
1297
-
1298
- (js ((fn foo
1299
- ([t] (foo t nil))
1300
- ([x y] y)
1301
- ([ a b & zs] b)) 1 2 3))
1302
-
1303
-
1304
- (jseval '((fn foo ([t] t) ([x y] y) ([ a b & zs] zs)) 12 13 14 15))
1305
-
1306
- (js (defn foo [this] this))
1307
-
1308
- (js (defn foo [a b c & ys] ys))
1309
- (js ((fn [x & ys] ys) 1 2 3 4))
1310
- (jseval '((fn [x & ys] ys) 1 2 3 4))
1311
- (js (cljs.core/deftype Foo [a b c] Fred (fred [x] a) (fred [x y] a) (ethel [x] c) Ethel (foo [] d)))
1312
- (jseval '(cljs.core/deftype Foo [a b c] Fred (fred [x] a) (fred [x y] a) (ethel [x] c) Ethel (foo [] d)))
1313
-
1314
- (js (do
1315
- (defprotocol Proto (foo [this]))
1316
- (deftype Type [a] Proto (foo [this] a))
1317
- (foo (new Type 42))))
1318
-
1319
- (jseval '(do
1320
- (defprotocol P-roto (foo? [this]))
1321
- (deftype T-ype [a] P-roto (foo? [this] a))
1322
- (foo? (new T-ype 42))))
1323
-
1324
- (js (def x (fn foo [x] (let [x 42] (js* "~{x}['foobar']")))))
1325
- (js (let [a 1 b 2 a b] a))
1326
-
1327
- (doseq [e '[nil true false 42 "fred" fred ethel my.ns/fred your.ns.fred
1328
- (if test then "fooelse")
1329
- (def x 45)
1330
- (do x y y)
1331
- (fn* [x y] x y x)
1332
- (fn* [x y] (if true 46 (recur 1 x)))
1333
- (let* [a 1 b 2 a a] a b)
1334
- (do "do1")
1335
- (loop* [x 1 y 2] (if true 42 (do (recur 43 44))))
1336
- (my.foo 1 2 3)
1337
- (let* [a 1 b 2 c 3] (set! y.s.d b) (new fred.Ethel a b c))
1338
- (let [x (do 1 2 3)] x)
1339
- ]]
1340
- (->> e (analyze envx) emit)
1341
- (newline)))