aboutsummaryrefslogtreecommitdiff
path: root/clojurescript/tojs.clj
diff options
context:
space:
mode:
Diffstat (limited to 'clojurescript/tojs.clj')
-rw-r--r--clojurescript/tojs.clj140
1 files changed, 113 insertions, 27 deletions
diff --git a/clojurescript/tojs.clj b/clojurescript/tojs.clj
index 867aa3b9..3ec87198 100644
--- a/clojurescript/tojs.clj
+++ b/clojurescript/tojs.clj
@@ -15,7 +15,8 @@
(defmulti tojs (fn [e ctx] (class e)))
(defmethod tojs clojure.lang.Var [e ctx]
- (-> e str (.substring 2) (.replace "/" ".")))
+ (let [{:keys [name ns]} ^e]
+ (str (Compiler/munge (str (.getName ns))) "." (Compiler/munge (str name)))))
(defmethod tojs clojure.lang.Compiler$DefExpr [e ctx]
(str (tojs (.var e) ctx) "=" (tojs (.init e) ctx) ";\n"))
@@ -23,56 +24,60 @@
(defn fnmethod [fm ctx]
(let [lm (into {} (map (fn [[lb lb] i] [lb (str (.name lb) "_" i)])
(.locals fm) (iterate inc 0)))]
- (vstr
- [
- "var " (vec (interpose "," (vals lm))) ";\n"
- (vec (for [lb (.reqParms fm)]
- [(lm lb) "=arguments[" (dec (.idx lb)) "];\n"]))
- (when-let lb (.restParm fm)
- ["var " (lm lb) "=clojure.lang.ArraySeq.create(arguments).drop("
- (count (.reqParms fm)) ");\n"])
- "return (" (tojs (.body fm) (assoc ctx :localmap lm)) ")"])))
+ (vstr [ "var " (vec (interpose "," (vals lm))) ";\n"
+ (vec (for [lb (.reqParms fm)]
+ [(lm lb) "=arguments[" (dec (.idx lb)) "];\n"]))
+ (when-let lb (.restParm fm)
+ ["var " (lm lb) "=clojure.RT.rest_args(arguments,"
+ (count (.reqParms fm)) ");\n"])
+ "var _rtn,_cnt;do{_cnt=0;\n_rtn="
+ (tojs (.body fm) (assoc ctx :localmap lm))
+ ";\n}while(_cnt);return _rtn;"])))
(defmethod tojs clojure.lang.Compiler$FnExpr [e ctx]
- (vstr ["function " (.thisName e) "(){\n"
+ (vstr ["(function " (.simpleName e) "(){\n"
(vec (for [fm (.methods e) :when (not= fm (.variadicMethod e))]
- ["if(arguments.length=" (count (.argLocals fm)) "){\n"
+ ["if(arguments.length==" (count (.argLocals fm)) "){\n"
(fnmethod fm ctx)
"}\n"]))
(if (.variadicMethod e)
[(fnmethod (.variadicMethod e) ctx) "\n"]
["throw \"Wrong number of args passed to: " (.thisName e) "\";\n"])
- "}"]))
+ "})"]))
(defmethod tojs clojure.lang.Compiler$BodyExpr [e ctx]
(apply str (interpose ",\n" (map #(tojs % ctx) (.exprs e)))))
(defmethod tojs clojure.lang.Compiler$LetExpr [e ctx]
(vstr ["("
+ (when (.isLoop e)
+ "(function(){var _rtn,_cnt;do{_cnt=0;\n_rtn=")
(vec (for [bi (.bindingInits e)]
["(" ((:localmap ctx) (.binding bi))
"=" (tojs (.init bi) ctx) "),\n"]))
(tojs (.body e) ctx)
+ (when (.isLoop e)
+ "}while(_cnt);return _rtn;})()")
")"]))
-;(defmethod tojs clojure.lang.Compiler$LetExpr [e ctx]
-; (let [names (map #(.name (.binding %)) (.bindingInits e))
-; inits (map #(.init %) (.bindingInits e))]
-; (vstr ["(function("
-; (vec (interpose ",\n" names))
-; "){\n" (tojs (.body e) ctx) "})(\n "
-; (vec (interpose ",\n " (map tojs inits)))
-; ");\n"])))
-
(defmethod tojs clojure.lang.Compiler$VectorExpr [e ctx]
- (vstr ["clojure.lang.PersistentVector.create(["
+ (vstr ["clojure.RT.lit_vector(["
(vec (interpose "," (map #(tojs % ctx) (.args e))))
"])"]))
+(defn const-str [c]
+ (cond
+ (string? c) (str \" c \")
+ (keyword? c) (str \" c \")
+ (symbol? c) (str \" \' c \")
+ (class? c) (.getCanonicalName c)
+ (list? c) (vstr ["clojure.RT.lit_list(["
+ (vec (interpose "," (map const-str c)))
+ "])"])
+ :else (str c)))
+
(defmethod tojs clojure.lang.Compiler$ConstantExpr [e ctx]
- (if (symbol? (.v e))
- (str \" (.v e) \")
- (str (.v e))))
+ (const-str (.v e)))
(defmethod tojs clojure.lang.Compiler$InvokeExpr [e ctx]
(vstr [(tojs (.fexpr e) ctx)
@@ -86,12 +91,22 @@
(defmethod tojs clojure.lang.Compiler$NilExpr [e ctx]
"null")
+(defmethod tojs clojure.lang.Compiler$EmptyExpr [e ctx]
+ (str (.getCanonicalName (class (.coll e))) ".EMPTY"))
+
(defmethod tojs clojure.lang.Compiler$StringExpr [e ctx]
- (str \" (.str e) \"))
+ (const-str (.str e)))
(defmethod tojs clojure.lang.Compiler$VarExpr [e ctx]
(tojs (.var e) ctx))
+(defmethod tojs clojure.lang.Compiler$TheVarExpr [e ctx]
+ ; XXX not really right
+ (tojs (.var e) ctx))
+
+(defmethod tojs clojure.lang.Compiler$KeywordExpr [e ctx]
+ (const-str (.k e)))
+
(defmethod tojs clojure.lang.Compiler$StaticFieldExpr [e ctx]
(str (.getCanonicalName (.c e)) "." (.fieldName e)))
@@ -100,11 +115,67 @@
(vec (interpose "," (map #(tojs % ctx) (.args e))))
")"]))
+(defmethod tojs clojure.lang.Compiler$NewExpr [e ctx]
+ (vstr ["(new " (.getCanonicalName (.c e)) "("
+ (vec (interpose "," (map #(tojs % ctx) (.args e))))
+ "))"]))
+
+(defmethod tojs clojure.lang.Compiler$InstanceMethodExpr [e ctx]
+ (vstr ["(" (tojs (.target e) ctx) ")." (.methodName e)
+ "(" (vec (interpose "," (map #(tojs % ctx) (.args e)))) ")"]))
+
+(defmethod tojs clojure.lang.Compiler$InstanceFieldExpr [e ctx]
+ (vstr ["(" (tojs (.target e) ctx) ")." (.fieldName e)]))
+
(defmethod tojs clojure.lang.Compiler$IfExpr [e ctx]
(str "(" (tojs (.testExpr e) ctx)
"?" (tojs (.thenExpr e) ctx)
":" (tojs (.elseExpr e) ctx) ")"))
+(defmethod tojs clojure.lang.Compiler$RecurExpr [e ctx]
+ (vstr ["(_cnt=0"
+ (vec (map #(str ",_t" %2 "=" (tojs %1 ctx)) (.args e) (iterate inc 0)))
+ (vec (map #(str "," ((:localmap ctx) %1) "=_t" %2)
+ (.loopLocals e) (iterate inc 0)))
+ ")"]))
+
+(defmethod tojs clojure.lang.Compiler$MapExpr [e ctx]
+ (vstr ["clojure.lang.HashMap.create(["
+ (vec (interpose "," (map #(tojs % ctx) (.keyvals e))))
+ "])"]))
+
+(defmethod tojs clojure.lang.Compiler$SetExpr [e ctx]
+ (vstr ["clojure.lang.HashSet.create(["
+ (vec (interpose "," (map #(tojs % ctx) (.keys e))))
+ "])"]))
+
+(defmethod tojs clojure.lang.Compiler$BooleanExpr [e ctx]
+ (if (.val e) "true" "false"))
+
+(defmethod tojs clojure.lang.Compiler$AssignExpr [e ctx]
+ (vstr ["(" (tojs (.target e) ctx) "=" (tojs (.val e) ctx) ")"]))
+
+(defmethod tojs clojure.lang.Compiler$ThrowExpr [e ctx]
+ (vstr ["(function(){throw " (tojs (.excExpr e) ctx) "})()"]))
+
+(defmethod tojs clojure.lang.Compiler$TryExpr [e ctx]
+ (vstr ["(function(){try{var _rtn="
+ (tojs (.tryExpr e) ctx)
+ "}"
+ (when (seq (.catchExprs e))
+ (when (not= 1 (count (.catchExprs e)))
+ (throw (Exception. "tojs only supports one catch clause per try")))
+ (let [cc (first (.catchExprs e))]
+ ["\ncatch(" ((:localmap ctx) (.lb cc)) "){_rtn="
+ (tojs (.handler e) ctx)
+ "}"]))
+ (when (.finallyExpr e)
+ ["\nfinally{"
+ (tojs (.finallyExpr e) ctx)
+ "}"])
+ "})()"]))
+
+
(defn formtojs [f]
(tojs (Compiler/analyze Compiler$C/STATEMENT f) {}))
@@ -112,6 +183,14 @@
(let [boot "/home/chouser/build/clojure/src/clj/clojure/boot.clj"
bootreader (java.io.PushbackReader. (ds/reader boot))
tmpns (create-ns 'tmp)]
+ (binding [*ns* tmpns]
+ (eval '(def identical? clojure/identical?))
+ (eval '(def *ns* nil))
+ (eval '(def *in* nil))
+ (eval '(def *out* nil))
+ (eval '(def *flush-on-newline* nil))
+ (eval '(def *print-readably* nil))
+ (eval '(def *agent* nil)))
(loop []
(when-let f (read bootreader)
(println "======")
@@ -142,4 +221,11 @@
(prn a))
(prn a))))
+(println (formtojs
+ '(defn x [] (conj [] (loop [i 5] (if (pos? i) (recur (- i 2)) i))))))
+
+(println (formtojs '(binding [*out* 5] (set! *out* 10))))
+(println (formtojs '(.replace "a/b/c" "/" ".")))
+(println (formtojs '(list '(1 "str" 'sym :key) 4 "str2" 6 #{:set 9 8})))
+
(testboot)