diff options
author | Rich Hickey <richhickey@gmail.com> | 2006-09-29 18:15:18 +0000 |
---|---|---|
committer | Rich Hickey <richhickey@gmail.com> | 2006-09-29 18:15:18 +0000 |
commit | f36e07ecf4275fc6c6773b56faff7426b5671147 (patch) | |
tree | f4c914555d3a3a580367dd8e82271b7747885ba0 | |
parent | 63f878b1103d32483c44ef6416a6c74c4b7b969b (diff) |
interim checkin
-rw-r--r-- | src/jvm/clojure/lang/Compiler.java | 87 |
1 files changed, 77 insertions, 10 deletions
diff --git a/src/jvm/clojure/lang/Compiler.java b/src/jvm/clojure/lang/Compiler.java index b755185f..46aecc5d 100644 --- a/src/jvm/clojure/lang/Compiler.java +++ b/src/jvm/clojure/lang/Compiler.java @@ -212,25 +212,25 @@ private static Expr analyzeFn(C context, ISeq form) throws Exception { static class FnExpr extends AnExpr{ IPersistentCollection methods; boolean isVariadic; - LocalBinding b; - private String className = null; + LocalBinding binding; + String name = null; boolean isCalledDirectly = false; //localbinding->itself IPersistentMap closes = null; - String getClassName(){ - if(className == null) + String getName(){ + if(name == null) { - if(b != null) - className = "FN__" + b.sym.name + "__" + RT.nextID(); + if(binding != null) + name = "FN__" + binding.sym.name + "__" + RT.nextID(); else - className = "FN__" + RT.nextID(); + name = "FN__" + RT.nextID(); } - return className; + return name; } public void emitExpression() throws Exception{ - format("(new ~A(", getClassName()); + format("(new ~A(", getName()); for(ISeq s = RT.seq(closes);s!=null;s=s.rest()) { LocalBinding b = (LocalBinding) ((MapEntry) s.first()).key(); @@ -240,7 +240,59 @@ static class FnExpr extends AnExpr{ } format("))"); } -} s + + public void emitDeclaration() throws Exception { + PersistentArrayList closesDecls = null; + if(closes != null) + { + closesDecls = new PersistentArrayList(closes.count() * 2); + for (ISeq s = RT.seq(closes); s != null; s = s.rest()) + { + LocalBinding b = (LocalBinding) ((MapEntry) s.first()).key(); + closesDecls.cons(b.typeDeclaration()); + closesDecls.cons(b.getName()); + } + } + if(!willBeStaticMethod()) + { + //emit class declaration + format("static public class ~A extends ~A{~%", + getName(), + isVariadic ? "clojure.lang.RestFn" : "AFn"); + if(closes != null) + { + //emit members and ctor if closure + format("~{~A ~A;~%~}", closesDecls); + format("public ~A (~{~A ~A~^, ~}){~%", getName(), closesDecls); + for (ISeq s = RT.seq(closes); s != null; s = s.rest()) + { + LocalBinding b = (LocalBinding) ((MapEntry) s.first()).key(); + format("this.~A = ~A;~%", b.getName(), b.getName()); + if (s.rest() != null) + format(","); + } + format("}~%"); + } + } + else + { + format("static public Object ~A(~{~A ~A~^, ~}", +s getName(), + closesDecls); + } + } + + boolean willBeStaticMethod() { + return !isVariadic + && methods.count() == 1 + && + ( + isCalledDirectly + || + (binding != null && !binding.isClosed && !binding.valueTaken) + ); + } +} static class FnMethod { FnMethod parent = null; @@ -328,6 +380,8 @@ private static FnMethod analyzeMethod(FnExpr fn,ISeq form) throws Exception { } } + + static LocalBindingExpr createParamBinding(Symbol p) { Symbol basep = baseSymbol(p); LocalBinding b = new LocalBinding(basep); @@ -568,6 +622,9 @@ static class LocalBinding{ boolean isParam = false; final int id = RT.nextID(); String typeHint; + public boolean valueTaken = false; + boolean isAssigned = false; + public LocalBinding(Symbol sym) { this.sym = sym; @@ -576,6 +633,16 @@ static class LocalBinding{ public String getName(){ return munge(sym.name) + "__" + id; } + + boolean needsBox(){ + return isClosed && isAssigned; + } + + String typeDeclaration(){ + if(needsBox()) + return "clojure.lang.Box"; + return "Object"; + } } static class LocalBindingExpr extends AnExpr{ |