diff options
author | Rich Hickey <richhickey@gmail.com> | 2009-11-04 12:31:34 -0500 |
---|---|---|
committer | Rich Hickey <richhickey@gmail.com> | 2009-11-04 12:31:34 -0500 |
commit | 7a10c9077b5d037e782b2bc63c821f42337e9e04 (patch) | |
tree | 37a2b366a4fc9a08386f802cc674dbad41315312 | |
parent | 406fc1c00f8138d47445047c9e17a8af12fefcff (diff) |
generate second ctor for defclass/type taking designated fields only, defaulting rest to nil
-rw-r--r-- | src/clj/clojure/core_deftype.clj | 9 | ||||
-rw-r--r-- | src/jvm/clojure/lang/Compiler.java | 54 |
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(); |