aboutsummaryrefslogtreecommitdiff
path: root/clojurescript
diff options
context:
space:
mode:
authorChouser <chouser@n01se.net>2008-09-13 03:30:47 +0000
committerChouser <chouser@n01se.net>2008-09-13 03:30:47 +0000
commit25926242b3307e9b4681b44a64a65fe06756ed8f (patch)
tree375428cf163f80c3b725ac3968dccab52023e709 /clojurescript
parent302cf65ab8c9827cd72c39588285cadd69d5f4b3 (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.patch69
-rw-r--r--clojurescript/tojs.clj140
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)