summaryrefslogtreecommitdiff
path: root/src/jvm/clojure
diff options
context:
space:
mode:
authorRich Hickey <richhickey@gmail.com>2008-11-18 19:46:41 +0000
committerRich Hickey <richhickey@gmail.com>2008-11-18 19:46:41 +0000
commitd10f462699a029fa22f6e7fde59af945b5eff9b4 (patch)
tree84ff429b1c90f69d5322961366ef0f6be00040fc /src/jvm/clojure
parent914c6af02006b6c650493716c7fc15b4e42a837b (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.java78
-rw-r--r--src/jvm/clojure/lang/RT.java4
-rw-r--r--src/jvm/clojure/lang/Var.java8
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);
}