summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/jvm/clojure/lang/Compiler.java124
1 files changed, 120 insertions, 4 deletions
diff --git a/src/jvm/clojure/lang/Compiler.java b/src/jvm/clojure/lang/Compiler.java
index eb1f4f70..06c7606d 100644
--- a/src/jvm/clojure/lang/Compiler.java
+++ b/src/jvm/clojure/lang/Compiler.java
@@ -2968,7 +2968,7 @@ static public class FnExpr implements Expr{
return ret;
}
- private void compile(){
+ private void compile() throws IOException{
//create bytecode for a class
//with name current_ns.defname[$letname]+
//anonymous fns get names fn__id
@@ -2976,7 +2976,7 @@ static public class FnExpr implements Expr{
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
// ClassWriter cw = new ClassWriter(0);
ClassVisitor cv = cw;
- //ClassVisitor cv = new TraceClassVisitor(new CheckClassAdapter(cw), new PrintWriter(System.out));
+// ClassVisitor cv = new TraceClassVisitor(new CheckClassAdapter(cw), new PrintWriter(System.out));
//ClassVisitor cv = new TraceClassVisitor(cw, new PrintWriter(System.out));
cv.visit(V1_5, ACC_PUBLIC + ACC_SUPER, internalName, null,
isVariadic() ? "clojure/lang/RestFn" : "clojure/lang/AFn", null);
@@ -3158,11 +3158,31 @@ static public class FnExpr implements Expr{
loader = (DynamicClassLoader) LOADER.get();
bytecode = cw.toByteArray();
+ String path = "gen" + File.separator + internalName + ".class";
+ File cf = new File(path);
+ cf.getParentFile().mkdirs();
+ cf.createNewFile();
+ OutputStream cfs = new FileOutputStream(cf);
+ try
+ {
+ cfs.write(bytecode);
+ }
+ finally
+ {
+ cfs.close();
+ }
}
synchronized Class getCompiledClass(){
if(compiledClass == null)
- compiledClass = loader.defineClass(name, bytecode);
+ try
+ {
+ compiledClass = RT.classForName(name);//loader.defineClass(name, bytecode);
+ }
+ catch(ClassNotFoundException e)
+ {
+ throw new RuntimeException(e);
+ }
return compiledClass;
}
@@ -3268,7 +3288,9 @@ static public class FnExpr implements Expr{
return Type.getType(RestFn.class);
else if(AFn.class.isAssignableFrom(c))
return Type.getType(AFn.class);
- return Type.getType(c);
+ else if(c == Var.class)
+ return Type.getType(Var.class);
+// return Type.getType(c);
}
return OBJECT_TYPE;
}
@@ -4421,6 +4443,100 @@ public static Object load(Reader rdr, String sourcePath, String sourceName) thro
}
return ret;
}
+
+public static Object compile(Reader rdr, String sourcePath, String sourceName) throws Exception{
+ Object EOF = new Object();
+ Object ret = null;
+ LineNumberingPushbackReader pushbackReader =
+ (rdr instanceof LineNumberingPushbackReader) ? (LineNumberingPushbackReader) rdr :
+ new LineNumberingPushbackReader(rdr);
+ Var.pushThreadBindings(
+ RT.map(SOURCE_PATH, sourcePath,
+ SOURCE, sourceName,
+ RT.CURRENT_NS, RT.CURRENT_NS.get(),
+ LINE_BEFORE, pushbackReader.getLineNumber(),
+ LINE_AFTER, pushbackReader.getLineNumber(),
+ CONSTANTS, PersistentVector.EMPTY,
+ KEYWORDS, PersistentHashMap.EMPTY,
+ VARS, PersistentHashMap.EMPTY
+ ));
+
+ try
+ {
+ FnExpr fn = new FnExpr(null);
+ fn.internalName = sourcePath.replace(File.separator, "/").substring(0, sourcePath.lastIndexOf('.'));
+ fn.fntype = Type.getObjectType(fn.internalName);
+ ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
+ ClassVisitor cv = cw;
+ cv.visit(V1_5, ACC_PUBLIC + ACC_SUPER, fn.internalName, null,
+ "java.lang.Object", null);
+
+ //static load method
+ GeneratorAdapter gen = new GeneratorAdapter(ACC_PUBLIC + ACC_STATIC,
+ Method.getMethod("void load ()"),
+ null,
+ null,
+ cv);
+ gen.visitCode();
+
+ for(Object r = LispReader.read(pushbackReader, false, EOF, false); r != EOF;
+ r = LispReader.read(pushbackReader, false, EOF, false))
+ {
+ LINE_AFTER.set(pushbackReader.getLineNumber());
+ Expr expr = analyze(C.EVAL, r);
+ fn.keywords = (IPersistentMap) KEYWORDS.get();
+ fn.vars = (IPersistentMap) VARS.get();
+ fn.constants = (PersistentVector) CONSTANTS.get();
+ expr.emit(C.EXPRESSION, fn, gen);
+ expr.eval();
+ LINE_BEFORE.set(pushbackReader.getLineNumber());
+ }
+ //end of load
+ gen.returnValue();
+ gen.endMethod();
+
+ //static fields for constants
+ for(int i = 0; i < fn.constants.count(); i++)
+ {
+ cv.visitField(ACC_PUBLIC + ACC_FINAL + ACC_STATIC, fn.constantName(i), fn.constantType(i).getDescriptor(),
+ null, null);
+ }
+
+ //static init for constants, keywords and vars
+ GeneratorAdapter clinitgen = new GeneratorAdapter(ACC_PUBLIC + ACC_STATIC,
+ Method.getMethod("void <clinit> ()"),
+ null,
+ null,
+ cv);
+ clinitgen.visitCode();
+ if(fn.constants.count() > 0)
+ {
+ for(int i = 0; i < fn.constants.count(); i++)
+ {
+ clinitgen.push(RT.printString(fn.constants.nth(i)));
+ clinitgen.invokeStatic(RT_TYPE, FnExpr.readStringMethod);
+ clinitgen.checkCast(fn.constantType(i));
+ clinitgen.putStatic(fn.fntype, fn.constantName(i), fn.constantType(i));
+ }
+ }
+ //end of static init
+ clinitgen.returnValue();
+ clinitgen.endMethod();
+
+ //end of class
+ cv.visitEnd();
+ }
+ catch(LispReader.ReaderException e)
+ {
+ throw new CompilerException(sourceName, e.line, e.getCause());
+ }
+ finally
+ {
+ Var.popThreadBindings();
+ }
+ return ret;
+}
+
/*
public static void main(String[] args) throws Exception{
RT.init();