summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRich Hickey <richhickey@gmail.com>2009-11-04 12:31:34 -0500
committerRich Hickey <richhickey@gmail.com>2009-11-04 12:31:34 -0500
commit7a10c9077b5d037e782b2bc63c821f42337e9e04 (patch)
tree37a2b366a4fc9a08386f802cc674dbad41315312 /src
parent406fc1c00f8138d47445047c9e17a8af12fefcff (diff)
generate second ctor for defclass/type taking designated fields only, defaulting rest to nil
Diffstat (limited to 'src')
-rw-r--r--src/clj/clojure/core_deftype.clj9
-rw-r--r--src/jvm/clojure/lang/Compiler.java54
2 files changed, 58 insertions, 5 deletions
diff --git a/src/clj/clojure/core_deftype.clj b/src/clj/clojure/core_deftype.clj
index 3149e954..22e4700b 100644
--- a/src/clj/clojure/core_deftype.clj
+++ b/src/clj/clojure/core_deftype.clj
@@ -106,10 +106,11 @@
writes the .class file to the *compile-path* directory. When not
compiling, does nothing.
- A constructor will be defined, taking the designated fields followed
- by a metadata map (nil for none) and an extension field map (nil for
- none). In the method bodies, the (unqualified) name can be used
- to name the class (for calls to new etc).
+ Two constructors will be defined, one taking the designated fields
+ followed by a metadata map (nil for none) and an extension field
+ map (nil for none), and one taking only the fields (using nil for
+ meta and extension fields). In the method bodies, the (unqualified)
+ name can be used to name the class (for calls to new etc).
See deftype for a description of fields, methods, equality and
generated interfaces."
diff --git a/src/jvm/clojure/lang/Compiler.java b/src/jvm/clojure/lang/Compiler.java
index 09de8b4c..5bcd7ad7 100644
--- a/src/jvm/clojure/lang/Compiler.java
+++ b/src/jvm/clojure/lang/Compiler.java
@@ -2949,6 +2949,7 @@ static public class ObjExpr implements Expr{
int line;
PersistentVector constants;
int constantsID;
+ int altCtorDrops = 0;
IPersistentVector keywordCallsites;
@@ -3231,6 +3232,31 @@ static public class ObjExpr implements Expr{
ctorgen.endMethod();
+ if(altCtorDrops > 0)
+ {
+ //ctor that takes closed-overs and inits base + fields
+ Type[] ctorTypes = ctorTypes();
+ Type[] altCtorTypes = new Type[ctorTypes.length-altCtorDrops];
+ for(int i=0;i<altCtorTypes.length;i++)
+ altCtorTypes[i] = ctorTypes[i];
+ Method alt = new Method("<init>", Type.VOID_TYPE, altCtorTypes);
+ ctorgen = new GeneratorAdapter(ACC_PUBLIC,
+ alt,
+ null,
+ null,
+ cv);
+ ctorgen.visitCode();
+ ctorgen.loadThis();
+ ctorgen.loadArgs();
+ for(int i=0;i<altCtorDrops;i++)
+ ctorgen.visitInsn(Opcodes.ACONST_NULL);
+
+ ctorgen.invokeConstructor(objtype, new Method("<init>", Type.VOID_TYPE, ctorTypes));
+
+ ctorgen.returnValue();
+ ctorgen.endMethod();
+ }
+
emitMethods(cv);
if(keywordCallsites.count() > 0)
@@ -5401,7 +5427,7 @@ static public class NewInstanceExpr extends ObjExpr{
}
}
- static Expr build(IPersistentVector interfaceSyms, IPersistentVector fieldSyms, Symbol thisSym, String className,
+ static ObjExpr build(IPersistentVector interfaceSyms, IPersistentVector fieldSyms, Symbol thisSym, String className,
Symbol typeTag, ISeq methodForms) throws Exception{
NewInstanceExpr ret = new NewInstanceExpr(null);
@@ -5435,6 +5461,8 @@ static public class NewInstanceExpr extends ObjExpr{
//use array map to preserve ctor order
ret.closes = new PersistentArrayMap(closesvec);
ret.fields = fmap;
+ for(int i=fieldSyms.count()-1;i >= 0 && ((Symbol)fieldSyms.nth(i)).name.startsWith("__");--i)
+ ret.altCtorDrops++;
}
//todo - set up volatiles
// ret.volatiles = PersistentHashSet.create(RT.seq(RT.get(ret.optionsMap, volatileKey)));
@@ -5545,6 +5573,30 @@ static public class NewInstanceExpr extends ObjExpr{
ctorgen.returnValue();
ctorgen.endMethod();
+ if(ret.altCtorDrops > 0)
+ {
+ Type[] ctorTypes = ret.ctorTypes();
+ Type[] altCtorTypes = new Type[ctorTypes.length-ret.altCtorDrops];
+ for(int i=0;i<altCtorTypes.length;i++)
+ altCtorTypes[i] = ctorTypes[i];
+ Method alt = new Method("<init>", Type.VOID_TYPE, altCtorTypes);
+ ctorgen = new GeneratorAdapter(ACC_PUBLIC,
+ alt,
+ null,
+ null,
+ cv);
+ ctorgen.visitCode();
+ ctorgen.loadThis();
+ ctorgen.loadArgs();
+ for(int i=0;i<ret.altCtorDrops;i++)
+ ctorgen.visitInsn(Opcodes.ACONST_NULL);
+
+ ctorgen.invokeConstructor(Type.getObjectType(COMPILE_STUB_PREFIX + "/" + ret.internalName),
+ new Method("<init>", Type.VOID_TYPE, ctorTypes));
+
+ ctorgen.returnValue();
+ ctorgen.endMethod();
+ }
//end of class
cv.visitEnd();