aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--clojurescript/clj.js148
-rw-r--r--clojurescript/clojurescript-compiler.patch128
-rw-r--r--clojurescript/t01.cljs13
-rw-r--r--clojurescript/t01.html12
-rw-r--r--clojurescript/tojs.clj132
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")