summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRich Hickey <richhickey@gmail.com>2008-02-08 19:11:58 +0000
committerRich Hickey <richhickey@gmail.com>2008-02-08 19:11:58 +0000
commit221023b4d27e75757e3c842176872d5300d35b23 (patch)
treeea3e1258301ad03d852fc267b6462dad8a6e3cee /src
parent81d57a3b85548d82668494a95368524087055665 (diff)
var metadata
Diffstat (limited to 'src')
-rw-r--r--src/boot.clj42
-rw-r--r--src/jvm/clojure/lang/Compiler.java52
-rw-r--r--src/jvm/clojure/lang/LispReader.java5
-rw-r--r--src/jvm/clojure/lang/RT.java4
-rw-r--r--src/jvm/clojure/lang/Var.java57
5 files changed, 95 insertions, 65 deletions
diff --git a/src/boot.clj b/src/boot.clj
index ad3d540e..302d22ef 100644
--- a/src/boot.clj
+++ b/src/boot.clj
@@ -16,7 +16,7 @@
(def defn (fn [name & fdecl]
(list 'def name (cons 'fn (cons name fdecl)))))
-(. (the-var defn) (setMacro))
+(. (var defn) (setMacro))
(defn instance? [#^Class c x]
(. c (isInstance x)))
@@ -52,9 +52,9 @@
(def defmacro (fn [name & args]
(list 'do
(cons 'defn (cons name args))
- (list '. (list 'the-var name) '(setMacro)))))
+ (list '. (list 'var name) '(setMacro)))))
-(. (the-var defmacro) (setMacro))
+(. (var defmacro) (setMacro))
(defmacro when [test & body]
(list 'if test (cons 'do body)))
@@ -414,11 +414,11 @@
`(def ~name (new clojure.lang.MultiFn ~dispatch-fn ~default-val))))
(defmacro defmethod [multifn dispatch-val & fn-tail]
- `(let [pvar# (the-var ~multifn)]
+ `(let [pvar# (var ~multifn)]
(. pvar# (commuteRoot (fn [mf#] (. mf# (assoc ~dispatch-val (fn ~@fn-tail))))))))
(defmacro remove-method [multifn dispatch-val]
- `(let [pvar# (the-var ~multifn)]
+ `(let [pvar# (var ~multifn)]
(. pvar# (commuteRoot (fn [mf#] (. mf# (dissoc ~dispatch-val)))))))
;;;;;;;;; var stuff
@@ -427,7 +427,7 @@
(let [var-ize (fn [var-vals]
(loop [ret [] vvs (seq var-vals)]
(if vvs
- (recur (conj (conj ret `(the-var ~(first vvs))) (second vvs))
+ (recur (conj (conj ret `(var ~(first vvs))) (second vvs))
(rest (rest vvs)))
(seq ret))))]
`(try
@@ -994,13 +994,14 @@
(defn ns-unmap [#^clojure.lang.Namespace ns sym]
(. ns (unmap sym)))
-(defn export [syms]
- (doseq sym syms
- (.. *ns* (intern sym) (setExported true))))
+;(defn export [syms]
+; (doseq sym syms
+; (.. *ns* (intern sym) (setExported true))))
(defn ns-exports [#^clojure.lang.Namespace ns]
(filter-key val (fn [v] (and (instance? clojure.lang.Var v)
- (. v (isExported))))
+ (= ns (. v ns))
+ (. v (isPublic))))
(ns-map ns)))
(defn ns-imports [#^clojure.lang.Namespace ns]
@@ -1015,10 +1016,10 @@
to-do (or (:only fs) (keys nsexports))]
(doseq sym to-do
(when-not (exclude sym)
- (let [var (nsexports sym)]
- (when-not var
+ (let [v (nsexports sym)]
+ (when-not v
(throw (new java.lang.IllegalAccessError (strcat sym " is not exported"))))
- (. *ns* (refer (or (rename sym) sym) var)))))))
+ (. *ns* (refer (or (rename sym) sym) v)))))))
(defn ns-refers [#^clojure.lang.Namespace ns]
(filter-key val (fn [v] (and (instance? clojure.lang.Var v)
@@ -1183,14 +1184,14 @@
(def defn* (fn [name & fdecl]
(list 'def name (cons `fn* (cons name fdecl)))))
-(. (the-var defn*) (setMacro))
+(. (var defn*) (setMacro))
(def defmacro* (fn [name & args]
(list 'do
(cons `defn* (cons name args))
- (list '. (list 'the-var name) '(setMacro)))))
+ (list '. (list 'var name) '(setMacro)))))
-(. (the-var defmacro*) (setMacro))
+(. (var defmacro*) (setMacro))
(defn bean [#^Object x]
(let [c (. x (getClass))
@@ -1216,6 +1217,9 @@
(lazy-cons (new clojure.lang.MapEntry (first pseq) (v (first pseq)))
(this (rest pseq))))) (keys pmap))))))
+(defmacro comment [& body])
+
+(comment
(export
'( load-file load
list cons conj defn
@@ -1269,7 +1273,8 @@
*warn-on-reflection*
resultset-seq
to-set distinct
- export ns-exports ns-imports ns-map
+ export
+ ns-exports ns-imports ns-map
identical? instance?
load-file in-ns find-ns
filter-key find-ns create-ns remove-ns
@@ -1281,6 +1286,7 @@
nthrest
string? symbol? map? seq? vector?
let* fn* defn* defmacro*
- bean
+ bean select
))
+ )
diff --git a/src/jvm/clojure/lang/Compiler.java b/src/jvm/clojure/lang/Compiler.java
index eb651994..637c28b7 100644
--- a/src/jvm/clojure/lang/Compiler.java
+++ b/src/jvm/clojure/lang/Compiler.java
@@ -28,7 +28,6 @@ import org.objectweb.asm.util.CheckClassAdapter;
//*/
import java.io.*;
-import java.math.BigInteger;
import java.util.List;
import java.util.ArrayList;
import java.util.LinkedList;
@@ -45,7 +44,7 @@ static final Symbol LET = Symbol.create("let");
static final Symbol DO = Symbol.create("do");
static final Symbol FN = Symbol.create("fn");
static final Symbol QUOTE = Symbol.create("quote");
-static final Symbol THE_VAR = Symbol.create("the-var");
+static final Symbol THE_VAR = Symbol.create("var");
static final Symbol DOT = Symbol.create(".");
static final Symbol ASSIGN = Symbol.create("set!");
//static final Symbol TRY_FINALLY = Symbol.create("try-finally");
@@ -117,6 +116,7 @@ final static Type CLASS_TYPE = Type.getType(Class.class);
final static Type REFLECTOR_TYPE = Type.getType(Reflector.class);
final static Type THROWABLE_TYPE = Type.getType(Throwable.class);
final static Type BOOLEAN_OBJECT_TYPE = Type.getType(Boolean.class);
+final static Type IPERSISTENTMAP_TYPE = Type.getType(IPersistentMap.class);
private static final Type[][] ARG_TYPES;
private static final Type[] EXCEPTION_TYPES = {Type.getType(Exception.class)};
@@ -238,23 +238,27 @@ static Symbol resolveSymbol(Symbol sym){
static class DefExpr implements Expr{
final Var var;
final Expr init;
- final Symbol tag;
+ final Expr meta;
final boolean initProvided;
final static Method bindRootMethod = Method.getMethod("void bindRoot(Object)");
final static Method setTagMethod = Method.getMethod("void setTag(clojure.lang.Symbol)");
+ final static Method setMetaMethod = Method.getMethod("void setMeta(clojure.lang.IPersistentMap)");
final static Method symcreate = Method.getMethod("clojure.lang.Symbol create(String, String)");
- public DefExpr(Var var, Expr init, boolean initProvided, Symbol tag){
+ public DefExpr(Var var, Expr init, Expr meta, boolean initProvided){
this.var = var;
this.init = init;
+ this.meta = meta;
this.initProvided = initProvided;
- this.tag = tag;
}
public Object eval() throws Exception{
if(initProvided)
var.bindRoot(init.eval());
- var.setTag(tag);
+ if(meta != null)
+ {
+ var.setMeta((IPersistentMap) meta.eval());
+ }
return var;
}
@@ -266,16 +270,14 @@ static class DefExpr implements Expr{
init.emit(C.EXPRESSION, fn, gen);
gen.invokeVirtual(VAR_TYPE, bindRootMethod);
}
- gen.dup();
- if(tag != null)
+ if(meta != null)
{
- gen.push(tag.ns);
- gen.push(tag.name);
- gen.invokeStatic(SYMBOL_TYPE, symcreate);
+ gen.dup();
+ meta.emit(C.EXPRESSION, fn, gen);
+ gen.checkCast(IPERSISTENTMAP_TYPE);
+ gen.invokeVirtual(VAR_TYPE, setMetaMethod);
}
- else
- gen.visitInsn(Opcodes.ACONST_NULL);
- gen.invokeVirtual(VAR_TYPE, setTagMethod);
+
if(context == C.STATEMENT)
gen.pop();
}
@@ -305,12 +307,15 @@ static class DefExpr implements Expr{
{
if(sym.ns == null)
throw new Exception("Name conflict, can't def " + sym + " because namespace: " + currentNS().name +
- " refers to:" + v.sym);
+ " refers to:" + v);
else
throw new Exception("Can't create defs outside of current ns");
}
+ IPersistentMap mm = sym.meta();
+ mm = (IPersistentMap) RT.assoc(mm, RT.LINE_KEY, LINE.get()).assoc(RT.FILE_KEY,SOURCE.get());
+ Expr meta = analyze(context == C.EVAL ? context : C.EXPRESSION, mm);
return new DefExpr(v, analyze(context == C.EVAL ? context : C.EXPRESSION, RT.third(form), v.sym.name),
- RT.count(form) == 3, tagOf(sym));
+ meta, RT.count(form) == 3);
}
}
}
@@ -356,7 +361,7 @@ static class AssignExpr implements Expr{
static class VarExpr implements Expr, AssignableExpr{
final Var var;
- final Symbol tag;
+ final Object tag;
final static Method getMethod = Method.getMethod("Object get()");
final static Method setMethod = Method.getMethod("Object set(Object)");
@@ -735,7 +740,7 @@ static abstract class HostExpr implements Expr{
return className;
}
*/
- static Class tagToClass(Symbol tag) throws Exception{
+ static Class tagToClass(Object tag) throws Exception{
Class c = maybeClass(tag, true);
if(c != null)
return c;
@@ -1906,7 +1911,6 @@ static class NewExpr implements Expr{
static class MetaExpr implements Expr{
final Expr expr;
final MapExpr meta;
- final static Type IPERSISTENTMAP_TYPE = Type.getType(IPersistentMap.class);
final static Type IOBJ_TYPE = Type.getType(IObj.class);
final static Method withMetaMethod = Method.getMethod("clojure.lang.IObj withMeta(clojure.lang.IPersistentMap)");
@@ -2226,7 +2230,7 @@ static class VectorExpr implements Expr{
static class InvokeExpr implements Expr{
final Expr fexpr;
- final Symbol tag;
+ final Object tag;
final IPersistentVector args;
final int line;
@@ -3146,7 +3150,7 @@ static public Var isMacro(Object op) throws Exception{
Var v = (op instanceof Var) ? (Var) op : lookupVar((Symbol) op, false);
if(v != null && v.isMacro())
{
- if(v.ns != currentNS() && !v.isExported())
+ if(v.ns != currentNS() && !v.isPublic())
throw new IllegalAccessError("var: " + v + " is not exported");
return v;
}
@@ -3158,8 +3162,8 @@ private static Expr analyzeSeq(C context, ISeq form, String name) throws Excepti
Integer line = (Integer) LINE.get();
try
{
- if(RT.meta(form) != null && RT.meta(form).containsKey(LispReader.LINE_KEY))
- line = (Integer) RT.meta(form).valAt(LispReader.LINE_KEY);
+ if(RT.meta(form) != null && RT.meta(form).containsKey(RT.LINE_KEY))
+ line = (Integer) RT.meta(form).valAt(RT.LINE_KEY);
Var.pushThreadBindings(
RT.map(LINE, line));
Object op = RT.first(form);
@@ -3275,7 +3279,7 @@ static public Object resolveIn(Namespace n, Symbol sym) throws Exception{
Var v = ns.findInternedVar(Symbol.create(sym.name));
if(v == null)
throw new Exception("No such var: " + sym);
- else if(v.ns != currentNS() && !v.isExported())
+ else if(v.ns != currentNS() && !v.isPublic())
throw new IllegalAccessError("var: " + sym + " is not exported");
return v;
}
diff --git a/src/jvm/clojure/lang/LispReader.java b/src/jvm/clojure/lang/LispReader.java
index 52db79c6..e2c12ae1 100644
--- a/src/jvm/clojure/lang/LispReader.java
+++ b/src/jvm/clojure/lang/LispReader.java
@@ -32,7 +32,6 @@ static Symbol WITH_META = Symbol.create("clojure", "with-meta");
static Symbol META = Symbol.create("clojure", "meta");
static Symbol DEREF = Symbol.create("clojure", "deref");
//static Symbol DEREF_BANG = Symbol.create("clojure", "deref!");
-static Keyword LINE_KEY = Keyword.intern("clojure", "line");
static IFn[] macros = new IFn[256];
static IFn[] dispatchMacros = new IFn[256];
@@ -374,7 +373,7 @@ static class MetaReader extends AFn{
if(o instanceof IObj)
{
if(line != -1 && o instanceof ISeq)
- meta = ((IPersistentMap) meta).assoc(LINE_KEY, line);
+ meta = ((IPersistentMap) meta).assoc(RT.LINE_KEY, line);
return ((IObj) o).withMeta((IPersistentMap) meta);
}
else
@@ -557,7 +556,7 @@ static class ListReader extends AFn{
IObj s = (IObj) PersistentList.create(list);
// IObj s = (IObj) RT.seq(list);
if(line != -1)
- return s.withMeta(RT.map(LINE_KEY, line));
+ return s.withMeta(RT.map(RT.LINE_KEY, line));
else
return s;
}
diff --git a/src/jvm/clojure/lang/RT.java b/src/jvm/clojure/lang/RT.java
index 1ede12f4..90ec1602 100644
--- a/src/jvm/clojure/lang/RT.java
+++ b/src/jvm/clojure/lang/RT.java
@@ -108,8 +108,10 @@ final static public Var OUT =
final static public Var IN =
Var.intern(CLOJURE_NS, Symbol.create("*in*"),
new LineNumberingPushbackReader(new InputStreamReader(System.in)));
-final static Keyword TAG_KEY = Keyword.intern("clojure", "tag");
+final static Keyword TAG_KEY = Keyword.intern(null, "tag");
final static Keyword AGENT_KEY = Keyword.intern("clojure", "agent");
+static Keyword LINE_KEY = Keyword.intern(null, "line");
+static Keyword FILE_KEY = Keyword.intern(null, "file");
//final static public Var CURRENT_MODULE = Var.intern(Symbol.create("clojure", "current-module"),
// Module.findOrCreateModule("clojure/user"));
diff --git a/src/jvm/clojure/lang/Var.java b/src/jvm/clojure/lang/Var.java
index 25c67e94..37f3bacd 100644
--- a/src/jvm/clojure/lang/Var.java
+++ b/src/jvm/clojure/lang/Var.java
@@ -12,11 +12,11 @@
package clojure.lang;
-import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicInteger;
-public final class Var implements IFn, IRef{
+public final class Var implements IFn, IRef, IObj{
+
static class Frame{
//Var->Box
@@ -44,13 +44,18 @@ static ThreadLocal<Frame> dvals = new ThreadLocal<Frame>(){
}
};
+static Keyword privateKey = Keyword.intern(null, "private");
+static Keyword macroKey = Keyword.intern(null, "macro");
+static Keyword nameKey = Keyword.intern(null, "name");
+static Keyword nsKey = Keyword.intern(null, "ns");
+//static Keyword tagKey = Keyword.intern(null, "tag");
+
volatile Object root;
transient final AtomicInteger count;
-final public Symbol sym;
-final public Namespace ns;
-boolean macroFlag = false;
-boolean exported = false;
-Symbol tag;
+public final Symbol sym;
+public final Namespace ns;
+
+IPersistentMap _meta;
public static Var intern(Namespace ns, Symbol sym, Object root){
return intern(ns, sym, root, true);
@@ -67,7 +72,7 @@ public static Var intern(Namespace ns, Symbol sym, Object root, boolean replaceR
public String toString(){
return "#<Var: " + (ns != null ? (ns.name + "/") : "") +
(sym != null ? sym.toString() : "--unnamed--") +
- (exported?" (exported)":"") + ">";
+ ">";
}
public static Var find(Symbol nsQualifiedSym){
@@ -102,6 +107,7 @@ Var(Namespace ns, Symbol sym){
this.sym = sym;
this.count = new AtomicInteger();
this.root = dvals; //use dvals as magic not-bound value
+ setMeta(PersistentHashMap.EMPTY);
}
Var(Namespace ns, Symbol sym, Object root){
@@ -140,32 +146,45 @@ public Object set(Object val){
throw new IllegalStateException(String.format("Can't change/establish root binding of: %s with set", sym));
}
+public void setMeta(IPersistentMap m){
+ //ensure these basis keys
+ _meta = m.assoc(nameKey, sym).assoc(nsKey, ns);
+}
+
+public IPersistentMap meta(){
+ return _meta;
+}
+
+public IObj withMeta(IPersistentMap meta){
+ throw new UnsupportedOperationException("Vars are not values");
+}
+
public void setMacro(){
- macroFlag = true;
+ _meta = _meta.assoc(macroKey, RT.T);
}
public boolean isMacro(){
- return macroFlag;
+ return RT.booleanCast(_meta.valAt(macroKey));
}
-public void setExported(boolean state){
- exported = state;
-}
+//public void setExported(boolean state){
+// _meta = _meta.assoc(privateKey, state);
+//}
-public boolean isExported(){
- return exported;
+public boolean isPublic(){
+ return !RT.booleanCast(_meta.valAt(privateKey));
}
public Object getRoot(){
return root;
}
-public Symbol getTag(){
- return tag;
+public Object getTag(){
+ return _meta.valAt(RT.TAG_KEY);
}
public void setTag(Symbol tag){
- this.tag = tag;
+ _meta = _meta.assoc(RT.TAG_KEY, tag);
}
final public boolean hasRoot(){
@@ -175,7 +194,7 @@ final public boolean hasRoot(){
//binding root always clears macro flag
synchronized public void bindRoot(Object root){
this.root = root;
- macroFlag = false;
+ _meta = _meta.assoc(macroKey, RT.F);
}
synchronized public void unbindRoot(){