Mercurial > lasercutter
view src/clojure/lang/Namespace.java @ 10:ef7dbbd6452c
added clojure source goodness
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Sat, 21 Aug 2010 06:25:44 -0400 |
parents | |
children |
line wrap: on
line source
1 /**2 * Copyright (c) Rich Hickey. All rights reserved.3 * The use and distribution terms for this software are covered by the4 * Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)5 * which can be found in the file epl-v10.html at the root of this distribution.6 * By using this software in any fashion, you are agreeing to be bound by7 * the terms of this license.8 * You must not remove this notice, or any other, from this software.9 **/11 /* rich Jan 23, 2008 */13 package clojure.lang;15 import java.io.ObjectStreamException;16 import java.io.Serializable;17 import java.util.concurrent.ConcurrentHashMap;18 import java.util.concurrent.atomic.AtomicReference;20 public class Namespace extends AReference implements Serializable {21 final public Symbol name;22 transient final AtomicReference<IPersistentMap> mappings = new AtomicReference<IPersistentMap>();23 transient final AtomicReference<IPersistentMap> aliases = new AtomicReference<IPersistentMap>();25 final static ConcurrentHashMap<Symbol, Namespace> namespaces = new ConcurrentHashMap<Symbol, Namespace>();27 public String toString(){28 return name.toString();29 }31 Namespace(Symbol name){32 super(name.meta());33 this.name = name;34 mappings.set(RT.DEFAULT_IMPORTS);35 aliases.set(RT.map());36 }38 public static ISeq all(){39 return RT.seq(namespaces.values());40 }42 public Symbol getName(){43 return name;44 }46 public IPersistentMap getMappings(){47 return mappings.get();48 }50 public Var intern(Symbol sym){51 if(sym.ns != null)52 {53 throw new IllegalArgumentException("Can't intern namespace-qualified symbol");54 }55 IPersistentMap map = getMappings();56 Object o;57 Var v = null;58 while((o = map.valAt(sym)) == null)59 {60 if(v == null)61 v = new Var(this, sym);62 IPersistentMap newMap = map.assoc(sym, v);63 mappings.compareAndSet(map, newMap);64 map = getMappings();65 }66 if(o instanceof Var && ((Var) o).ns == this)67 return (Var) o;69 if(v == null)70 v = new Var(this, sym);72 warnOrFailOnReplace(sym, o, v);75 while(!mappings.compareAndSet(map, map.assoc(sym, v)))76 map = getMappings();78 return v;79 }81 private void warnOrFailOnReplace(Symbol sym, Object o, Object v){82 if (o instanceof Var)83 {84 Namespace ns = ((Var)o).ns;85 if (ns == this)86 return;87 if (ns != RT.CLOJURE_NS)88 throw new IllegalStateException(sym + " already refers to: " + o + " in namespace: " + name);89 }90 RT.errPrintWriter().println("WARNING: " + sym + " already refers to: " + o + " in namespace: " + name91 + ", being replaced by: " + v);92 }94 Object reference(Symbol sym, Object val){95 if(sym.ns != null)96 {97 throw new IllegalArgumentException("Can't intern namespace-qualified symbol");98 }99 IPersistentMap map = getMappings();100 Object o;101 while((o = map.valAt(sym)) == null)102 {103 IPersistentMap newMap = map.assoc(sym, val);104 mappings.compareAndSet(map, newMap);105 map = getMappings();106 }107 if(o == val)108 return o;110 warnOrFailOnReplace(sym, o, val);112 while(!mappings.compareAndSet(map, map.assoc(sym, val)))113 map = getMappings();115 return val;117 }119 public static boolean areDifferentInstancesOfSameClassName(Class cls1, Class cls2) {120 return (cls1 != cls2) && (cls1.getName().equals(cls2.getName()));121 }123 Class referenceClass(Symbol sym, Class val){124 if(sym.ns != null)125 {126 throw new IllegalArgumentException("Can't intern namespace-qualified symbol");127 }128 IPersistentMap map = getMappings();129 Class c = (Class) map.valAt(sym);130 while((c == null) || (areDifferentInstancesOfSameClassName(c, val)))131 {132 IPersistentMap newMap = map.assoc(sym, val);133 mappings.compareAndSet(map, newMap);134 map = getMappings();135 c = (Class) map.valAt(sym);136 }137 if(c == val)138 return c;140 throw new IllegalStateException(sym + " already refers to: " + c + " in namespace: " + name);141 }143 public void unmap(Symbol sym) throws Exception{144 if(sym.ns != null)145 {146 throw new IllegalArgumentException("Can't unintern namespace-qualified symbol");147 }148 IPersistentMap map = getMappings();149 while(map.containsKey(sym))150 {151 IPersistentMap newMap = map.without(sym);152 mappings.compareAndSet(map, newMap);153 map = getMappings();154 }155 }157 public Class importClass(Symbol sym, Class c){158 return referenceClass(sym, c);160 }162 public Class importClass(Class c){163 String n = c.getName();164 return importClass(Symbol.intern(n.substring(n.lastIndexOf('.') + 1)), c);165 }167 public Var refer(Symbol sym, Var var){168 return (Var) reference(sym, var);170 }172 public static Namespace findOrCreate(Symbol name){173 Namespace ns = namespaces.get(name);174 if(ns != null)175 return ns;176 Namespace newns = new Namespace(name);177 ns = namespaces.putIfAbsent(name, newns);178 return ns == null ? newns : ns;179 }181 public static Namespace remove(Symbol name){182 if(name.equals(RT.CLOJURE_NS.name))183 throw new IllegalArgumentException("Cannot remove clojure namespace");184 return namespaces.remove(name);185 }187 public static Namespace find(Symbol name){188 return namespaces.get(name);189 }191 public Object getMapping(Symbol name){192 return mappings.get().valAt(name);193 }195 public Var findInternedVar(Symbol symbol){196 Object o = mappings.get().valAt(symbol);197 if(o != null && o instanceof Var && ((Var) o).ns == this)198 return (Var) o;199 return null;200 }203 public IPersistentMap getAliases(){204 return aliases.get();205 }207 public Namespace lookupAlias(Symbol alias){208 IPersistentMap map = getAliases();209 return (Namespace) map.valAt(alias);210 }212 public void addAlias(Symbol alias, Namespace ns){213 if (alias == null || ns == null)214 throw new NullPointerException("Expecting Symbol + Namespace");215 IPersistentMap map = getAliases();216 while(!map.containsKey(alias))217 {218 IPersistentMap newMap = map.assoc(alias, ns);219 aliases.compareAndSet(map, newMap);220 map = getAliases();221 }222 // you can rebind an alias, but only to the initially-aliased namespace.223 if(!map.valAt(alias).equals(ns))224 throw new IllegalStateException("Alias " + alias + " already exists in namespace "225 + name + ", aliasing " + map.valAt(alias));226 }228 public void removeAlias(Symbol alias) throws Exception{229 IPersistentMap map = getAliases();230 while(map.containsKey(alias))231 {232 IPersistentMap newMap = map.without(alias);233 aliases.compareAndSet(map, newMap);234 map = getAliases();235 }236 }238 private Object readResolve() throws ObjectStreamException {239 // ensures that serialized namespaces are "deserialized" to the240 // namespace in the present runtime241 return findOrCreate(name);242 }243 }