diff options
author | Rich Hickey <richhickey@gmail.com> | 2008-11-18 19:46:41 +0000 |
---|---|---|
committer | Rich Hickey <richhickey@gmail.com> | 2008-11-18 19:46:41 +0000 |
commit | d10f462699a029fa22f6e7fde59af945b5eff9b4 (patch) | |
tree | 84ff429b1c90f69d5322961366ef0f6be00040fc /src/jvm/clojure | |
parent | 914c6af02006b6c650493716c7fc15b4e42a837b (diff) |
Added AOT-based genclass
!!!Note - breaking change to gen-class!!!
Do not move to this version if you use gen-and-xxx-class until you are ready to port to new system.
Adds :gen-class clause to ns, which can be used to configure the class generated for the namespace
Diffstat (limited to 'src/jvm/clojure')
-rw-r--r-- | src/jvm/clojure/lang/Compiler.java | 78 | ||||
-rw-r--r-- | src/jvm/clojure/lang/RT.java | 4 | ||||
-rw-r--r-- | src/jvm/clojure/lang/Var.java | 8 |
3 files changed, 67 insertions, 23 deletions
diff --git a/src/jvm/clojure/lang/Compiler.java b/src/jvm/clojure/lang/Compiler.java index d83be385..da3f022c 100644 --- a/src/jvm/clojure/lang/Compiler.java +++ b/src/jvm/clojure/lang/Compiler.java @@ -4485,8 +4485,44 @@ public static Object compile(Reader rdr, String sourcePath, String sourceName) t try { + //use genclass for the stub + String classname = sourcePath.substring(0, sourcePath.lastIndexOf('.')).replace('/', '.'); + Object r = LispReader.read(pushbackReader, false, EOF, false); + Object genclassArgs = null; + if(r instanceof IPersistentList + && (Util.equal(RT.first(r), Symbol.create("ns")) + || Util.equal(RT.first(r), Symbol.create("clojure.core", "ns")))) + { + Keyword gk = Keyword.intern(null, "gen-class"); + Symbol nssym = (Symbol) RT.second(r); + if(!nssym.toString().equals(classname)) + throw new Exception(String.format("Namespace name must match file, had: %s and %s", + nssym, sourcePath)); + for(ISeq s = RT.rest(RT.rest(r)); s != null; s = s.rest()) + { + Object entry = s.first(); + if(RT.first(entry).equals(gk)) + { + genclassArgs = RT.rest(entry); + break; + } + } + } + + if(genclassArgs == null) + genclassArgs = RT.list(Keyword.intern(null, "main"), RT.T); + + genclassArgs = RT.cons(classname, genclassArgs); + Var genclass = RT.var("clojure.core", "gen-class"); + IPersistentMap gret = (IPersistentMap) genclass.applyTo(RT.seq(genclassArgs)); + writeClassFile(sourcePath.substring(0, sourcePath.lastIndexOf('.')), + (byte[]) RT.get(gret, Keyword.intern(null, "bytecode"))); + + //generate loader class FnExpr fn = new FnExpr(null); - fn.internalName = sourcePath.replace(File.separator, "/").substring(0, sourcePath.lastIndexOf('.')); + fn.internalName = sourcePath.replace(File.separator, "/").substring(0, sourcePath.lastIndexOf('.')) + + "__init"; + fn.fntype = Type.getObjectType(fn.internalName); ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS); ClassVisitor cv = cw; @@ -4500,7 +4536,7 @@ public static Object compile(Reader rdr, String sourcePath, String sourceName) t cv); gen.visitCode(); - for(Object r = LispReader.read(pushbackReader, false, EOF, false); r != EOF; + for(; r != EOF; r = LispReader.read(pushbackReader, false, EOF, false)) { LINE_AFTER.set(pushbackReader.getLineNumber()); @@ -4558,28 +4594,28 @@ public static Object compile(Reader rdr, String sourcePath, String sourceName) t clinitgen.endMethod(); //main - GeneratorAdapter maingen = new GeneratorAdapter(ACC_PUBLIC + ACC_STATIC, - Method.getMethod("void main (String[])"), - null, - null, - cv); - maingen.visitCode(); - maingen.push(fn.internalName.replace('/', '.')); - maingen.push("main"); - maingen.invokeStatic(RT_TYPE, Method.getMethod("clojure.lang.Var var(String,String)")); - maingen.loadArgs(); - maingen.invokeStatic(RT_TYPE,Method.getMethod("clojure.lang.ISeq seq(Object)")); - maingen.invokeInterface(IFN_TYPE, new Method("applyTo",OBJECT_TYPE,new Type[]{Type.getType(ISeq.class)})); - maingen.pop(); - - //end of main - maingen.returnValue(); - maingen.endMethod(); +// GeneratorAdapter maingen = new GeneratorAdapter(ACC_PUBLIC + ACC_STATIC, +// Method.getMethod("void main (String[])"), +// null, +// null, +// cv); +// maingen.visitCode(); +// maingen.push(fn.internalName.replace('/', '.')); +// maingen.push("main"); +// maingen.invokeStatic(RT_TYPE, Method.getMethod("clojure.lang.Var var(String,String)")); +// maingen.loadArgs(); +// maingen.invokeStatic(RT_TYPE, Method.getMethod("clojure.lang.ISeq seq(Object)")); +// maingen.invokeInterface(IFN_TYPE, new Method("applyTo", OBJECT_TYPE, new Type[]{Type.getType(ISeq.class)})); +// maingen.pop(); +// +// //end of main +// maingen.returnValue(); +// maingen.endMethod(); //end of class cv.visitEnd(); - - writeClassFile(fn.internalName,cw.toByteArray()); + + writeClassFile(fn.internalName, cw.toByteArray()); } catch(LispReader.ReaderException e) { diff --git a/src/jvm/clojure/lang/RT.java b/src/jvm/clojure/lang/RT.java index e714b80e..1c81e3c8 100644 --- a/src/jvm/clojure/lang/RT.java +++ b/src/jvm/clojure/lang/RT.java @@ -1615,11 +1615,11 @@ static public Class classForName(String name) throws ClassNotFoundException{ return Class.forName(name, false, baseLoader()); } -static public boolean loadClassForName(String name) throws ClassNotFoundException{ +static public boolean loadClassForName(String name) throws Exception{ try{ Class.forName(name, true, baseLoader()); } - catch(Exception e) + catch(ClassNotFoundException e) { return false; } diff --git a/src/jvm/clojure/lang/Var.java b/src/jvm/clojure/lang/Var.java index 5fcfd5eb..6b7d1d9e 100644 --- a/src/jvm/clojure/lang/Var.java +++ b/src/jvm/clojure/lang/Var.java @@ -45,6 +45,7 @@ static ThreadLocal<Frame> dvals = new ThreadLocal<Frame>(){ }; static Keyword privateKey = Keyword.intern(null, "private"); +static IPersistentMap privateMeta = new PersistentArrayMap(new Object[]{privateKey, Boolean.TRUE}); static Keyword macroKey = Keyword.intern(null, "macro"); static Keyword nameKey = Keyword.intern(null, "name"); static Keyword nsKey = Keyword.intern(null, "ns"); @@ -90,6 +91,13 @@ public static Var intern(Symbol nsName, Symbol sym){ return intern(ns, sym); } +public static Var internPrivate(String nsName, String sym){ + Namespace ns = Namespace.findOrCreate(Symbol.intern(nsName)); + Var ret = intern(ns, Symbol.intern(sym)); + ret.setMeta(privateMeta); + return ret; +} + public static Var intern(Namespace ns, Symbol sym){ return ns.intern(sym); } |