summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRich Hickey <richhickey@gmail.com>2007-09-15 23:09:05 +0000
committerRich Hickey <richhickey@gmail.com>2007-09-15 23:09:05 +0000
commite0decde9777bd4a7f1b3f41a0810f66bb8190794 (patch)
tree074811e05b4c8791b9becd32892ceeb7e0d94fa2 /src
parent534b094db5e9bda280951e6fa9d9b75884825441 (diff)
direct compilation of ctors
Diffstat (limited to 'src')
-rw-r--r--src/jvm/clojure/lang/Compiler.java38
1 files changed, 33 insertions, 5 deletions
diff --git a/src/jvm/clojure/lang/Compiler.java b/src/jvm/clojure/lang/Compiler.java
index b453dc22..af8df6c2 100644
--- a/src/jvm/clojure/lang/Compiler.java
+++ b/src/jvm/clojure/lang/Compiler.java
@@ -21,6 +21,8 @@ import org.objectweb.asm.util.CheckClassAdapter;
import java.io.*;
import java.math.BigInteger;
import java.util.List;
+import java.util.ArrayList;
+import java.lang.reflect.Constructor;
public class Compiler implements Opcodes{
@@ -1037,14 +1039,29 @@ static class ClassExpr implements Expr{
static class NewExpr implements Expr{
final String className;
final IPersistentVector args;
+ final Constructor ctor;
+ final Class c;
final static Method invokeConstructorMethod =
Method.getMethod("Object invokeConstructor(Class,Object[])");
final static Method forNameMethod = Method.getMethod("Class forName(String)");
- public NewExpr(String className, IPersistentVector args){
+ public NewExpr(String className, IPersistentVector args) throws ClassNotFoundException{
this.args = args;
this.className = className;
+ this.c = Class.forName(className);
+ Constructor[] allctors = c.getConstructors();
+ ArrayList ctors = new ArrayList();
+ for(int i = 0; i < allctors.length; i++)
+ {
+ Constructor ctor = allctors[i];
+ if(ctor.getParameterTypes().length == args.count())
+ ctors.add(ctor);
+ }
+ if(ctors.isEmpty())
+ throw new IllegalArgumentException("No matching ctor found");
+
+ this.ctor = (ctors.size() == 1) ? (Constructor) ctors.get(0) : null;
}
public Object eval() throws Exception{
@@ -1055,10 +1072,21 @@ static class NewExpr implements Expr{
}
public void emit(C context, FnExpr fn, GeneratorAdapter gen){
- gen.push(className);
- gen.invokeStatic(CLASS_TYPE, forNameMethod);
- MethodExpr.emitArgsAsArray(args, fn, gen);
- gen.invokeStatic(REFLECTOR_TYPE, invokeConstructorMethod);
+ if(this.ctor != null)
+ {
+ Type type = Type.getType(c);
+ gen.newInstance(type);
+ gen.dup();
+ MethodExpr.emitTypedArgs(fn, gen, ctor.getParameterTypes(), args);
+ gen.invokeConstructor(type, new Method("<init>", Type.getConstructorDescriptor(ctor)));
+ }
+ else
+ {
+ gen.push(className);
+ gen.invokeStatic(CLASS_TYPE, forNameMethod);
+ MethodExpr.emitArgsAsArray(args, fn, gen);
+ gen.invokeStatic(REFLECTOR_TYPE, invokeConstructorMethod);
+ }
if(context == C.STATEMENT)
gen.pop();
}