summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/clojure/boot.clj16
-rw-r--r--src/jvm/clojure/lang/Compiler.java31
-rw-r--r--src/jvm/clojure/lang/Namespace.java41
3 files changed, 78 insertions, 10 deletions
diff --git a/src/clojure/boot.clj b/src/clojure/boot.clj
index 89cda99d..b585c5ca 100644
--- a/src/clojure/boot.clj
+++ b/src/clojure/boot.clj
@@ -1934,6 +1934,22 @@ not-every? (comp not every?))
(= ns (. v ns))))
(ns-map ns)))
+(defn alias
+ "Add an alias in the current namespace to another
+ namespace. Arguments are two symbols: the alias to be used, and
+ the symbolic name of the target namespace."
+ [alias namespace-sym]
+ (.addAlias *ns* alias (find-ns namespace-sym)))
+
+(defn ns-aliases
+ "Returns a map of the aliases for the namespace."
+ [#^clojure.lang.Namespace ns] (.getAliases ns))
+
+(defn ns-unalias
+ "Removes the alias for the symbol from the namespace."
+ [#^clojure.lang.Namespace ns sym]
+ (. ns (removeAlias sym)))
+
(defn take-nth
"Returns a lazy seq of every nth item in coll."
[n coll]
diff --git a/src/jvm/clojure/lang/Compiler.java b/src/jvm/clojure/lang/Compiler.java
index 700116c3..c3cba099 100644
--- a/src/jvm/clojure/lang/Compiler.java
+++ b/src/jvm/clojure/lang/Compiler.java
@@ -3748,9 +3748,9 @@ public static Object macroexpand1(Object x) throws Exception{
}
else if(sym.ns != null)
{
- Symbol target = Symbol.intern(sym.ns);
- if(Namespace.find(target) == null)
+ if(namespaceFor(sym) == null)
{
+ Symbol target = Symbol.intern(sym.ns);
Class c = HostExpr.maybeClass(target, false);
if(c != null)
{
@@ -3884,9 +3884,9 @@ private static Expr analyzeSymbol(Symbol sym) throws Exception{
}
else
{
- Symbol nsSym = Symbol.create(sym.ns);
- if(Namespace.find(nsSym) == null)
+ if(namespaceFor(sym) == null)
{
+ Symbol nsSym = Symbol.create(sym.ns);
Class c = HostExpr.maybeClass(nsSym, false);
if(c != null)
{
@@ -3916,13 +3916,27 @@ static Object resolve(Symbol sym) throws Exception{
return resolveIn(currentNS(), sym);
}
+static private Namespace namespaceFor(Symbol sym) {
+ //note, presumes non-nil sym.ns
+ // first check against currentNS' aliases...
+ Symbol nsSym = Symbol.create(sym.ns);
+ Namespace ns = currentNS().lookupAlias(nsSym);
+ if (ns == null)
+ {
+ // ...otherwise check the Namespaces map.
+ ns = Namespace.find(nsSym);
+ }
+ return ns;
+}
+
static public Object resolveIn(Namespace n, Symbol sym) throws Exception{
//note - ns-qualified vars must already exist
if(sym.ns != null)
{
- Namespace ns = Namespace.find(Symbol.create(sym.ns));
+ Namespace ns = namespaceFor(sym);
if(ns == null)
throw new Exception("No such namespace: " + sym.ns);
+
Var v = ns.findInternedVar(Symbol.create(sym.name));
if(v == null)
throw new Exception("No such var: " + sym);
@@ -3943,11 +3957,12 @@ static public Object resolveIn(Namespace n, Symbol sym) throws Exception{
}
}
+
static public Object maybeResolveIn(Namespace n, Symbol sym) throws Exception{
//note - ns-qualified vars must already exist
if(sym.ns != null)
{
- Namespace ns = Namespace.find(Symbol.create(sym.ns));
+ Namespace ns = namespaceFor(sym);
if(ns == null)
return null;
Var v = ns.findInternedVar(Symbol.create(sym.name));
@@ -3966,14 +3981,14 @@ static public Object maybeResolveIn(Namespace n, Symbol sym) throws Exception{
}
}
+
static Var lookupVar(Symbol sym, boolean internNew) throws Exception{
Var var = null;
//note - ns-qualified vars in other namespaces must already exist
if(sym.ns != null)
{
- Symbol nsSym = Symbol.create(sym.ns);
- Namespace ns = Namespace.find(nsSym);
+ Namespace ns = namespaceFor(sym);
if(ns == null)
return null;
//throw new Exception("No such namespace: " + sym.ns);
diff --git a/src/jvm/clojure/lang/Namespace.java b/src/jvm/clojure/lang/Namespace.java
index ec16c3be..bdbdb85b 100644
--- a/src/jvm/clojure/lang/Namespace.java
+++ b/src/jvm/clojure/lang/Namespace.java
@@ -15,19 +15,21 @@ package clojure.lang;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicReference;
-public class Namespace {
+public class Namespace{
final public Symbol name;
final AtomicReference<IPersistentMap> mappings = new AtomicReference<IPersistentMap>();
+final AtomicReference<IPersistentMap> aliases = new AtomicReference<IPersistentMap>();
final static ConcurrentHashMap<Symbol, Namespace> namespaces = new ConcurrentHashMap<Symbol, Namespace>();
-public String toString() {
+public String toString(){
return "#<Namespace: " + name + ">";
}
Namespace(Symbol name){
this.name = name;
mappings.set(RT.DEFAULT_IMPORTS);
+ aliases.set(RT.map());
}
public static ISeq all(){
@@ -137,4 +139,39 @@ public Var findInternedVar(Symbol symbol){
return null;
}
+
+public IPersistentMap getAliases(){
+ return aliases.get();
+}
+
+public Namespace lookupAlias(Symbol alias){
+ IPersistentMap map = getAliases();
+ return (Namespace) map.valAt(alias);
+}
+
+public void addAlias(Symbol alias, Namespace ns){
+ if (alias == null || ns == null)
+ throw new NullPointerException("Expecting Symbol + Namespace");
+ IPersistentMap map = getAliases();
+ while(!map.containsKey(alias))
+ {
+ IPersistentMap newMap = map.assoc(alias, ns);
+ aliases.compareAndSet(map, newMap);
+ map = getAliases();
+ }
+ // you can rebind an alias, but only to the initially-aliased namespace.
+ if(!map.valAt(alias).equals(ns))
+ throw new IllegalStateException("Alias " + alias + " already exists in namespace "
+ + name + ", aliasing " + map.valAt(alias));
+}
+
+public void removeAlias(Symbol alias) throws Exception{
+ IPersistentMap map = getAliases();
+ while(map.containsKey(alias))
+ {
+ IPersistentMap newMap = map.without(alias);
+ aliases.compareAndSet(map, newMap);
+ map = getAliases();
+ }
}
+} \ No newline at end of file