summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRich Hickey <richhickey@gmail.com>2010-01-19 14:25:26 -0500
committerRich Hickey <richhickey@gmail.com>2010-01-19 14:25:26 -0500
commit430dd4fa711d0008137d7a82d4b4cd27b6e2d6d1 (patch)
treef599f6a0bf560363f73b66bb322b5e00dd139553
parent277f0235c1387ddd6247a72857597814a3e10bc3 (diff)
metadata for fns
-rw-r--r--src/clj/clojure/core.clj12
-rw-r--r--src/jvm/clojure/lang/AFn.java13
-rw-r--r--src/jvm/clojure/lang/AFunction.java10
-rw-r--r--src/jvm/clojure/lang/APersistentMap.java9
-rw-r--r--src/jvm/clojure/lang/APersistentSet.java3
-rw-r--r--src/jvm/clojure/lang/APersistentVector.java19
-rw-r--r--src/jvm/clojure/lang/Compiler.java126
-rw-r--r--src/jvm/clojure/lang/PersistentArrayMap.java11
-rw-r--r--src/jvm/clojure/lang/PersistentHashMap.java10
-rw-r--r--src/jvm/clojure/lang/PersistentHashSet.java11
-rw-r--r--src/jvm/clojure/lang/PersistentList.java8
-rw-r--r--src/jvm/clojure/lang/PersistentStructMap.java12
-rw-r--r--src/jvm/clojure/lang/PersistentTreeMap.java13
-rw-r--r--src/jvm/clojure/lang/PersistentTreeSet.java9
-rw-r--r--src/jvm/clojure/lang/PersistentVector.java12
-rw-r--r--src/jvm/clojure/lang/Symbol.java11
-rw-r--r--test/clojure/test_clojure/evaluation.clj4
17 files changed, 210 insertions, 83 deletions
diff --git a/src/clj/clojure/core.clj b/src/clj/clojure/core.clj
index ddc42e95..99c7bd15 100644
--- a/src/clj/clojure/core.clj
+++ b/src/clj/clojure/core.clj
@@ -36,7 +36,9 @@
(def
#^{:macro true}
- fn (fn* fn [&form &env & decl] (cons 'fn* decl)))
+ fn (fn* fn [&form &env & decl]
+ (.withMeta #^clojure.lang.IObj (cons 'fn* decl)
+ (.meta #^clojure.lang.IMeta &form))))
(def
#^{:arglists '([coll])
@@ -241,10 +243,10 @@
(if (instance? clojure.lang.Symbol iname) false true))
;; inserts the same fn name to the inline fn if it does not have one
(assoc m :inline (cons ifn (cons name (next inline))))
- m))]
- (list 'def (with-meta name (conj (if (meta name) (meta name) {}) m))
- (cons `fn (cons name fdecl))))))
- ;(cons `fn fdecl)))))
+ m))
+ m (conj (if (meta name) (meta name) {}) m)]
+ (list 'def (with-meta name m)
+ (list '.withMeta (cons `fn (cons name fdecl)) (list '.meta (list 'var name)))))))
(. (var defn) (setMacro))
diff --git a/src/jvm/clojure/lang/AFn.java b/src/jvm/clojure/lang/AFn.java
index 9a86cd2a..075448e5 100644
--- a/src/jvm/clojure/lang/AFn.java
+++ b/src/jvm/clojure/lang/AFn.java
@@ -14,18 +14,7 @@ package clojure.lang;
import java.io.Serializable;
-public abstract class AFn extends Obj implements IFn, Serializable{
-
-public AFn(IPersistentMap meta){
- super(meta);
-}
-
-public AFn(){
-}
-
-public Obj withMeta(IPersistentMap meta){
- throw new UnsupportedOperationException();
-}
+public abstract class AFn implements IFn, Serializable{
public Object call() throws Exception{
return invoke();
diff --git a/src/jvm/clojure/lang/AFunction.java b/src/jvm/clojure/lang/AFunction.java
index d89e88e6..260bbb3e 100644
--- a/src/jvm/clojure/lang/AFunction.java
+++ b/src/jvm/clojure/lang/AFunction.java
@@ -14,19 +14,11 @@ package clojure.lang;
import java.util.Comparator;
-public abstract class AFunction extends AFn implements Comparator, Fn{
+public abstract class AFunction extends AFn implements IObj, Comparator, Fn{
//note - this is not even volatile by design
public MethodImplCache __methodImplCache;
-public AFunction(IPersistentMap meta){
- super(meta);
-}
-
-public AFunction(){
- super();
-}
-
public int compare(Object o1, Object o2){
try
{
diff --git a/src/jvm/clojure/lang/APersistentMap.java b/src/jvm/clojure/lang/APersistentMap.java
index 743f4480..e693a802 100644
--- a/src/jvm/clojure/lang/APersistentMap.java
+++ b/src/jvm/clojure/lang/APersistentMap.java
@@ -15,15 +15,6 @@ import java.util.*;
public abstract class APersistentMap extends AFn implements IPersistentMap, Map, Iterable{
int _hash = -1;
-
-protected APersistentMap(IPersistentMap meta){
- super(meta);
-}
-
-
-protected APersistentMap(){
-}
-
public String toString(){
return RT.printString(this);
}
diff --git a/src/jvm/clojure/lang/APersistentSet.java b/src/jvm/clojure/lang/APersistentSet.java
index d6e815e9..988ff5dd 100644
--- a/src/jvm/clojure/lang/APersistentSet.java
+++ b/src/jvm/clojure/lang/APersistentSet.java
@@ -20,8 +20,7 @@ public abstract class APersistentSet extends AFn implements IPersistentSet, Coll
int _hash = -1;
final IPersistentMap impl;
-protected APersistentSet(IPersistentMap meta, IPersistentMap impl){
- super(meta);
+protected APersistentSet(IPersistentMap impl){
this.impl = impl;
}
diff --git a/src/jvm/clojure/lang/APersistentVector.java b/src/jvm/clojure/lang/APersistentVector.java
index a11217e3..4fcde2d1 100644
--- a/src/jvm/clojure/lang/APersistentVector.java
+++ b/src/jvm/clojure/lang/APersistentVector.java
@@ -13,20 +13,12 @@
package clojure.lang;
import java.util.*;
-import java.util.concurrent.atomic.AtomicInteger;
public abstract class APersistentVector extends AFn implements IPersistentVector, Iterable,
List,
RandomAccess, Comparable, Streamable{
int _hash = -1;
-public APersistentVector(IPersistentMap meta){
- super(meta);
-}
-
-protected APersistentVector(){
-}
-
public String toString(){
return RT.printString(this);
}
@@ -516,14 +508,17 @@ static class RSeq extends ASeq implements IndexedSeq, Counted{
}
}
-static class SubVector extends APersistentVector{
+static class SubVector extends APersistentVector implements IObj{
final IPersistentVector v;
final int start;
final int end;
+ final IPersistentMap _meta;
+
public SubVector(IPersistentMap meta, IPersistentVector v, int start, int end){
- super(meta);
+ this._meta = meta;
+
if(v instanceof APersistentVector.SubVector)
{
APersistentVector.SubVector sv = (APersistentVector.SubVector) v;
@@ -575,5 +570,9 @@ static class SubVector extends APersistentVector{
return this;
return new SubVector(meta, v, start, end);
}
+
+ public IPersistentMap meta(){
+ return _meta;
+ }
}
}
diff --git a/src/jvm/clojure/lang/Compiler.java b/src/jvm/clojure/lang/Compiler.java
index 9f58b794..18882651 100644
--- a/src/jvm/clojure/lang/Compiler.java
+++ b/src/jvm/clojure/lang/Compiler.java
@@ -181,6 +181,9 @@ static final public Var LOOP_LABEL = Var.create();
//vector<object>
static final public Var CONSTANTS = Var.create();
+//IdentityHashMap
+static final public Var CONSTANT_IDS = Var.create();
+
//vector<keyword>
static final public Var KEYWORD_CALLSITES = Var.create();
@@ -359,12 +362,6 @@ static class DefExpr implements Expr{
public void emit(C context, ObjExpr objx, GeneratorAdapter gen){
objx.emitVar(gen, var);
- if(initProvided)
- {
- gen.dup();
- init.emit(C.EXPRESSION, objx, gen);
- gen.invokeVirtual(VAR_TYPE, bindRootMethod);
- }
if(meta != null)
{
gen.dup();
@@ -372,6 +369,12 @@ static class DefExpr implements Expr{
gen.checkCast(IPERSISTENTMAP_TYPE);
gen.invokeVirtual(VAR_TYPE, setMetaMethod);
}
+ if(initProvided)
+ {
+ gen.dup();
+ init.emit(C.EXPRESSION, objx, gen);
+ gen.invokeVirtual(VAR_TYPE, bindRootMethod);
+ }
if(context == C.STATEMENT)
gen.pop();
@@ -3070,6 +3073,14 @@ static public class FnExpr extends ObjExpr{
super(tag);
}
+ public boolean hasJavaClass() throws Exception{
+ return true;
+ }
+
+ public Class getJavaClass() throws Exception{
+ return AFunction.class;
+ }
+
protected void emitMethods(ClassVisitor cv){
//override of invoke/doInvoke for each method
for(ISeq s = RT.seq(methods); s != null; s = s.next())
@@ -3093,6 +3104,7 @@ static public class FnExpr extends ObjExpr{
}
static Expr parse(C context, ISeq form, String name) throws Exception{
+ ISeq origForm = form;
FnExpr fn = new FnExpr(tagOf(form));
ObjMethod enclosingMethod = (ObjMethod) METHOD.deref();
if(((IMeta) form.first()).meta() != null)
@@ -3117,6 +3129,7 @@ static public class FnExpr extends ObjExpr{
{
Var.pushThreadBindings(
RT.map(CONSTANTS, PersistentVector.EMPTY,
+ CONSTANT_IDS, new IdentityHashMap(),
KEYWORDS, PersistentHashMap.EMPTY,
VARS, PersistentHashMap.EMPTY,
KEYWORD_CALLSITES, PersistentVector.EMPTY,
@@ -3188,7 +3201,11 @@ static public class FnExpr extends ObjExpr{
fn.compile(fn.isVariadic() ? "clojure/lang/RestFn" : "clojure/lang/AFunction",null,fn.onceOnly);
fn.getCompiledClass();
- return fn;
+ if(origForm instanceof IObj && ((IObj) origForm).meta() != null)
+ return new MetaExpr(fn, (MapExpr) MapExpr
+ .parse(context == C.EVAL ? context : C.EXPRESSION, ((IObj) origForm).meta()));
+ else
+ return fn;
}
public final ObjMethod variadicMethod(){
@@ -3315,9 +3332,7 @@ static public class ObjExpr implements Expr{
Type[] ctorTypes(){
- if(closes.count() == 0)
- return ARG_TYPES[0];
- PersistentVector tv = PersistentVector.EMPTY;
+ IPersistentVector tv = isDeftype()?PersistentVector.EMPTY:RT.vector(IPERSISTENTMAP_TYPE);
for(ISeq s = RT.keys(closes); s != null; s = s.next())
{
LocalBinding lb = (LocalBinding) s.first();
@@ -3451,6 +3466,10 @@ static public class ObjExpr implements Expr{
clinitgen.returnValue();
clinitgen.endMethod();
+ if(!isDeftype())
+ {
+ cv.visitField(ACC_FINAL, "__meta", IPERSISTENTMAP_TYPE.getDescriptor(), null, null);
+ }
//instance fields for closed-overs
for(ISeq s = RT.keys(closes); s != null; s = s.next())
{
@@ -3510,7 +3529,14 @@ static public class ObjExpr implements Expr{
// }
// else
// ctorgen.invokeConstructor(aFnType, voidctor);
- int a = 1;
+ if(!isDeftype())
+ {
+ ctorgen.loadThis();
+ ctorgen.visitVarInsn(IPERSISTENTMAP_TYPE.getOpcode(Opcodes.ILOAD), 1);
+ ctorgen.putField(objtype, "__meta", IPERSISTENTMAP_TYPE);
+ }
+
+ int a = isDeftype()?1:2;
for(ISeq s = RT.keys(closes); s != null; s = s.next(), ++a)
{
LocalBinding lb = (LocalBinding) s.first();
@@ -3563,6 +3589,76 @@ static public class ObjExpr implements Expr{
ctorgen.endMethod();
}
+ if(!isDeftype())
+ {
+ //ctor that takes closed-overs but not meta
+ Type[] ctorTypes = ctorTypes();
+ Type[] noMetaCtorTypes = new Type[ctorTypes.length-1];
+ for(int i=1;i<ctorTypes.length;i++)
+ noMetaCtorTypes[i-1] = ctorTypes[i];
+ Method alt = new Method("<init>", Type.VOID_TYPE, noMetaCtorTypes);
+ ctorgen = new GeneratorAdapter(ACC_PUBLIC,
+ alt,
+ null,
+ null,
+ cv);
+ ctorgen.visitCode();
+ ctorgen.loadThis();
+ ctorgen.visitInsn(Opcodes.ACONST_NULL); //null meta
+ ctorgen.loadArgs();
+ ctorgen.invokeConstructor(objtype, new Method("<init>", Type.VOID_TYPE, ctorTypes));
+
+ ctorgen.returnValue();
+ ctorgen.endMethod();
+
+ //meta()
+ Method meth = Method.getMethod("clojure.lang.IPersistentMap meta()");
+
+ GeneratorAdapter gen = new GeneratorAdapter(ACC_PUBLIC,
+ meth,
+ null,
+ null,
+ cv);
+ gen.visitCode();
+ gen.loadThis();
+ gen.getField(objtype,"__meta",IPERSISTENTMAP_TYPE);
+
+ gen.returnValue();
+ gen.endMethod();
+
+ //withMeta()
+ meth = Method.getMethod("clojure.lang.IObj withMeta(clojure.lang.IPersistentMap)");
+
+ gen = new GeneratorAdapter(ACC_PUBLIC,
+ meth,
+ null,
+ null,
+ cv);
+ gen.visitCode();
+ gen.newInstance(objtype);
+ gen.dup();
+ gen.loadArg(0);
+
+ for(ISeq s = RT.keys(closes); s != null; s = s.next(), ++a)
+ {
+ LocalBinding lb = (LocalBinding) s.first();
+ gen.loadThis();
+ Class primc = lb.getPrimitiveType();
+ if(primc != null)
+ {
+ gen.getField(objtype, lb.name, Type.getType(primc));
+ }
+ else
+ {
+ gen.getField(objtype, lb.name, OBJECT_TYPE);
+ }
+ }
+
+ gen.invokeConstructor(objtype, new Method("<init>", Type.VOID_TYPE, ctorTypes));
+ gen.returnValue();
+ gen.endMethod();
+ }
+
emitMethods(cv);
if(keywordCallsites.count() > 0)
@@ -3888,6 +3984,7 @@ static public class ObjExpr implements Expr{
{
gen.newInstance(objtype);
gen.dup();
+ gen.visitInsn(Opcodes.ACONST_NULL);
for(ISeq s = RT.seq(closesExprs); s != null; s = s.next())
{
LocalBindingExpr lbe = (LocalBindingExpr) s.first();
@@ -5280,7 +5377,12 @@ private static int registerConstant(Object o){
if(!CONSTANTS.isBound())
return -1;
PersistentVector v = (PersistentVector) CONSTANTS.deref();
+ IdentityHashMap<Object,Integer> ids = (IdentityHashMap<Object,Integer>) CONSTANT_IDS.deref();
+ Integer i = ids.get(o);
+ if(i != null)
+ return i;
CONSTANTS.set(RT.conj(v, o));
+ ids.put(o, v.count());
return v.count();
}
@@ -5757,6 +5859,7 @@ public static Object compile(Reader rdr, String sourcePath, String sourceName) t
LINE_BEFORE, pushbackReader.getLineNumber(),
LINE_AFTER, pushbackReader.getLineNumber(),
CONSTANTS, PersistentVector.EMPTY,
+ CONSTANT_IDS, new IdentityHashMap(),
KEYWORDS, PersistentHashMap.EMPTY,
VARS, PersistentHashMap.EMPTY
,LOADER, RT.makeClassLoader()
@@ -5970,6 +6073,7 @@ static public class NewInstanceExpr extends ObjExpr{
{
Var.pushThreadBindings(
RT.map(CONSTANTS, PersistentVector.EMPTY,
+ CONSTANT_IDS, new IdentityHashMap(),
KEYWORDS, PersistentHashMap.EMPTY,
VARS, PersistentHashMap.EMPTY,
KEYWORD_CALLSITES, PersistentVector.EMPTY,
diff --git a/src/jvm/clojure/lang/PersistentArrayMap.java b/src/jvm/clojure/lang/PersistentArrayMap.java
index 75ebe964..8f63e5f8 100644
--- a/src/jvm/clojure/lang/PersistentArrayMap.java
+++ b/src/jvm/clojure/lang/PersistentArrayMap.java
@@ -25,12 +25,13 @@ import java.util.Map;
* null keys and values are ok, but you won't be able to distinguish a null value via valAt - use contains/entryAt
*/
-public class PersistentArrayMap extends APersistentMap implements IEditableCollection {
+public class PersistentArrayMap extends APersistentMap implements IObj, IEditableCollection {
final Object[] array;
static final int HASHTABLE_THRESHOLD = 16;
public static final PersistentArrayMap EMPTY = new PersistentArrayMap();
+private final IPersistentMap _meta;
static public IPersistentMap create(Map other){
ITransientMap ret = EMPTY.asTransient();
@@ -44,6 +45,7 @@ static public IPersistentMap create(Map other){
protected PersistentArrayMap(){
this.array = new Object[]{};
+ this._meta = null;
}
public PersistentArrayMap withMeta(IPersistentMap meta){
@@ -65,11 +67,12 @@ IPersistentMap createHT(Object[] init){
*/
public PersistentArrayMap(Object[] init){
this.array = init;
+ this._meta = null;
}
public PersistentArrayMap(IPersistentMap meta, Object[] init){
- super(meta);
+ this._meta = meta;
this.array = init;
}
@@ -198,6 +201,10 @@ public ISeq seq(){
return null;
}
+public IPersistentMap meta(){
+ return _meta;
+}
+
static class Seq extends ASeq implements Counted{
final Object[] array;
final int i;
diff --git a/src/jvm/clojure/lang/PersistentHashMap.java b/src/jvm/clojure/lang/PersistentHashMap.java
index 1f223e61..4fae3f30 100644
--- a/src/jvm/clojure/lang/PersistentHashMap.java
+++ b/src/jvm/clojure/lang/PersistentHashMap.java
@@ -25,12 +25,13 @@ import java.util.concurrent.atomic.AtomicReference;
Any errors are my own
*/
-public class PersistentHashMap extends APersistentMap implements IEditableCollection {
+public class PersistentHashMap extends APersistentMap implements IEditableCollection, IObj {
final int count;
final INode root;
final boolean hasNull;
final Object nullValue;
+final IPersistentMap _meta;
final public static PersistentHashMap EMPTY = new PersistentHashMap(0, null, false, null);
final private static Object NOT_FOUND = new Object();
@@ -93,10 +94,11 @@ PersistentHashMap(int count, INode root, boolean hasNull, Object nullValue){
this.root = root;
this.hasNull = hasNull;
this.nullValue = nullValue;
+ this._meta = null;
}
public PersistentHashMap(IPersistentMap meta, int count, INode root, boolean hasNull, Object nullValue){
- super(meta);
+ this._meta = meta;
this.count = count;
this.root = root;
this.hasNull = hasNull;
@@ -186,6 +188,10 @@ public TransientHashMap asTransient() {
return new TransientHashMap(this);
}
+public IPersistentMap meta(){
+ return _meta;
+}
+
static final class TransientHashMap extends ATransientMap {
AtomicReference<Thread> edit;
INode root;
diff --git a/src/jvm/clojure/lang/PersistentHashSet.java b/src/jvm/clojure/lang/PersistentHashSet.java
index 73a5a61f..eced8663 100644
--- a/src/jvm/clojure/lang/PersistentHashSet.java
+++ b/src/jvm/clojure/lang/PersistentHashSet.java
@@ -14,10 +14,12 @@ package clojure.lang;
import java.util.List;
-public class PersistentHashSet extends APersistentSet implements IEditableCollection {
+public class PersistentHashSet extends APersistentSet implements IObj, IEditableCollection {
static public final PersistentHashSet EMPTY = new PersistentHashSet(null, PersistentHashMap.EMPTY);
+final IPersistentMap _meta;
+
public static PersistentHashSet create(Object... init){
PersistentHashSet ret = EMPTY;
for(int i = 0; i < init.length; i++)
@@ -46,7 +48,8 @@ static public PersistentHashSet create(ISeq items){
}
PersistentHashSet(IPersistentMap meta, IPersistentMap impl){
- super(meta, impl);
+ super(impl);
+ this._meta = meta;
}
public IPersistentSet disjoin(Object key) throws Exception{
@@ -73,6 +76,10 @@ public ITransientCollection asTransient() {
return new TransientHashSet(((PersistentHashMap) impl).asTransient());
}
+public IPersistentMap meta(){
+ return _meta;
+}
+
static final class TransientHashSet extends ATransientSet {
TransientHashSet(ITransientMap impl) {
super(impl);
diff --git a/src/jvm/clojure/lang/PersistentList.java b/src/jvm/clojure/lang/PersistentList.java
index 912d2f8d..477d1cba 100644
--- a/src/jvm/clojure/lang/PersistentList.java
+++ b/src/jvm/clojure/lang/PersistentList.java
@@ -37,6 +37,14 @@ public static IFn creator = new RestFn(){
list.add(s.first());
return create(list);
}
+
+ public IObj withMeta(IPersistentMap meta){
+ throw new UnsupportedOperationException();
+ }
+
+ public IPersistentMap meta(){
+ return null;
+ }
};
final public static EmptyList EMPTY = new EmptyList(null);
diff --git a/src/jvm/clojure/lang/PersistentStructMap.java b/src/jvm/clojure/lang/PersistentStructMap.java
index 1331ceb1..b015203f 100644
--- a/src/jvm/clojure/lang/PersistentStructMap.java
+++ b/src/jvm/clojure/lang/PersistentStructMap.java
@@ -16,7 +16,7 @@ import java.util.Iterator;
import java.util.Map;
import java.io.Serializable;
-public class PersistentStructMap extends APersistentMap{
+public class PersistentStructMap extends APersistentMap implements IObj{
public static class Def implements Serializable{
final ISeq keys;
@@ -31,6 +31,8 @@ public static class Def implements Serializable{
final Def def;
final Object[] vals;
final IPersistentMap ext;
+final IPersistentMap _meta;
+
static public Def createSlotMap(ISeq keys){
if(keys == null)
@@ -94,7 +96,7 @@ static public IFn getAccessor(final Def def, Object key){
}
protected PersistentStructMap(IPersistentMap meta, Def def, Object[] vals, IPersistentMap ext){
- super(meta);
+ this._meta = meta;
this.ext = ext;
this.def = def;
this.vals = vals;
@@ -111,12 +113,16 @@ protected PersistentStructMap makeNew(IPersistentMap meta, Def def, Object[] val
return new PersistentStructMap(meta, def, vals, ext);
}
-public Obj withMeta(IPersistentMap meta){
+public IObj withMeta(IPersistentMap meta){
if(meta == _meta)
return this;
return makeNew(meta, def, vals, ext);
}
+public IPersistentMap meta(){
+ return _meta;
+}
+
public boolean containsKey(Object key){
return def.keyslots.containsKey(key) || ext.containsKey(key);
}
diff --git a/src/jvm/clojure/lang/PersistentTreeMap.java b/src/jvm/clojure/lang/PersistentTreeMap.java
index d69952b9..4fd987f4 100644
--- a/src/jvm/clojure/lang/PersistentTreeMap.java
+++ b/src/jvm/clojure/lang/PersistentTreeMap.java
@@ -22,11 +22,12 @@ import java.util.*;
* See Okasaki, Kahrs, Larsen et al
*/
-public class PersistentTreeMap extends APersistentMap implements Reversible, Sorted{
+public class PersistentTreeMap extends APersistentMap implements IObj, Reversible, Sorted{
public final Comparator comp;
public final Node tree;
public final int _count;
+final IPersistentMap _meta;
final static public PersistentTreeMap EMPTY = new PersistentTreeMap();
@@ -54,14 +55,14 @@ private PersistentTreeMap(Comparator comp){
public PersistentTreeMap(IPersistentMap meta, Comparator comp){
- super(meta);
this.comp = comp;
+ this._meta = meta;
tree = null;
_count = 0;
}
PersistentTreeMap(IPersistentMap meta, Comparator comp, Node tree, int _count){
- super(meta);
+ this._meta = meta;
this.comp = comp;
this.tree = tree;
this._count = _count;
@@ -441,7 +442,7 @@ Node replace(Node t, Object key, Object val){
}
PersistentTreeMap(Comparator comp, Node tree, int count, IPersistentMap meta){
- super(meta);
+ this._meta = meta;
this.comp = comp;
this.tree = tree;
this._count = count;
@@ -471,6 +472,10 @@ static Black black(Object key, Object val, Node left, Node right){
return new BlackBranchVal(key, val, left, right);
}
+public IPersistentMap meta(){
+ return _meta;
+}
+
static abstract class Node extends AMapEntry{
final Object key;
diff --git a/src/jvm/clojure/lang/PersistentTreeSet.java b/src/jvm/clojure/lang/PersistentTreeSet.java
index 22979f11..d55452c7 100644
--- a/src/jvm/clojure/lang/PersistentTreeSet.java
+++ b/src/jvm/clojure/lang/PersistentTreeSet.java
@@ -14,8 +14,9 @@ package clojure.lang;
import java.util.Comparator;
-public class PersistentTreeSet extends APersistentSet implements Reversible, Sorted{
+public class PersistentTreeSet extends APersistentSet implements IObj, Reversible, Sorted{
static public final PersistentTreeSet EMPTY = new PersistentTreeSet(null, PersistentTreeMap.EMPTY);
+final IPersistentMap _meta;
static public PersistentTreeSet create(ISeq items){
@@ -37,7 +38,8 @@ static public PersistentTreeSet create(Comparator comp, ISeq items){
}
PersistentTreeSet(IPersistentMap meta, IPersistentMap impl){
- super(meta, impl);
+ super(impl);
+ this._meta = meta;
}
public IPersistentSet disjoin(Object key) throws Exception{
@@ -82,4 +84,7 @@ public ISeq seqFrom(Object key, boolean ascending){
return RT.keys(m.seqFrom(key,ascending));
}
+public IPersistentMap meta(){
+ return _meta;
+}
}
diff --git a/src/jvm/clojure/lang/PersistentVector.java b/src/jvm/clojure/lang/PersistentVector.java
index 392599c9..878d5711 100644
--- a/src/jvm/clojure/lang/PersistentVector.java
+++ b/src/jvm/clojure/lang/PersistentVector.java
@@ -15,7 +15,7 @@ package clojure.lang;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
-public class PersistentVector extends APersistentVector implements IEditableCollection{
+public class PersistentVector extends APersistentVector implements IObj, IEditableCollection{
static class Node{
final AtomicReference<Thread> edit;
@@ -39,6 +39,8 @@ final int cnt;
final int shift;
final Node root;
final Object[] tail;
+final IPersistentMap _meta;
+
public final static PersistentVector EMPTY = new PersistentVector(0, 5, EMPTY_NODE, new Object[]{});
@@ -64,7 +66,7 @@ static public PersistentVector create(Object... items){
}
PersistentVector(int cnt, int shift, Node root, Object[] tail){
- super(null);
+ this._meta = null;
this.cnt = cnt;
this.shift = shift;
this.root = root;
@@ -73,7 +75,7 @@ PersistentVector(int cnt, int shift, Node root, Object[] tail){
PersistentVector(IPersistentMap meta, int cnt, int shift, Node root, Object[] tail){
- super(meta);
+ this._meta = meta;
this.cnt = cnt;
this.shift = shift;
this.root = root;
@@ -149,6 +151,10 @@ public PersistentVector withMeta(IPersistentMap meta){
return new PersistentVector(meta, cnt, shift, root, tail);
}
+public IPersistentMap meta(){
+ return _meta;
+}
+
public PersistentVector cons(Object val){
int i = cnt;
diff --git a/src/jvm/clojure/lang/Symbol.java b/src/jvm/clojure/lang/Symbol.java
index 001043d9..dbf3b36e 100644
--- a/src/jvm/clojure/lang/Symbol.java
+++ b/src/jvm/clojure/lang/Symbol.java
@@ -16,11 +16,12 @@ import java.io.Serializable;
import java.io.ObjectStreamException;
-public class Symbol extends AFn implements Comparable, Named, Serializable{
+public class Symbol extends AFn implements IObj, Comparable, Named, Serializable{
//these must be interned strings!
final String ns;
final String name;
final int hash;
+final IPersistentMap _meta;
public String toString(){
if(ns != null)
@@ -60,6 +61,7 @@ private Symbol(String ns_interned, String name_interned){
this.name = name_interned;
this.ns = ns_interned;
this.hash = Util.hashCombine(name.hashCode(), Util.hash(ns));
+ this._meta = null;
}
public boolean equals(Object o){
@@ -78,14 +80,14 @@ public int hashCode(){
return hash;
}
-public Obj withMeta(IPersistentMap meta){
+public IObj withMeta(IPersistentMap meta){
return new Symbol(meta, ns, name);
}
private Symbol(IPersistentMap meta, String ns, String name){
- super(meta);
this.name = name;
this.ns = ns;
+ this._meta = meta;
this.hash = Util.hashCombine(name.hashCode(), Util.hash(ns));
}
@@ -118,4 +120,7 @@ public Object invoke(Object obj, Object notFound) throws Exception{
return RT.get(obj, this, notFound);
}
+public IPersistentMap meta(){
+ return _meta;
+}
}
diff --git a/test/clojure/test_clojure/evaluation.clj b/test/clojure/test_clojure/evaluation.clj
index 283896c5..3269c58f 100644
--- a/test/clojure/test_clojure/evaluation.clj
+++ b/test/clojure/test_clojure/evaluation.clj
@@ -184,10 +184,6 @@
(defstruct struct-with-symbols (with-meta 'k {:a "A"}))
(deftest Metadata
- (test-that
- "If a Symbol has metadata, it will not be part of the resulting value"
- (is (not (nil? (meta (with-meta (symbol "test") {:doc "doc"})))))
- (is (nil? (meta (eval (with-meta (symbol "test") {:doc "doc"}))))))
(test-that
"find returns key symbols and their metadata"