diff options
author | Chouser <chouser@n01se.net> | 2008-09-13 03:30:47 +0000 |
---|---|---|
committer | Chouser <chouser@n01se.net> | 2008-09-13 03:30:47 +0000 |
commit | 25926242b3307e9b4681b44a64a65fe06756ed8f (patch) | |
tree | 375428cf163f80c3b725ac3968dccab52023e709 /clojurescript | |
parent | 302cf65ab8c9827cd72c39588285cadd69d5f4b3 (diff) |
clojurescript: added support for loop, recur, try/catch/finally, and a bunch of constant expressions
Diffstat (limited to 'clojurescript')
-rw-r--r-- | clojurescript/clojurescript-compiler.patch | 69 | ||||
-rw-r--r-- | clojurescript/tojs.clj | 140 |
2 files changed, 177 insertions, 32 deletions
diff --git a/clojurescript/clojurescript-compiler.patch b/clojurescript/clojurescript-compiler.patch index 532c2646..ad80848f 100644 --- a/clojurescript/clojurescript-compiler.patch +++ b/clojurescript/clojurescript-compiler.patch @@ -1,5 +1,5 @@ diff --git a/src/jvm/clojure/lang/Compiler.java b/src/jvm/clojure/lang/Compiler.java -index afb25de..fd3cc49 100644 +index afb25de..832abd8 100644 --- a/src/jvm/clojure/lang/Compiler.java +++ b/src/jvm/clojure/lang/Compiler.java @@ -195,7 +195,7 @@ static final public Var RET_LOCAL_NUM = Var.create(); @@ -95,6 +95,23 @@ index afb25de..fd3cc49 100644 abstract Object val(); public Object eval(){ +@@ -809,11 +808,11 @@ static abstract class FieldExpr extends HostExpr{ + } + + static class InstanceFieldExpr extends FieldExpr implements AssignableExpr{ +- final Expr target; +- final Class targetClass; +- final java.lang.reflect.Field field; +- final String fieldName; +- final int line; ++ public final Expr target; ++ public final Class targetClass; ++ public final java.lang.reflect.Field field; ++ public final String fieldName; ++ public final int line; + final static Method invokeNoArgInstanceMember = Method.getMethod("Object invokeNoArgInstanceMember(Object,String)"); + final static Method setInstanceFieldMethod = Method.getMethod("Object setInstanceField(Object,String,Object)"); + @@ -909,9 +908,9 @@ static class InstanceFieldExpr extends FieldExpr implements AssignableExpr{ static class StaticFieldExpr extends FieldExpr implements AssignableExpr{ @@ -108,6 +125,23 @@ index afb25de..fd3cc49 100644 final static Method getStaticFieldMethod = Method.getMethod("Object getStaticField(String,String)"); final static Method setStaticFieldMethod = Method.getMethod("Object setStaticField(String,String,Object)"); final int line; +@@ -1033,11 +1032,11 @@ static abstract class MethodExpr extends HostExpr{ + } + + static class InstanceMethodExpr extends MethodExpr{ +- final Expr target; +- final String methodName; +- final IPersistentVector args; +- final int line; +- final java.lang.reflect.Method method; ++ public final Expr target; ++ public final String methodName; ++ public final IPersistentVector args; ++ public final int line; ++ public final java.lang.reflect.Method method; + + final static Method invokeInstanceMethodMethod = + Method.getMethod("Object invokeInstanceMethod(Object,String,Object[])"); @@ -1171,11 +1170,11 @@ static class InstanceMethodExpr extends MethodExpr{ static class StaticMethodExpr extends MethodExpr{ @@ -136,6 +170,15 @@ index afb25de..fd3cc49 100644 public ConstantExpr(Object v){ this.v = v; +@@ -1369,7 +1368,7 @@ static class NilExpr extends LiteralExpr{ + final static NilExpr NIL_EXPR = new NilExpr(); + + static class BooleanExpr extends LiteralExpr{ +- final boolean val; ++ public final boolean val; + + + public BooleanExpr(boolean val){ @@ -1404,7 +1403,7 @@ final static BooleanExpr TRUE_EXPR = new BooleanExpr(true); final static BooleanExpr FALSE_EXPR = new BooleanExpr(false); @@ -145,17 +188,15 @@ index afb25de..fd3cc49 100644 public StringExpr(String str){ this.str = str; -@@ -1575,12 +1574,12 @@ static class MonitorExitExpr extends UntypedExpr{ - +@@ -1576,17 +1575,17 @@ static class MonitorExitExpr extends UntypedExpr{ } --static class TryExpr implements Expr{ + static class TryExpr implements Expr{ - final Expr tryExpr; - final Expr finallyExpr; - final PersistentVector catchExprs; - final int retLocal; - final int finallyLocal; -+public static class TryExpr implements Expr{ + public final Expr tryExpr; + public final Expr finallyExpr; + public final PersistentVector catchExprs; @@ -164,6 +205,24 @@ index afb25de..fd3cc49 100644 static class CatchClause{ //final String className; +- final Class c; +- final LocalBinding lb; +- final Expr handler; ++ public final Class c; ++ public final LocalBinding lb; ++ public final Expr handler; + Label label; + Label endLabel; + +@@ -1828,7 +1827,7 @@ static class TryExpr implements Expr{ + //} + + static class ThrowExpr extends UntypedExpr{ +- final Expr excExpr; ++ public final Expr excExpr; + + public ThrowExpr(Expr excExpr){ + this.excExpr = excExpr; @@ -1955,10 +1954,10 @@ static int getMatchingParams(String methodName, ArrayList<Class[]> paramlists, I return matchIdx; } 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) |