diff options
-rw-r--r-- | clojurescript/clj.js | 148 | ||||
-rw-r--r-- | clojurescript/clojurescript-compiler.patch | 128 | ||||
-rw-r--r-- | clojurescript/t01.cljs | 13 | ||||
-rw-r--r-- | clojurescript/t01.html | 12 | ||||
-rw-r--r-- | clojurescript/tojs.clj | 132 |
5 files changed, 349 insertions, 84 deletions
diff --git a/clojurescript/clj.js b/clojurescript/clj.js new file mode 100644 index 00000000..4fd572c2 --- /dev/null +++ b/clojurescript/clj.js @@ -0,0 +1,148 @@ +clojure = { + in_ns: function(s) { + var ns = s.substring(1); + if( ! window[ns] ) { + window[ns] = {}; + } + }, + refer: function(s) {}, + seq: function(coll){ + if( coll === null ) return null; + else if( coll.seq ) return coll.seq(); + //else if( coll.constructor === String ) + // return clojure.lang.StringSeq.create(coll); + else if( typeof coll.length == typeof 0 ) + return clojure.lang.ArraySeq.create(coll); + else if( typeof coll === typeof {} ) + return clojure.JS.ObjSeq.create(coll); + throw ("Don't know how to create ISeq from: " + + (typeof coll) + " " + coll.constructor.name); + }, + first: function(x) { + if( x.first ) return x.first(); + var seq = clojure.seq( x ); + if( seq === null ) return null; + return seq.first(); + }, + rest: function(x) { + if( x.rest ) return x.rest(); + var seq = clojure.seq( x ); + if( seq === null ) return null; + return seq.rest(); + }, + second: function(x) { return clojure.first(clojure.rest(x)); }, + prn: print, + 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); + }, + JS: { + resolveVar: function( symns, symnm, ctxns ) { + if( symns ) { + return symns[ symnm ]; + } + else { + return ctxns[ symnm ] || clojure[ symnm ] || window[ symnm ]; + } + }, + ObjSeq: { + create: function( obj ) { + var pairs = []; + for( var i in obj ) { + pairs.push( [i, obj[i]] ); + } + return clojure.lang.ArraySeq.create( pairs ); + } + } + }, + lang: {} +}; + +clojure.lang.ArraySeq = function( _meta, a, i ) { + this._meta = _meta; + this.a = a; + this.i = i; +}; + +clojure.lang.ArraySeq.create = function( a ) { + if( a && a.length ) { + return new clojure.lang.ArraySeq( null, a, 0 ); + } + else { + return nil; + } +}; + +clojure.lang.ArraySeq.prototype.first = function() { + return this.a[this.i]; +}; + +clojure.lang.ArraySeq.prototype.rest = function() { + if( this.i + 1 < this.a.length ) + return new clojure.lang.ArraySeq( this._meta, this.a, this.i + 1 ); + return null; +}; + +clojure.lang.ArraySeq.prototype.count = function() { + return this.a.length - this.i; +}; + +clojure.lang.ArraySeq.prototype.index = function() { + return this.i; +}; + +clojure.lang.ArraySeq.prototype.withMeta = function( _meta ) { + return new clojure.lang.ArraySeq( _meta, this.array, this.i ); +}; + +clojure.lang.ArraySeq.prototype.reduce = function( fn, start ) { + var ret = (start === undefined) ? this.a[0] : fn(start, this.a[0]); + for( var x = this.i + 1; x < this.a.length; ++x ) { + ret = fn( ret, this.a[x] ); + } + return ret; +}; + +clojure.lang.ArraySeq.prototype.seq = function() { + return this; +}; + + +clojure.lang.LazyCons = function(f,_first,_rest) { + this.f = f; + this._first = _first === undefined ? clojure.lang.LazyCons.sentinel : _first; + this._rest = _rest === undefined ? clojure.lang.LazyCons.sentinel : _rest; +}; + +clojure.lang.LazyCons.sentinel = {}; + +clojure.lang.LazyCons.prototype.first = function() { + if( this._first === clojure.lang.LazyCons.sentinel ) + this._first = this.f(); + return this._first; +}; + +clojure.lang.LazyCons.prototype.rest = function() { + if( this._rest === clojure.lang.LazyCons.sentinel ) { + if( this._first === clojure.lang.LazyCons.sentinel ) { + this.first(); + } + this._rest = clojure.seq( this.f(null) ); + this.f = null; + } + return this._rest; +}; + +clojure.lang.LazyCons.prototype.withMeta = function(_meta) { + if( _meta == this.meta() ) + return this; + //force before copying + this.rest(); + return new clojure.lang.LazyCons( _meta, this._first, this._rest ); +}; + +clojure.lang.LazyCons.prototype.seq = function() { + return this; +}; diff --git a/clojurescript/clojurescript-compiler.patch b/clojurescript/clojurescript-compiler.patch index ad80848f..54210848 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..832abd8 100644 +index e087d08..659d346 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(); @@ -37,7 +37,7 @@ index afb25de..832abd8 100644 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)"); -@@ -341,10 +341,9 @@ static class DefExpr implements Expr{ +@@ -346,10 +346,9 @@ static class DefExpr implements Expr{ } } @@ -51,7 +51,7 @@ index afb25de..832abd8 100644 public AssignExpr(AssignableExpr target, Expr val){ this.target = target; -@@ -380,9 +379,9 @@ static class AssignExpr implements Expr{ +@@ -385,9 +384,9 @@ static class AssignExpr implements Expr{ } } @@ -64,7 +64,7 @@ index afb25de..832abd8 100644 final static Method getMethod = Method.getMethod("Object get()"); final static Method setMethod = Method.getMethod("Object set(Object)"); -@@ -426,8 +425,8 @@ static class VarExpr implements Expr, AssignableExpr{ +@@ -431,8 +430,8 @@ static class VarExpr implements Expr, AssignableExpr{ } } @@ -75,7 +75,7 @@ index afb25de..832abd8 100644 public TheVarExpr(Var var){ this.var = var; -@@ -462,8 +461,8 @@ static class TheVarExpr implements Expr{ +@@ -467,8 +466,8 @@ static class TheVarExpr implements Expr{ } } @@ -86,7 +86,7 @@ index afb25de..832abd8 100644 public KeywordExpr(Keyword k){ this.k = k; -@@ -489,7 +488,7 @@ static class KeywordExpr implements Expr{ +@@ -494,7 +493,7 @@ static class KeywordExpr implements Expr{ } } @@ -95,7 +95,7 @@ index afb25de..832abd8 100644 abstract Object val(); public Object eval(){ -@@ -809,11 +808,11 @@ static abstract class FieldExpr extends HostExpr{ +@@ -814,11 +813,11 @@ static abstract class FieldExpr extends HostExpr{ } static class InstanceFieldExpr extends FieldExpr implements AssignableExpr{ @@ -112,7 +112,7 @@ index afb25de..832abd8 100644 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{ +@@ -914,9 +913,9 @@ static class InstanceFieldExpr extends FieldExpr implements AssignableExpr{ static class StaticFieldExpr extends FieldExpr implements AssignableExpr{ //final String className; @@ -125,7 +125,7 @@ index afb25de..832abd8 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{ +@@ -1038,11 +1037,11 @@ static abstract class MethodExpr extends HostExpr{ } static class InstanceMethodExpr extends MethodExpr{ @@ -142,7 +142,7 @@ index afb25de..832abd8 100644 final static Method invokeInstanceMethodMethod = Method.getMethod("Object invokeInstanceMethod(Object,String,Object[])"); -@@ -1171,11 +1170,11 @@ static class InstanceMethodExpr extends MethodExpr{ +@@ -1176,11 +1175,11 @@ static class InstanceMethodExpr extends MethodExpr{ static class StaticMethodExpr extends MethodExpr{ //final String className; @@ -159,7 +159,35 @@ index afb25de..832abd8 100644 final static Method invokeStaticMethodMethod = Method.getMethod("Object invokeStaticMethod(String,String,Object[])"); -@@ -1284,8 +1283,8 @@ static class StaticMethodExpr extends MethodExpr{ +@@ -1285,12 +1284,36 @@ static class StaticMethodExpr extends MethodExpr{ + } + } + ++static class UnresolvedVarExpr implements Expr{ ++ public final Symbol symbol; ++ ++ public UnresolvedVarExpr(Symbol symbol) { ++ this.symbol = symbol; ++ } ++ ++ public boolean hasJavaClass(){ ++ return false; ++ } ++ ++ public Class getJavaClass() throws Exception{ ++ throw new IllegalArgumentException( ++ "UnresolvedVarExpr has no Java class"); ++ } ++ ++ public void emit(C context, FnExpr fn, GeneratorAdapter gen){ ++ } ++ ++ public Object eval() throws Exception{ ++ throw new IllegalArgumentException( ++ "UnresolvedVarExpr cannot be evalled"); ++ } ++} + static class ConstantExpr extends LiteralExpr{ //stuff quoted vals in classloader at compile time, pull out at runtime //this won't work for static compilation... @@ -170,7 +198,7 @@ index afb25de..832abd8 100644 public ConstantExpr(Object v){ this.v = v; -@@ -1369,7 +1368,7 @@ static class NilExpr extends LiteralExpr{ +@@ -1374,7 +1397,7 @@ static class NilExpr extends LiteralExpr{ final static NilExpr NIL_EXPR = new NilExpr(); static class BooleanExpr extends LiteralExpr{ @@ -179,7 +207,7 @@ index afb25de..832abd8 100644 public BooleanExpr(boolean val){ -@@ -1404,7 +1403,7 @@ final static BooleanExpr TRUE_EXPR = new BooleanExpr(true); +@@ -1409,7 +1432,7 @@ final static BooleanExpr TRUE_EXPR = new BooleanExpr(true); final static BooleanExpr FALSE_EXPR = new BooleanExpr(false); static class StringExpr extends LiteralExpr{ @@ -188,7 +216,7 @@ index afb25de..832abd8 100644 public StringExpr(String str){ this.str = str; -@@ -1576,17 +1575,17 @@ static class MonitorExitExpr extends UntypedExpr{ +@@ -1581,17 +1604,17 @@ static class MonitorExitExpr extends UntypedExpr{ } static class TryExpr implements Expr{ @@ -214,7 +242,7 @@ index afb25de..832abd8 100644 Label label; Label endLabel; -@@ -1828,7 +1827,7 @@ static class TryExpr implements Expr{ +@@ -1833,7 +1856,7 @@ static class TryExpr implements Expr{ //} static class ThrowExpr extends UntypedExpr{ @@ -223,7 +251,7 @@ index afb25de..832abd8 100644 public ThrowExpr(Expr excExpr){ this.excExpr = excExpr; -@@ -1955,10 +1954,10 @@ static int getMatchingParams(String methodName, ArrayList<Class[]> paramlists, I +@@ -1960,10 +1983,10 @@ static int getMatchingParams(String methodName, ArrayList<Class[]> paramlists, I return matchIdx; } @@ -238,7 +266,7 @@ index afb25de..832abd8 100644 final static Method invokeConstructorMethod = Method.getMethod("Object invokeConstructor(Class,Object[])"); final static Method forNameMethod = Method.getMethod("Class classForName(String)"); -@@ -2170,9 +2169,9 @@ static class NewExpr implements Expr{ +@@ -2175,9 +2198,9 @@ static class NewExpr implements Expr{ // } //} @@ -251,7 +279,7 @@ index afb25de..832abd8 100644 final static Type IOBJ_TYPE = Type.getType(IObj.class); final static Method withMetaMethod = Method.getMethod("clojure.lang.IObj withMeta(clojure.lang.IPersistentMap)"); -@@ -2207,11 +2206,11 @@ static class MetaExpr implements Expr{ +@@ -2212,11 +2235,11 @@ static class MetaExpr implements Expr{ } } @@ -268,7 +296,7 @@ index afb25de..832abd8 100644 public IfExpr(int line, Expr testExpr, Expr thenExpr, Expr elseExpr){ -@@ -2336,8 +2335,8 @@ static public String munge(String name){ +@@ -2341,8 +2364,8 @@ static public String munge(String name){ return sb.toString(); } @@ -279,7 +307,7 @@ index afb25de..832abd8 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); -@@ -2388,8 +2387,8 @@ static class EmptyExpr implements Expr{ +@@ -2393,8 +2416,8 @@ static class EmptyExpr implements Expr{ } } @@ -290,7 +318,7 @@ index afb25de..832abd8 100644 final static Method arrayToListMethod = Method.getMethod("clojure.lang.ISeq arrayToList(Object[])"); -@@ -2421,8 +2420,8 @@ static class ListExpr implements Expr{ +@@ -2426,8 +2449,8 @@ static class ListExpr implements Expr{ } @@ -301,7 +329,7 @@ index afb25de..832abd8 100644 final static Method mapMethod = Method.getMethod("clojure.lang.IPersistentMap map(Object[])"); -@@ -2470,8 +2469,8 @@ static class MapExpr implements Expr{ +@@ -2475,8 +2498,8 @@ static class MapExpr implements Expr{ } } @@ -312,7 +340,7 @@ index afb25de..832abd8 100644 final static Method setMethod = Method.getMethod("clojure.lang.IPersistentSet set(Object[])"); -@@ -2518,8 +2517,8 @@ static class SetExpr implements Expr{ +@@ -2523,8 +2546,8 @@ static class SetExpr implements Expr{ } } @@ -323,7 +351,7 @@ index afb25de..832abd8 100644 final static Method vectorMethod = Method.getMethod("clojure.lang.IPersistentVector vector(Object[])"); -@@ -2563,11 +2562,11 @@ static class VectorExpr implements Expr{ +@@ -2568,11 +2591,11 @@ static class VectorExpr implements Expr{ } @@ -340,7 +368,7 @@ index afb25de..832abd8 100644 public InvokeExpr(int line, Symbol tag, Expr fexpr, IPersistentVector args){ this.fexpr = fexpr; -@@ -2661,7 +2660,7 @@ static public class FnExpr implements Expr{ +@@ -2693,7 +2716,7 @@ static public class FnExpr implements Expr{ String internalName; String thisName; Type fntype; @@ -349,7 +377,7 @@ index afb25de..832abd8 100644 //localbinding->itself IPersistentMap closes = PersistentHashMap.EMPTY; //Keyword->KeywordExpr -@@ -2671,6 +2670,20 @@ static public class FnExpr implements Expr{ +@@ -2703,6 +2726,20 @@ static public class FnExpr implements Expr{ int line; PersistentVector constants; int constantsID; @@ -370,7 +398,7 @@ index afb25de..832abd8 100644 final static Method kwintern = Method.getMethod("clojure.lang.Keyword intern(String, String)"); final static Method symcreate = Method.getMethod("clojure.lang.Symbol create(String)"); -@@ -3098,10 +3111,10 @@ enum PSTATE{ +@@ -3139,10 +3176,10 @@ enum PSTATE{ } @@ -383,7 +411,7 @@ index afb25de..832abd8 100644 //localbinding->localbinding IPersistentMap locals = null; //localbinding->localbinding -@@ -3113,6 +3126,14 @@ static class FnMethod{ +@@ -3154,6 +3191,14 @@ static class FnMethod{ int maxLocal = 0; int line; PersistentHashSet localsUsedInCatchFinally = PersistentHashSet.EMPTY; @@ -398,7 +426,7 @@ index afb25de..832abd8 100644 public FnMethod(FnExpr fn, FnMethod parent){ this.parent = parent; -@@ -3252,12 +3273,12 @@ static class FnMethod{ +@@ -3293,12 +3338,12 @@ static class FnMethod{ } } @@ -417,7 +445,7 @@ index afb25de..832abd8 100644 public LocalBinding(int num, Symbol sym, Symbol tag, Expr init) throws Exception{ if(maybePrimitiveType(init) != null && tag != null) -@@ -3288,9 +3309,9 @@ static class LocalBinding{ +@@ -3329,9 +3374,9 @@ static class LocalBinding{ } } @@ -430,7 +458,7 @@ index afb25de..832abd8 100644 public LocalBindingExpr(LocalBinding b, Symbol tag) throws Exception{ if(b.getPrimitiveType() != null && tag != null) -@@ -3325,8 +3346,9 @@ static class LocalBindingExpr implements Expr, MaybePrimitiveExpr{ +@@ -3366,8 +3411,9 @@ static class LocalBindingExpr implements Expr, MaybePrimitiveExpr{ } @@ -441,7 +469,7 @@ index afb25de..832abd8 100644 public BodyExpr(PersistentVector exprs){ this.exprs = exprs; -@@ -3386,9 +3408,11 @@ static class BodyExpr implements Expr{ +@@ -3427,9 +3473,11 @@ static class BodyExpr implements Expr{ } } @@ -454,7 +482,7 @@ index afb25de..832abd8 100644 public BindingInit(LocalBinding binding, Expr init){ this.binding = binding; -@@ -3396,10 +3420,10 @@ static class BindingInit{ +@@ -3437,10 +3485,10 @@ static class BindingInit{ } } @@ -469,7 +497,7 @@ index afb25de..832abd8 100644 public LetExpr(PersistentVector bindingInits, Expr body, boolean isLoop){ this.bindingInits = bindingInits; -@@ -3522,9 +3546,9 @@ static class LetExpr implements Expr{ +@@ -3563,9 +3611,9 @@ static class LetExpr implements Expr{ } } @@ -482,7 +510,7 @@ index afb25de..832abd8 100644 public RecurExpr(IPersistentVector loopLocals, IPersistentVector args){ this.loopLocals = loopLocals; -@@ -3626,7 +3650,7 @@ private static int getAndIncLocalNum(){ +@@ -3667,7 +3715,7 @@ private static int getAndIncLocalNum(){ return num; } @@ -491,3 +519,33 @@ index afb25de..832abd8 100644 return analyze(context, form, null); } +@@ -3963,6 +4011,8 @@ private static Expr analyzeSymbol(Symbol sym) throws Exception{ + } + else if(o instanceof Class) + return new ConstantExpr(o); ++ else if(o instanceof Symbol) ++ return new UnresolvedVarExpr((Symbol) o); + + throw new Exception("Unable to resolve symbol: " + sym + " in this context"); + +@@ -4008,6 +4058,8 @@ static public Object resolveIn(Namespace n, Symbol sym) throws Exception{ + return RT.NS_VAR; + else if(sym.equals(IN_NS)) + return RT.IN_NS_VAR; ++ else if(RT.booleanCast(RT.ALLOW_UNRESOLVED_VARS.get())) ++ return sym; + else + { + Object o = n.getMapping(sym); +diff --git a/src/jvm/clojure/lang/RT.java b/src/jvm/clojure/lang/RT.java +index 2ce55e4..06379eb 100644 +--- a/src/jvm/clojure/lang/RT.java ++++ b/src/jvm/clojure/lang/RT.java +@@ -198,6 +198,7 @@ final static Var FLUSH_ON_NEWLINE = Var.intern(CLOJURE_NS, Symbol.create("*flush + final static Var PRINT_META = Var.intern(CLOJURE_NS, Symbol.create("*print-meta*"), F); + final static Var PRINT_READABLY = Var.intern(CLOJURE_NS, Symbol.create("*print-readably*"), T); + final static Var WARN_ON_REFLECTION = Var.intern(CLOJURE_NS, Symbol.create("*warn-on-reflection*"), F); ++final static Var ALLOW_UNRESOLVED_VARS = Var.intern(CLOJURE_NS, Symbol.create("*allow-unresolved-vars*"), F); + + final static Var IN_NS_VAR = Var.intern(CLOJURE_NS, Symbol.create("in-ns"), F); + final static Var NS_VAR = Var.intern(CLOJURE_NS, Symbol.create("ns"), F); diff --git a/clojurescript/t01.cljs b/clojurescript/t01.cljs new file mode 100644 index 00000000..7f96c2d0 --- /dev/null +++ b/clojurescript/t01.cljs @@ -0,0 +1,13 @@ +; 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")] + (if-let src (.src elem) + src + "--none--"))) + +(doseq src (script-src) + (prn src)) diff --git a/clojurescript/t01.html b/clojurescript/t01.html new file mode 100644 index 00000000..dc1098df --- /dev/null +++ b/clojurescript/t01.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="PersistentVector-proto.js"></script> + <script type="text/javascript" src="t01.js"></script> + </body> +</html> diff --git a/clojurescript/tojs.clj b/clojurescript/tojs.clj index 3ec87198..5653a7bd 100644 --- a/clojurescript/tojs.clj +++ b/clojurescript/tojs.clj @@ -24,21 +24,25 @@ (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" + (vstr ["var " (vec (interpose "," (vals lm))) ";\n" + (when-let thisfn (some #(when (= (.name %) + (.thisName (:fnexpr ctx))) %) + (keys lm)) + [(lm thisfn) "=" (.simpleName (:fnexpr ctx)) ";\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," + ["var " (lm lb) "=clojure.JS.rest_args(arguments," (count (.reqParms fm)) ");\n"]) "var _rtn,_cnt;do{_cnt=0;\n_rtn=" - (tojs (.body fm) (assoc ctx :localmap lm)) + (tojs (.body fm) (merge-with merge ctx {:localmap lm})) ";\n}while(_cnt);return _rtn;"]))) (defmethod tojs clojure.lang.Compiler$FnExpr [e ctx] (vstr ["(function " (.simpleName e) "(){\n" (vec (for [fm (.methods e) :when (not= fm (.variadicMethod e))] ["if(arguments.length==" (count (.argLocals fm)) "){\n" - (fnmethod fm ctx) + (fnmethod fm (assoc ctx :fnexpr e)) "}\n"])) (if (.variadicMethod e) [(fnmethod (.variadicMethod e) ctx) "\n"] @@ -49,19 +53,18 @@ (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;})()") - ")"])) + (let [inits (vec (for [bi (.bindingInits e)] + ["(" ((:localmap ctx) (.binding bi)) + "=" (tojs (.init bi) ctx) "),\n"]))] + (if (.isLoop e) + (vstr ["((function(){var _rtn,_cnt;" + inits "0;" + "do{_cnt=0;\n_rtn=" (tojs (.body e) ctx) + "}while(_cnt);return _rtn;})())"]) + (vstr ["(" inits (tojs (.body e) ctx) ")"])))) (defmethod tojs clojure.lang.Compiler$VectorExpr [e ctx] - (vstr ["clojure.RT.lit_vector([" + (vstr ["clojure.JS.lit_vector([" (vec (interpose "," (map #(tojs % ctx) (.args e)))) "])"])) @@ -71,7 +74,7 @@ (keyword? c) (str \" c \") (symbol? c) (str \" \' c \") (class? c) (.getCanonicalName c) - (list? c) (vstr ["clojure.RT.lit_list([" + (list? c) (vstr ["clojure.JS.lit_list([" (vec (interpose "," (map const-str c))) "])"]) :else (str c))) @@ -79,6 +82,15 @@ (defmethod tojs clojure.lang.Compiler$ConstantExpr [e ctx] (const-str (.v e))) +(defmethod tojs clojure.lang.Compiler$UnresolvedVarExpr [e ctx] + (vstr ["clojure.JS.resolveVar(" + (if-let ns (namespace (.symbol e)) + [\" (Compiler/munge ns) \"] + "null") + ",\"" (Compiler/munge (name (.symbol e))) + "\"," (Compiler/munge (name (.name *ns*))) + ")"])) + (defmethod tojs clojure.lang.Compiler$InvokeExpr [e ctx] (vstr [(tojs (.fexpr e) ctx) "(" @@ -128,12 +140,12 @@ (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) ")")) + (str "((" (tojs (.testExpr e) ctx) + ")?(" (tojs (.thenExpr e) ctx) + "):(" (tojs (.elseExpr e) ctx) "))")) (defmethod tojs clojure.lang.Compiler$RecurExpr [e ctx] - (vstr ["(_cnt=0" + (vstr ["(_cnt=1" (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))) @@ -177,7 +189,10 @@ (defn formtojs [f] - (tojs (Compiler/analyze Compiler$C/STATEMENT 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" @@ -201,31 +216,50 @@ (eval f)) (recur))))) -(println (formtojs - '(defn foo - ([a b c & d] (prn 3 a b c)) - ([c]; - ;(String/asd "hello") - ;(.foo 55) - (let [[a b] [1 2]] - (prn a b c) - "hi"))))) - -(println (formtojs - '(defn foo [a] - (prn "hi") - (let [a 5] - (let [a 10] - (prn "yo") - (prn a)) - (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) +(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)) + (recur)))))) + +(defn simple-tests [] + (println (formtojs + '(defn foo + ([a b c & d] (prn 3 a b c)) + ([c]; + ;(String/asd "hello") + ;(.foo 55) + (let [[a b] [1 2]] + (prn a b c) + "hi"))))) + + (println (formtojs + '(defn foo [a] + (prn "hi") + (let [a 5] + (let [a 10] + (prn "yo") + (prn a)) + (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}))) + (println (formtojs '(fn forever[] (forever))))) + +;(simple-tests) +;(testboot) + +(filetojs "t01.cljs") |