Mercurial > lasercutter
comparison 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 |
comparison
equal
deleted
inserted
replaced
9:35cf337adfcf | 10:ef7dbbd6452c |
---|---|
1 /** | |
2 * Copyright (c) Rich Hickey. All rights reserved. | |
3 * The use and distribution terms for this software are covered by the | |
4 * 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 by | |
7 * the terms of this license. | |
8 * You must not remove this notice, or any other, from this software. | |
9 **/ | |
10 | |
11 /* rich Jan 23, 2008 */ | |
12 | |
13 package clojure.lang; | |
14 | |
15 import java.io.ObjectStreamException; | |
16 import java.io.Serializable; | |
17 import java.util.concurrent.ConcurrentHashMap; | |
18 import java.util.concurrent.atomic.AtomicReference; | |
19 | |
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>(); | |
24 | |
25 final static ConcurrentHashMap<Symbol, Namespace> namespaces = new ConcurrentHashMap<Symbol, Namespace>(); | |
26 | |
27 public String toString(){ | |
28 return name.toString(); | |
29 } | |
30 | |
31 Namespace(Symbol name){ | |
32 super(name.meta()); | |
33 this.name = name; | |
34 mappings.set(RT.DEFAULT_IMPORTS); | |
35 aliases.set(RT.map()); | |
36 } | |
37 | |
38 public static ISeq all(){ | |
39 return RT.seq(namespaces.values()); | |
40 } | |
41 | |
42 public Symbol getName(){ | |
43 return name; | |
44 } | |
45 | |
46 public IPersistentMap getMappings(){ | |
47 return mappings.get(); | |
48 } | |
49 | |
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; | |
68 | |
69 if(v == null) | |
70 v = new Var(this, sym); | |
71 | |
72 warnOrFailOnReplace(sym, o, v); | |
73 | |
74 | |
75 while(!mappings.compareAndSet(map, map.assoc(sym, v))) | |
76 map = getMappings(); | |
77 | |
78 return v; | |
79 } | |
80 | |
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: " + name | |
91 + ", being replaced by: " + v); | |
92 } | |
93 | |
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; | |
109 | |
110 warnOrFailOnReplace(sym, o, val); | |
111 | |
112 while(!mappings.compareAndSet(map, map.assoc(sym, val))) | |
113 map = getMappings(); | |
114 | |
115 return val; | |
116 | |
117 } | |
118 | |
119 public static boolean areDifferentInstancesOfSameClassName(Class cls1, Class cls2) { | |
120 return (cls1 != cls2) && (cls1.getName().equals(cls2.getName())); | |
121 } | |
122 | |
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; | |
139 | |
140 throw new IllegalStateException(sym + " already refers to: " + c + " in namespace: " + name); | |
141 } | |
142 | |
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 } | |
156 | |
157 public Class importClass(Symbol sym, Class c){ | |
158 return referenceClass(sym, c); | |
159 | |
160 } | |
161 | |
162 public Class importClass(Class c){ | |
163 String n = c.getName(); | |
164 return importClass(Symbol.intern(n.substring(n.lastIndexOf('.') + 1)), c); | |
165 } | |
166 | |
167 public Var refer(Symbol sym, Var var){ | |
168 return (Var) reference(sym, var); | |
169 | |
170 } | |
171 | |
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 } | |
180 | |
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 } | |
186 | |
187 public static Namespace find(Symbol name){ | |
188 return namespaces.get(name); | |
189 } | |
190 | |
191 public Object getMapping(Symbol name){ | |
192 return mappings.get().valAt(name); | |
193 } | |
194 | |
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 } | |
201 | |
202 | |
203 public IPersistentMap getAliases(){ | |
204 return aliases.get(); | |
205 } | |
206 | |
207 public Namespace lookupAlias(Symbol alias){ | |
208 IPersistentMap map = getAliases(); | |
209 return (Namespace) map.valAt(alias); | |
210 } | |
211 | |
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 } | |
227 | |
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 } | |
237 | |
238 private Object readResolve() throws ObjectStreamException { | |
239 // ensures that serialized namespaces are "deserialized" to the | |
240 // namespace in the present runtime | |
241 return findOrCreate(name); | |
242 } | |
243 } |