diff options
author | Chouser <chouser@n01se.net> | 2008-09-19 17:17:34 +0000 |
---|---|---|
committer | Chouser <chouser@n01se.net> | 2008-09-19 17:17:34 +0000 |
commit | b0d0dd38cc3cdf8673d16009621501f10a25e023 (patch) | |
tree | d223d96abfb66723d43ad32cfbac33fd0ce6368c /clojurescript | |
parent | a67ffc6bf63f54f63d033763dd18341d5e15f156 (diff) |
ClojureScript: boot.clj can now be converted to syntactically correct JavaScript.
Diffstat (limited to 'clojurescript')
-rw-r--r-- | clojurescript/clj.js | 72 | ||||
-rw-r--r-- | clojurescript/clojurescript-compiler.patch | 105 | ||||
-rw-r--r-- | clojurescript/t04.cljs | 15 | ||||
-rw-r--r-- | clojurescript/t04.html | 12 | ||||
-rw-r--r-- | clojurescript/tojs.clj | 102 |
5 files changed, 203 insertions, 103 deletions
diff --git a/clojurescript/clj.js b/clojurescript/clj.js index 5d212003..553f342d 100644 --- a/clojurescript/clj.js +++ b/clojurescript/clj.js @@ -1,10 +1,21 @@ -clojure = { +function clojure_merge( t, s ) { + for( var i in s ) { + t[ i ] = s[ i ]; + } + return t; +}; + +function clojure_Namespace( m ) { + clojure_merge( this, m || {} ); +}; + +clojure = new clojure_Namespace({ in_ns: function(s) { var nsparts = s.substring(1).split('.'); var base = window; for( var i = 0; i < nsparts.length; ++i ) { if( ! base[nsparts[i]] ) { - base[nsparts[i]] = {}; + base[nsparts[i]] = new clojure.lang.Namespace(); } base = base[nsparts[i]]; } @@ -22,6 +33,8 @@ clojure = { throw ("Don't know how to create ISeq from: " + (typeof coll) + " " + coll.constructor.name); }, + apply: function( f, args ) { + }, first: function(x) { if( x.first ) return x.first(); var seq = clojure.seq( x ); @@ -35,6 +48,9 @@ clojure = { return seq.rest(); }, second: function(x) { return clojure.first(clojure.rest(x)); }, + instance_QMARK_: function( c, o ) { + return o !== null && o.constructor == c; + }, prn: function() { var args = []; for( var i = 0; i < arguments.length; ++i ) { @@ -50,13 +66,22 @@ clojure = { } return clojure.lang.ArraySeq.create( pairs ); }, + assoc: function( coll, key, val ) { + if( coll === null ) + return new clojure.lang.PersistentArrayMap([key, val]); + return coll.assoc( key, val ); + }, count: function(x) { if( x === null ) return 0; if( x.count ) return x.count(); if( x.length != undefined ) return x.length; throw ("count not supported on: " + (typeof x) + " " + x.constructor); }, + identical_QMARK_: function( a, b ) { + return a === b; + }, JS: { + merge: clojure_merge, resolveVar: function( sym, ctxns ) { return ctxns[ sym ] || clojure[ sym ] || window[ sym ]; }, @@ -64,6 +89,13 @@ clojure = { var v = new clojure.lang.Var( ns, name ); ns["_var_" + name] = v; v.push( init ); + return v; + }, + rest_args: function( args, i ) { + return clojure.lang.ArraySeq.create( null, args, i ); + }, + lit_list: function( a ) { + return clojure.lang.ArraySeq.create( null, a, 0 ); }, ObjSeq: { create: function( obj ) { @@ -83,9 +115,10 @@ clojure = { }, Util: { equal: function(x,y) { return x == y; } - } + }, + IReduce: {} } -}; +}); clojure.lang.ArraySeq = function( _meta, a, i ) { this._meta = _meta; @@ -98,7 +131,7 @@ clojure.lang.ArraySeq.create = function( a ) { return new clojure.lang.ArraySeq( null, a, 0 ); } else { - return nil; + return null; } }; @@ -196,6 +229,14 @@ clojure.lang.Var.prototype.set = function( val ) { this.push( val ); }; +clojure.lang.Var.prototype.hasRoot = function() { + return this.stack.length > 0; +}; + +clojure.lang.Var.prototype.setMacro = function() { + this.macro = true; +}; + clojure.lang.Var.stack = []; clojure.lang.Var.pushThreadBindings = function( m ) { @@ -214,3 +255,24 @@ clojure.lang.Var.popThreadBindings = function() { vars[i].pop(); } }; + +clojure.lang.PersistentList = { creator: function() { + var real = clojure.lang.PersistentList.creator; + if( real == arguments.callee ) { + throw "Not yet implemented: clojure.lang.PersistentList.creator"; + } + return real.apply( arguments ); +}}; + +clojure.lang.Namespace = clojure_Namespace; + +clojure.lang.Namespace.find = function( s ) { + return window[ s.substring(1) ]; +}; + +clojure.lang.Namespace.prototype.getMappings = function() { + return this; +}; + +delete clojure_merge; +delete clojure_Namespace; diff --git a/clojurescript/clojurescript-compiler.patch b/clojurescript/clojurescript-compiler.patch index 6d7fba99..709abdae 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 e087d08..400b34a 100644 +index a44aa2e..aae4cc9 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(); @@ -20,24 +20,26 @@ index e087d08..400b34a 100644 public Class getJavaClass(){ throw new IllegalArgumentException("Has no Java class"); -@@ -256,11 +256,11 @@ static Symbol resolveSymbol(Symbol sym){ - +@@ -257,12 +257,12 @@ static Symbol resolveSymbol(Symbol sym){ } --static class DefExpr implements Expr{ + static class DefExpr implements Expr{ - final Var var; - final Expr init; - final Expr meta; - final boolean initProvided; -+public static class DefExpr implements Expr{ +- final String source; +- final int line; + public final Var var; + public final Expr init; + public final Expr meta; + public final boolean initProvided; ++ public final String source; ++ public final int line; final static Method bindRootMethod = Method.getMethod("void bindRoot(Object)"); final static Method setTagMethod = Method.getMethod("void setTag(clojure.lang.Symbol)"); final static Method setMetaMethod = Method.getMethod("void setMeta(clojure.lang.IPersistentMap)"); -@@ -346,10 +346,9 @@ static class DefExpr implements Expr{ +@@ -361,10 +361,9 @@ static class DefExpr implements Expr{ } } @@ -51,7 +53,7 @@ index e087d08..400b34a 100644 public AssignExpr(AssignableExpr target, Expr val){ this.target = target; -@@ -385,9 +384,9 @@ static class AssignExpr implements Expr{ +@@ -400,9 +399,9 @@ static class AssignExpr implements Expr{ } } @@ -64,7 +66,7 @@ index e087d08..400b34a 100644 final static Method getMethod = Method.getMethod("Object get()"); final static Method setMethod = Method.getMethod("Object set(Object)"); -@@ -431,8 +430,8 @@ static class VarExpr implements Expr, AssignableExpr{ +@@ -446,8 +445,8 @@ static class VarExpr implements Expr, AssignableExpr{ } } @@ -75,7 +77,7 @@ index e087d08..400b34a 100644 public TheVarExpr(Var var){ this.var = var; -@@ -467,8 +466,8 @@ static class TheVarExpr implements Expr{ +@@ -482,8 +481,8 @@ static class TheVarExpr implements Expr{ } } @@ -86,7 +88,7 @@ index e087d08..400b34a 100644 public KeywordExpr(Keyword k){ this.k = k; -@@ -494,7 +493,7 @@ static class KeywordExpr implements Expr{ +@@ -509,7 +508,7 @@ static class KeywordExpr implements Expr{ } } @@ -95,7 +97,7 @@ index e087d08..400b34a 100644 abstract Object val(); public Object eval(){ -@@ -814,11 +813,11 @@ static abstract class FieldExpr extends HostExpr{ +@@ -830,11 +829,11 @@ static abstract class FieldExpr extends HostExpr{ } static class InstanceFieldExpr extends FieldExpr implements AssignableExpr{ @@ -112,7 +114,7 @@ index e087d08..400b34a 100644 final static Method invokeNoArgInstanceMember = Method.getMethod("Object invokeNoArgInstanceMember(Object,String)"); final static Method setInstanceFieldMethod = Method.getMethod("Object setInstanceField(Object,String,Object)"); -@@ -914,9 +913,9 @@ static class InstanceFieldExpr extends FieldExpr implements AssignableExpr{ +@@ -930,9 +929,9 @@ static class InstanceFieldExpr extends FieldExpr implements AssignableExpr{ static class StaticFieldExpr extends FieldExpr implements AssignableExpr{ //final String className; @@ -125,41 +127,45 @@ index e087d08..400b34a 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; -@@ -1038,11 +1037,11 @@ static abstract class MethodExpr extends HostExpr{ +@@ -1054,12 +1053,12 @@ static abstract class MethodExpr extends HostExpr{ } static class InstanceMethodExpr extends MethodExpr{ - final Expr target; - final String methodName; - final IPersistentVector args; +- final String source; - final int line; - final java.lang.reflect.Method method; + public final Expr target; + public final String methodName; + public final IPersistentVector args; ++ public final String source; + public final int line; + public final java.lang.reflect.Method method; final static Method invokeInstanceMethodMethod = Method.getMethod("Object invokeInstanceMethod(Object,String,Object[])"); -@@ -1176,11 +1175,11 @@ static class InstanceMethodExpr extends MethodExpr{ +@@ -1205,12 +1204,12 @@ static class InstanceMethodExpr extends MethodExpr{ static class StaticMethodExpr extends MethodExpr{ //final String className; - final Class c; - final String methodName; - final IPersistentVector args; +- final String source; - final int line; - final java.lang.reflect.Method method; + public final Class c; + public final String methodName; + public final IPersistentVector args; ++ public final String source; + public final int line; + public final java.lang.reflect.Method method; final static Method invokeStaticMethodMethod = Method.getMethod("Object invokeStaticMethod(String,String,Object[])"); -@@ -1285,12 +1284,36 @@ static class StaticMethodExpr extends MethodExpr{ +@@ -1326,12 +1325,36 @@ static class StaticMethodExpr extends MethodExpr{ } } @@ -198,7 +204,7 @@ index e087d08..400b34a 100644 public ConstantExpr(Object v){ this.v = v; -@@ -1374,7 +1397,7 @@ static class NilExpr extends LiteralExpr{ +@@ -1415,7 +1438,7 @@ static class NilExpr extends LiteralExpr{ final static NilExpr NIL_EXPR = new NilExpr(); static class BooleanExpr extends LiteralExpr{ @@ -207,7 +213,7 @@ index e087d08..400b34a 100644 public BooleanExpr(boolean val){ -@@ -1409,7 +1432,7 @@ final static BooleanExpr TRUE_EXPR = new BooleanExpr(true); +@@ -1450,7 +1473,7 @@ final static BooleanExpr TRUE_EXPR = new BooleanExpr(true); final static BooleanExpr FALSE_EXPR = new BooleanExpr(false); static class StringExpr extends LiteralExpr{ @@ -216,22 +222,25 @@ index e087d08..400b34a 100644 public StringExpr(String str){ this.str = str; -@@ -1581,17 +1604,17 @@ static class MonitorExitExpr extends UntypedExpr{ +@@ -1621,18 +1644,18 @@ 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; + public final int retLocal; + public final int finallyLocal; - static class CatchClause{ +- static class CatchClause{ ++ public static class CatchClause{ //final String className; - final Class c; - final LocalBinding lb; @@ -242,7 +251,7 @@ index e087d08..400b34a 100644 Label label; Label endLabel; -@@ -1833,7 +1856,7 @@ static class TryExpr implements Expr{ +@@ -1874,7 +1897,7 @@ static class TryExpr implements Expr{ //} static class ThrowExpr extends UntypedExpr{ @@ -251,7 +260,7 @@ index e087d08..400b34a 100644 public ThrowExpr(Expr excExpr){ this.excExpr = excExpr; -@@ -1960,10 +1983,10 @@ static int getMatchingParams(String methodName, ArrayList<Class[]> paramlists, I +@@ -2001,10 +2024,10 @@ static int getMatchingParams(String methodName, ArrayList<Class[]> paramlists, I return matchIdx; } @@ -266,7 +275,7 @@ index e087d08..400b34a 100644 final static Method invokeConstructorMethod = Method.getMethod("Object invokeConstructor(Class,Object[])"); final static Method forNameMethod = Method.getMethod("Class classForName(String)"); -@@ -2175,9 +2198,9 @@ static class NewExpr implements Expr{ +@@ -2216,9 +2239,9 @@ static class NewExpr implements Expr{ // } //} @@ -279,7 +288,7 @@ index e087d08..400b34a 100644 final static Type IOBJ_TYPE = Type.getType(IObj.class); final static Method withMetaMethod = Method.getMethod("clojure.lang.IObj withMeta(clojure.lang.IPersistentMap)"); -@@ -2212,11 +2235,11 @@ static class MetaExpr implements Expr{ +@@ -2253,11 +2276,11 @@ static class MetaExpr implements Expr{ } } @@ -296,7 +305,7 @@ index e087d08..400b34a 100644 public IfExpr(int line, Expr testExpr, Expr thenExpr, Expr elseExpr){ -@@ -2341,8 +2364,8 @@ static public String munge(String name){ +@@ -2382,8 +2405,8 @@ static public String munge(String name){ return sb.toString(); } @@ -307,7 +316,7 @@ index e087d08..400b34a 100644 final static Type HASHMAP_TYPE = Type.getType(PersistentHashMap.class); final static Type HASHSET_TYPE = Type.getType(PersistentHashSet.class); final static Type VECTOR_TYPE = Type.getType(PersistentVector.class); -@@ -2393,8 +2416,8 @@ static class EmptyExpr implements Expr{ +@@ -2434,8 +2457,8 @@ static class EmptyExpr implements Expr{ } } @@ -318,7 +327,7 @@ index e087d08..400b34a 100644 final static Method arrayToListMethod = Method.getMethod("clojure.lang.ISeq arrayToList(Object[])"); -@@ -2426,8 +2449,8 @@ static class ListExpr implements Expr{ +@@ -2467,8 +2490,8 @@ static class ListExpr implements Expr{ } @@ -329,7 +338,7 @@ index e087d08..400b34a 100644 final static Method mapMethod = Method.getMethod("clojure.lang.IPersistentMap map(Object[])"); -@@ -2475,8 +2498,8 @@ static class MapExpr implements Expr{ +@@ -2516,8 +2539,8 @@ static class MapExpr implements Expr{ } } @@ -340,7 +349,7 @@ index e087d08..400b34a 100644 final static Method setMethod = Method.getMethod("clojure.lang.IPersistentSet set(Object[])"); -@@ -2523,8 +2546,8 @@ static class SetExpr implements Expr{ +@@ -2564,8 +2587,8 @@ static class SetExpr implements Expr{ } } @@ -351,24 +360,24 @@ index e087d08..400b34a 100644 final static Method vectorMethod = Method.getMethod("clojure.lang.IPersistentVector vector(Object[])"); -@@ -2568,11 +2591,11 @@ static class VectorExpr implements Expr{ - +@@ -2610,11 +2633,11 @@ static class VectorExpr implements Expr{ } --static class InvokeExpr implements Expr{ + static class InvokeExpr implements Expr{ - final Expr fexpr; - final Object tag; - final IPersistentVector args; - final int line; -+public static class InvokeExpr implements Expr{ +- final String source; + public final Expr fexpr; + public final Object tag; + public final IPersistentVector args; + public final int line; ++ public final String source; - public InvokeExpr(int line, Symbol tag, Expr fexpr, IPersistentVector args){ - this.fexpr = fexpr; -@@ -2693,7 +2716,7 @@ static public class FnExpr implements Expr{ + public InvokeExpr(String source, int line, Symbol tag, Expr fexpr, IPersistentVector args){ + this.source = source; +@@ -2746,7 +2769,7 @@ static public class FnExpr implements Expr{ String internalName; String thisName; Type fntype; @@ -377,7 +386,7 @@ index e087d08..400b34a 100644 //localbinding->itself IPersistentMap closes = PersistentHashMap.EMPTY; //Keyword->KeywordExpr -@@ -2703,6 +2726,20 @@ static public class FnExpr implements Expr{ +@@ -2756,6 +2779,20 @@ static public class FnExpr implements Expr{ int line; PersistentVector constants; int constantsID; @@ -398,7 +407,7 @@ index e087d08..400b34a 100644 final static Method kwintern = Method.getMethod("clojure.lang.Keyword intern(String, String)"); final static Method symcreate = Method.getMethod("clojure.lang.Symbol create(String)"); -@@ -3139,10 +3176,10 @@ enum PSTATE{ +@@ -3192,10 +3229,10 @@ enum PSTATE{ } @@ -411,7 +420,7 @@ index e087d08..400b34a 100644 //localbinding->localbinding IPersistentMap locals = null; //localbinding->localbinding -@@ -3154,6 +3191,14 @@ static class FnMethod{ +@@ -3207,6 +3244,14 @@ static class FnMethod{ int maxLocal = 0; int line; PersistentHashSet localsUsedInCatchFinally = PersistentHashSet.EMPTY; @@ -426,7 +435,7 @@ index e087d08..400b34a 100644 public FnMethod(FnExpr fn, FnMethod parent){ this.parent = parent; -@@ -3293,12 +3338,12 @@ static class FnMethod{ +@@ -3346,12 +3391,12 @@ static class FnMethod{ } } @@ -445,7 +454,7 @@ index e087d08..400b34a 100644 public LocalBinding(int num, Symbol sym, Symbol tag, Expr init) throws Exception{ if(maybePrimitiveType(init) != null && tag != null) -@@ -3329,9 +3374,9 @@ static class LocalBinding{ +@@ -3382,9 +3427,9 @@ static class LocalBinding{ } } @@ -458,7 +467,7 @@ index e087d08..400b34a 100644 public LocalBindingExpr(LocalBinding b, Symbol tag) throws Exception{ if(b.getPrimitiveType() != null && tag != null) -@@ -3366,8 +3411,9 @@ static class LocalBindingExpr implements Expr, MaybePrimitiveExpr{ +@@ -3419,8 +3464,9 @@ static class LocalBindingExpr implements Expr, MaybePrimitiveExpr{ } @@ -469,7 +478,7 @@ index e087d08..400b34a 100644 public BodyExpr(PersistentVector exprs){ this.exprs = exprs; -@@ -3427,9 +3473,11 @@ static class BodyExpr implements Expr{ +@@ -3480,9 +3526,11 @@ static class BodyExpr implements Expr{ } } @@ -482,7 +491,7 @@ index e087d08..400b34a 100644 public BindingInit(LocalBinding binding, Expr init){ this.binding = binding; -@@ -3437,10 +3485,10 @@ static class BindingInit{ +@@ -3490,10 +3538,10 @@ static class BindingInit{ } } @@ -497,7 +506,7 @@ index e087d08..400b34a 100644 public LetExpr(PersistentVector bindingInits, Expr body, boolean isLoop){ this.bindingInits = bindingInits; -@@ -3563,9 +3611,9 @@ static class LetExpr implements Expr{ +@@ -3616,9 +3664,9 @@ static class LetExpr implements Expr{ } } @@ -510,7 +519,7 @@ index e087d08..400b34a 100644 public RecurExpr(IPersistentVector loopLocals, IPersistentVector args){ this.loopLocals = loopLocals; -@@ -3667,7 +3715,7 @@ private static int getAndIncLocalNum(){ +@@ -3720,7 +3768,7 @@ private static int getAndIncLocalNum(){ return num; } @@ -519,7 +528,7 @@ index e087d08..400b34a 100644 return analyze(context, form, null); } -@@ -3963,6 +4011,8 @@ private static Expr analyzeSymbol(Symbol sym) throws Exception{ +@@ -4021,6 +4069,8 @@ private static Expr analyzeSymbol(Symbol sym) throws Exception{ } else if(o instanceof Class) return new ConstantExpr(o); @@ -528,7 +537,7 @@ index e087d08..400b34a 100644 throw new Exception("Unable to resolve symbol: " + sym + " in this context"); -@@ -4012,7 +4062,16 @@ static public Object resolveIn(Namespace n, Symbol sym) throws Exception{ +@@ -4074,7 +4124,16 @@ static public Object resolveIn(Namespace n, Symbol sym) throws Exception{ { Object o = n.getMapping(sym); if(o == null) diff --git a/clojurescript/t04.cljs b/clojurescript/t04.cljs new file mode 100644 index 00000000..4574bdff --- /dev/null +++ b/clojurescript/t04.cljs @@ -0,0 +1,15 @@ +; This may look like Clojure, but it's actually ClojureScript. Macros +; may be used here, but should be defined elsewhere, in regular +; Clojure code. +(ns n01se) + +(defn script-src [] + (for [elem (.getElementsByTagName document "script")] + (do + (prn :next) + (if-let src (.src elem) + src + "--none--")))) + +(doseq src (take 2 (script-src)) + (prn src)) diff --git a/clojurescript/t04.html b/clojurescript/t04.html new file mode 100644 index 00000000..5786a8c8 --- /dev/null +++ b/clojurescript/t04.html @@ -0,0 +1,12 @@ +<html> + <body> + <textarea rows="24" cols="80" id="ta"></textarea> + <script type="text/javascript"> + var ta = document.getElementById( 'ta' ); + function print( x ) { ta.value += x + "\n"; } + </script> + <script type="text/javascript" src="clj.js"></script> + <script type="text/javascript" src="boot.js"></script> + <script type="text/javascript" src="t04.js"></script> + </body> +</html> diff --git a/clojurescript/tojs.clj b/clojurescript/tojs.clj index 4addd141..fa8f4fde 100644 --- a/clojurescript/tojs.clj +++ b/clojurescript/tojs.clj @@ -12,7 +12,10 @@ (lvl v) (str sb))) -(def *has-recur*) +(def *debug-fn-names* true) +(def *debug-comments* true) + +(def *has-recur*) ; used internally (defmulti tojs (fn [e ctx] (class e))) @@ -33,8 +36,8 @@ (for [lb (.reqParms fm)] [(lm lb) "=arguments[" (dec (.idx lb)) "]"])) (when-let lb (.restParm fm) - [(lm lb) "=clojure.JS.rest_args(arguments," - (count (.reqParms fm)) ")"]))] + [(str (lm lb) "=clojure.JS.rest_args(arguments," + (count (.reqParms fm)) ")")]))] (.reqParms maxm) (vstr [(when (seq inits) [(apply vector "var " (interpose "," inits)) ";\n"]) @@ -53,7 +56,10 @@ last val)) manym (< 1 (count (.methods e))) newctx (assoc ctx :fnname (.thisName e))] - (vstr ["(function(" + (vstr ["(function" + (when *debug-fn-names* + [" __" (.replaceAll (.name e) "[\\W_]+" "_")]) + "(" (vec (interpose "," (for [lb (.reqParms maxm)] [(.name lb) "_" (.idx lb)]))) "){\n" @@ -75,10 +81,12 @@ "=" (tojs (.init bi) ctx) ")"])))] (if (.isLoop e) (binding [*has-recur* false] - (vstr ["((function(){var _rtn,_cnt;" - inits ";" - "do{_cnt=0;\n_rtn=" (tojs (.body e) ctx) - "}while(_cnt);return _rtn;})())"])) + (vstr ["((function" + (when *debug-fn-names* " __loop") + "(){var _rtn,_cnt;" + inits ";" + "do{_cnt=0;\n_rtn=" (tojs (.body e) ctx) + "}while(_cnt);return _rtn;})())"])) (vstr ["(" inits ",\n" (tojs (.body e) ctx) ")"])))) (defmethod tojs clojure.lang.Compiler$VectorExpr [e ctx] @@ -88,27 +96,30 @@ (defn const-str [c] (cond - (string? c) (str \" c \") - (keyword? c) (str \" c \") + (or (instance? Character c) + (keyword? c) + (string? c)) (pr-str (str c)) (symbol? c) (str \" \' c \") (class? c) (.getCanonicalName c) (list? c) (vstr ["clojure.JS.lit_list([" (vec (interpose "," (map const-str c))) "])"]) + (fn? c) (str \" c \") :else (str c))) (defmethod tojs clojure.lang.Compiler$ConstantExpr [e ctx] (const-str (.v e))) +(defn var-munge [x] + (-> x str Compiler/munge (.replace "." "_DOT_"))) (defn var-parts [e] (let [{:keys [name ns]} ^(.var e)] - [(Compiler/munge (str (.getName ns))) - (Compiler/munge (str name))])) + [(Compiler/munge (str (.getName ns))) (var-munge name)])) (defmethod tojs clojure.lang.Compiler$UnresolvedVarExpr [e ctx] (vstr ["clojure.JS.resolveVar(\"" - (Compiler/munge (name (.symbol e))) "\"," + (var-munge (name (.symbol e))) "\"," (Compiler/munge (name (.name *ns*))) ")"])) (defmethod tojs clojure.lang.Compiler$VarExpr [e ctx] @@ -196,18 +207,22 @@ (if (.val e) "true" "false")) (defmethod tojs clojure.lang.Compiler$ThrowExpr [e ctx] - (vstr ["(function(){throw " (tojs (.excExpr e) ctx) "})()"])) + (vstr ["(function" + (when *debug-fn-names* " __throw") + "(){throw " (tojs (.excExpr e) ctx) "})()"])) (defmethod tojs clojure.lang.Compiler$TryExpr [e ctx] - (vstr ["(function(){try{var _rtn=" + (vstr ["(function" + (when *debug-fn-names* " __try") + "(){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) + (tojs (.handler cc) ctx) "}"])) (when (.finallyExpr e) ["\nfinally{" @@ -215,47 +230,35 @@ "}"]) "})()"])) +(def skip-defs '#{seq instance? assoc floats doubles ints longs + global-hierarchy apply}) (defn formtojs [f] (binding [*allow-unresolved-vars* true] - (str (tojs (Compiler/analyze Compiler$C/STATEMENT `((fn [] ~f))) - {:localmap {}}) - ";\n"))) - -(defn testboot [] - (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 "======") - (prn f) - (println "---") - (binding [*ns* tmpns] - (println (formtojs f)) - (eval f)) - (recur))))) + (let [expr (Compiler/analyze Compiler$C/STATEMENT `((fn [] ~f))) + mainexpr (-> expr .fexpr .methods first .body .exprs first)] + (when-not (or (and (instance? clojure.lang.Compiler$DefExpr mainexpr) + (skip-defs (:name ^(.var mainexpr)))) + (and (instance? clojure.lang.Compiler$BodyExpr mainexpr) + (instance? clojure.lang.Compiler$DefExpr (first (.exprs mainexpr))) + (skip-defs (:name ^(.var (first (.exprs mainexpr))))))) + (str (tojs expr {:localmap {}}) ";"))))) (defn filetojs [filename] (let [reader (java.io.PushbackReader. (ds/reader filename))] (binding [*ns* (create-ns 'tmp)] (loop [] (when-let f (try (read reader) (catch Exception e nil)) - (println "//======") - (print "//") - (prn f) - (println "//---") - (println (formtojs f)) - (when (= 'ns (first f)) - (eval f)) + (when-let js (formtojs f) + (when *debug-comments* + (println "\n//======") + (print "//") + (prn f) + (println "//---")) + (println (formtojs f)) + (when (or (= 'ns (first f)) + (= 'in-ns (first f))) + (eval f))) (recur)))))) (defn simple-tests [] @@ -289,6 +292,5 @@ (println (formtojs '(fn forever[] (loop [] (recur)))))) ;(simple-tests) -;(testboot) (filetojs (first *command-line-args*)) |