Mercurial > lasercutter
diff src/clojure/lang/Var.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 diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/src/clojure/lang/Var.java Sat Aug 21 06:25:44 2010 -0400 1.3 @@ -0,0 +1,497 @@ 1.4 +/** 1.5 + * Copyright (c) Rich Hickey. All rights reserved. 1.6 + * The use and distribution terms for this software are covered by the 1.7 + * Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) 1.8 + * which can be found in the file epl-v10.html at the root of this distribution. 1.9 + * By using this software in any fashion, you are agreeing to be bound by 1.10 + * the terms of this license. 1.11 + * You must not remove this notice, or any other, from this software. 1.12 + **/ 1.13 + 1.14 +/* rich Jul 31, 2007 */ 1.15 + 1.16 +package clojure.lang; 1.17 + 1.18 +import java.util.concurrent.atomic.AtomicInteger; 1.19 + 1.20 + 1.21 +public final class Var extends ARef implements IFn, IRef, Settable{ 1.22 + 1.23 + 1.24 +static class Frame{ 1.25 + //Var->Box 1.26 + Associative bindings; 1.27 + //Var->val 1.28 + Associative frameBindings; 1.29 + Frame prev; 1.30 + 1.31 + 1.32 + public Frame(){ 1.33 + this(PersistentHashMap.EMPTY, PersistentHashMap.EMPTY, null); 1.34 + } 1.35 + 1.36 + public Frame(Associative frameBindings, Associative bindings, Frame prev){ 1.37 + this.frameBindings = frameBindings; 1.38 + this.bindings = bindings; 1.39 + this.prev = prev; 1.40 + } 1.41 +} 1.42 + 1.43 +static ThreadLocal<Frame> dvals = new ThreadLocal<Frame>(){ 1.44 + 1.45 + protected Frame initialValue(){ 1.46 + return new Frame(); 1.47 + } 1.48 +}; 1.49 + 1.50 +static Keyword privateKey = Keyword.intern(null, "private"); 1.51 +static IPersistentMap privateMeta = new PersistentArrayMap(new Object[]{privateKey, Boolean.TRUE}); 1.52 +static Keyword macroKey = Keyword.intern(null, "macro"); 1.53 +static Keyword nameKey = Keyword.intern(null, "name"); 1.54 +static Keyword nsKey = Keyword.intern(null, "ns"); 1.55 +//static Keyword tagKey = Keyword.intern(null, "tag"); 1.56 + 1.57 +volatile Object root; 1.58 +transient final AtomicInteger count; 1.59 +public final Symbol sym; 1.60 +public final Namespace ns; 1.61 + 1.62 +//IPersistentMap _meta; 1.63 + 1.64 +public static Var intern(Namespace ns, Symbol sym, Object root){ 1.65 + return intern(ns, sym, root, true); 1.66 +} 1.67 + 1.68 +public static Var intern(Namespace ns, Symbol sym, Object root, boolean replaceRoot){ 1.69 + Var dvout = ns.intern(sym); 1.70 + if(!dvout.hasRoot() || replaceRoot) 1.71 + dvout.bindRoot(root); 1.72 + return dvout; 1.73 +} 1.74 + 1.75 + 1.76 +public String toString(){ 1.77 + if(ns != null) 1.78 + return "#'" + ns.name + "/" + sym; 1.79 + return "#<Var: " + (sym != null ? sym.toString() : "--unnamed--") + ">"; 1.80 +} 1.81 + 1.82 +public static Var find(Symbol nsQualifiedSym){ 1.83 + if(nsQualifiedSym.ns == null) 1.84 + throw new IllegalArgumentException("Symbol must be namespace-qualified"); 1.85 + Namespace ns = Namespace.find(Symbol.create(nsQualifiedSym.ns)); 1.86 + if(ns == null) 1.87 + throw new IllegalArgumentException("No such namespace: " + nsQualifiedSym.ns); 1.88 + return ns.findInternedVar(Symbol.create(nsQualifiedSym.name)); 1.89 +} 1.90 + 1.91 +public static Var intern(Symbol nsName, Symbol sym){ 1.92 + Namespace ns = Namespace.findOrCreate(nsName); 1.93 + return intern(ns, sym); 1.94 +} 1.95 + 1.96 +public static Var internPrivate(String nsName, String sym){ 1.97 + Namespace ns = Namespace.findOrCreate(Symbol.intern(nsName)); 1.98 + Var ret = intern(ns, Symbol.intern(sym)); 1.99 + ret.setMeta(privateMeta); 1.100 + return ret; 1.101 +} 1.102 + 1.103 +public static Var intern(Namespace ns, Symbol sym){ 1.104 + return ns.intern(sym); 1.105 +} 1.106 + 1.107 + 1.108 +public static Var create(){ 1.109 + return new Var(null, null); 1.110 +} 1.111 + 1.112 +public static Var create(Object root){ 1.113 + return new Var(null, null, root); 1.114 +} 1.115 + 1.116 +Var(Namespace ns, Symbol sym){ 1.117 + this.ns = ns; 1.118 + this.sym = sym; 1.119 + this.count = new AtomicInteger(); 1.120 + this.root = dvals; //use dvals as magic not-bound value 1.121 + setMeta(PersistentHashMap.EMPTY); 1.122 +} 1.123 + 1.124 +Var(Namespace ns, Symbol sym, Object root){ 1.125 + this(ns, sym); 1.126 + this.root = root; 1.127 +} 1.128 + 1.129 +public boolean isBound(){ 1.130 + return hasRoot() || (count.get() > 0 && dvals.get().bindings.containsKey(this)); 1.131 +} 1.132 + 1.133 +final public Object get(){ 1.134 + if(count.get() == 0 && root != dvals) 1.135 + return root; 1.136 + return deref(); 1.137 +} 1.138 + 1.139 +final public Object deref(){ 1.140 + Box b = getThreadBinding(); 1.141 + if(b != null) 1.142 + return b.val; 1.143 + if(hasRoot()) 1.144 + return root; 1.145 + throw new IllegalStateException(String.format("Var %s/%s is unbound.", ns, sym)); 1.146 +} 1.147 + 1.148 +public void setValidator(IFn vf){ 1.149 + if(hasRoot()) 1.150 + validate(vf, getRoot()); 1.151 + validator = vf; 1.152 +} 1.153 + 1.154 +public Object alter(IFn fn, ISeq args) throws Exception{ 1.155 + set(fn.applyTo(RT.cons(deref(), args))); 1.156 + return this; 1.157 +} 1.158 + 1.159 +public Object set(Object val){ 1.160 + validate(getValidator(), val); 1.161 + Box b = getThreadBinding(); 1.162 + if(b != null) 1.163 + return (b.val = val); 1.164 + //jury still out on this 1.165 +// if(hasRoot()) 1.166 +// { 1.167 +// bindRoot(val); 1.168 +// return val; 1.169 +// } 1.170 + throw new IllegalStateException(String.format("Can't change/establish root binding of: %s with set", sym)); 1.171 +} 1.172 + 1.173 +public Object doSet(Object val) throws Exception { 1.174 + return set(val); 1.175 + } 1.176 + 1.177 +public Object doReset(Object val) throws Exception { 1.178 + bindRoot(val); 1.179 + return val; 1.180 + } 1.181 + 1.182 +public void setMeta(IPersistentMap m) { 1.183 + //ensure these basis keys 1.184 + resetMeta(m.assoc(nameKey, sym).assoc(nsKey, ns)); 1.185 +} 1.186 + 1.187 +public void setMacro() { 1.188 + try 1.189 + { 1.190 + alterMeta(assoc, RT.list(macroKey, RT.T)); 1.191 + } 1.192 + catch (Exception e) 1.193 + { 1.194 + throw new RuntimeException(e); 1.195 + } 1.196 +} 1.197 + 1.198 +public boolean isMacro(){ 1.199 + return RT.booleanCast(meta().valAt(macroKey)); 1.200 +} 1.201 + 1.202 +//public void setExported(boolean state){ 1.203 +// _meta = _meta.assoc(privateKey, state); 1.204 +//} 1.205 + 1.206 +public boolean isPublic(){ 1.207 + return !RT.booleanCast(meta().valAt(privateKey)); 1.208 +} 1.209 + 1.210 +public Object getRoot(){ 1.211 + if(hasRoot()) 1.212 + return root; 1.213 + throw new IllegalStateException(String.format("Var %s/%s is unbound.", ns, sym)); 1.214 +} 1.215 + 1.216 +public Object getRawRoot(){ 1.217 + return root; 1.218 +} 1.219 + 1.220 +public Object getTag(){ 1.221 + return meta().valAt(RT.TAG_KEY); 1.222 +} 1.223 + 1.224 +public void setTag(Symbol tag) { 1.225 + try 1.226 + { 1.227 + alterMeta(assoc, RT.list(RT.TAG_KEY, tag)); 1.228 + } 1.229 + catch (Exception e) 1.230 + { 1.231 + throw new RuntimeException(e); 1.232 + } 1.233 +} 1.234 + 1.235 +final public boolean hasRoot(){ 1.236 + return root != dvals; 1.237 +} 1.238 + 1.239 +//binding root always clears macro flag 1.240 +synchronized public void bindRoot(Object root){ 1.241 + validate(getValidator(), root); 1.242 + Object oldroot = hasRoot()?this.root:null; 1.243 + this.root = root; 1.244 + try 1.245 + { 1.246 + alterMeta(dissoc, RT.list(macroKey)); 1.247 + } 1.248 + catch (Exception e) 1.249 + { 1.250 + throw new RuntimeException(e); 1.251 + } 1.252 + notifyWatches(oldroot,this.root); 1.253 +} 1.254 + 1.255 +synchronized void swapRoot(Object root){ 1.256 + validate(getValidator(), root); 1.257 + Object oldroot = hasRoot()?this.root:null; 1.258 + this.root = root; 1.259 + notifyWatches(oldroot,root); 1.260 +} 1.261 + 1.262 +synchronized public void unbindRoot(){ 1.263 + this.root = dvals; 1.264 +} 1.265 + 1.266 +synchronized public void commuteRoot(IFn fn) throws Exception{ 1.267 + Object newRoot = fn.invoke(root); 1.268 + validate(getValidator(), newRoot); 1.269 + Object oldroot = getRoot(); 1.270 + this.root = newRoot; 1.271 + notifyWatches(oldroot,newRoot); 1.272 +} 1.273 + 1.274 +synchronized public Object alterRoot(IFn fn, ISeq args) throws Exception{ 1.275 + Object newRoot = fn.applyTo(RT.cons(root, args)); 1.276 + validate(getValidator(), newRoot); 1.277 + Object oldroot = getRoot(); 1.278 + this.root = newRoot; 1.279 + notifyWatches(oldroot,newRoot); 1.280 + return newRoot; 1.281 +} 1.282 + 1.283 +public static void pushThreadBindings(Associative bindings){ 1.284 + Frame f = dvals.get(); 1.285 + Associative bmap = f.bindings; 1.286 + for(ISeq bs = bindings.seq(); bs != null; bs = bs.next()) 1.287 + { 1.288 + IMapEntry e = (IMapEntry) bs.first(); 1.289 + Var v = (Var) e.key(); 1.290 + v.validate(v.getValidator(), e.val()); 1.291 + v.count.incrementAndGet(); 1.292 + bmap = bmap.assoc(v, new Box(e.val())); 1.293 + } 1.294 + dvals.set(new Frame(bindings, bmap, f)); 1.295 +} 1.296 + 1.297 +public static void popThreadBindings(){ 1.298 + Frame f = dvals.get(); 1.299 + if(f.prev == null) 1.300 + throw new IllegalStateException("Pop without matching push"); 1.301 + for(ISeq bs = RT.keys(f.frameBindings); bs != null; bs = bs.next()) 1.302 + { 1.303 + Var v = (Var) bs.first(); 1.304 + v.count.decrementAndGet(); 1.305 + } 1.306 + dvals.set(f.prev); 1.307 +} 1.308 + 1.309 +public static void releaseThreadBindings(){ 1.310 + Frame f = dvals.get(); 1.311 + if(f.prev == null) 1.312 + throw new IllegalStateException("Release without full unwind"); 1.313 + for(ISeq bs = RT.keys(f.bindings); bs != null; bs = bs.next()) 1.314 + { 1.315 + Var v = (Var) bs.first(); 1.316 + v.count.decrementAndGet(); 1.317 + } 1.318 + dvals.set(null); 1.319 +} 1.320 + 1.321 +public static Associative getThreadBindings(){ 1.322 + Frame f = dvals.get(); 1.323 + IPersistentMap ret = PersistentHashMap.EMPTY; 1.324 + for(ISeq bs = f.bindings.seq(); bs != null; bs = bs.next()) 1.325 + { 1.326 + IMapEntry e = (IMapEntry) bs.first(); 1.327 + Var v = (Var) e.key(); 1.328 + Box b = (Box) e.val(); 1.329 + ret = ret.assoc(v, b.val); 1.330 + } 1.331 + return ret; 1.332 +} 1.333 + 1.334 +public final Box getThreadBinding(){ 1.335 + if(count.get() > 0) 1.336 + { 1.337 + IMapEntry e = dvals.get().bindings.entryAt(this); 1.338 + if(e != null) 1.339 + return (Box) e.val(); 1.340 + } 1.341 + return null; 1.342 +} 1.343 + 1.344 +final public IFn fn(){ 1.345 + return (IFn) deref(); 1.346 +} 1.347 + 1.348 +public Object call() throws Exception{ 1.349 + return invoke(); 1.350 +} 1.351 + 1.352 +public void run(){ 1.353 + try 1.354 + { 1.355 + invoke(); 1.356 + } 1.357 + catch(Exception e) 1.358 + { 1.359 + throw new RuntimeException(e); 1.360 + } 1.361 +} 1.362 + 1.363 +public Object invoke() throws Exception{ 1.364 + return fn().invoke(); 1.365 +} 1.366 + 1.367 +public Object invoke(Object arg1) throws Exception{ 1.368 + return fn().invoke(arg1); 1.369 +} 1.370 + 1.371 +public Object invoke(Object arg1, Object arg2) throws Exception{ 1.372 + return fn().invoke(arg1, arg2); 1.373 +} 1.374 + 1.375 +public Object invoke(Object arg1, Object arg2, Object arg3) throws Exception{ 1.376 + return fn().invoke(arg1, arg2, arg3); 1.377 +} 1.378 + 1.379 +public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4) throws Exception{ 1.380 + return fn().invoke(arg1, arg2, arg3, arg4); 1.381 +} 1.382 + 1.383 +public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5) throws Exception{ 1.384 + return fn().invoke(arg1, arg2, arg3, arg4, arg5); 1.385 +} 1.386 + 1.387 +public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6) throws Exception{ 1.388 + return fn().invoke(arg1, arg2, arg3, arg4, arg5, arg6); 1.389 +} 1.390 + 1.391 +public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7) 1.392 + throws Exception{ 1.393 + return fn().invoke(arg1, arg2, arg3, arg4, arg5, arg6, arg7); 1.394 +} 1.395 + 1.396 +public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, 1.397 + Object arg8) throws Exception{ 1.398 + return fn().invoke(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); 1.399 +} 1.400 + 1.401 +public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, 1.402 + Object arg8, Object arg9) throws Exception{ 1.403 + return fn().invoke(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9); 1.404 +} 1.405 + 1.406 +public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, 1.407 + Object arg8, Object arg9, Object arg10) throws Exception{ 1.408 + return fn().invoke(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10); 1.409 +} 1.410 + 1.411 +public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, 1.412 + Object arg8, Object arg9, Object arg10, Object arg11) throws Exception{ 1.413 + return fn().invoke(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11); 1.414 +} 1.415 + 1.416 +public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, 1.417 + Object arg8, Object arg9, Object arg10, Object arg11, Object arg12) throws Exception{ 1.418 + return fn().invoke(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12); 1.419 +} 1.420 + 1.421 +public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, 1.422 + Object arg8, Object arg9, Object arg10, Object arg11, Object arg12, Object arg13) 1.423 + throws Exception{ 1.424 + return fn().invoke(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13); 1.425 +} 1.426 + 1.427 +public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, 1.428 + Object arg8, Object arg9, Object arg10, Object arg11, Object arg12, Object arg13, Object arg14) 1.429 + throws Exception{ 1.430 + return fn().invoke(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14); 1.431 +} 1.432 + 1.433 +public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, 1.434 + Object arg8, Object arg9, Object arg10, Object arg11, Object arg12, Object arg13, Object arg14, 1.435 + Object arg15) throws Exception{ 1.436 + return fn().invoke(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15); 1.437 +} 1.438 + 1.439 +public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, 1.440 + Object arg8, Object arg9, Object arg10, Object arg11, Object arg12, Object arg13, Object arg14, 1.441 + Object arg15, Object arg16) throws Exception{ 1.442 + return fn().invoke(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, 1.443 + arg16); 1.444 +} 1.445 + 1.446 +public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, 1.447 + Object arg8, Object arg9, Object arg10, Object arg11, Object arg12, Object arg13, Object arg14, 1.448 + Object arg15, Object arg16, Object arg17) throws Exception{ 1.449 + return fn().invoke(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, 1.450 + arg16, arg17); 1.451 +} 1.452 + 1.453 +public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, 1.454 + Object arg8, Object arg9, Object arg10, Object arg11, Object arg12, Object arg13, Object arg14, 1.455 + Object arg15, Object arg16, Object arg17, Object arg18) throws Exception{ 1.456 + return fn().invoke(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, 1.457 + arg16, arg17, arg18); 1.458 +} 1.459 + 1.460 +public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, 1.461 + Object arg8, Object arg9, Object arg10, Object arg11, Object arg12, Object arg13, Object arg14, 1.462 + Object arg15, Object arg16, Object arg17, Object arg18, Object arg19) throws Exception{ 1.463 + return fn().invoke(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, 1.464 + arg16, arg17, arg18, arg19); 1.465 +} 1.466 + 1.467 +public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, 1.468 + Object arg8, Object arg9, Object arg10, Object arg11, Object arg12, Object arg13, Object arg14, 1.469 + Object arg15, Object arg16, Object arg17, Object arg18, Object arg19, Object arg20) 1.470 + throws Exception{ 1.471 + return fn().invoke(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, 1.472 + arg16, arg17, arg18, arg19, arg20); 1.473 +} 1.474 + 1.475 +public Object invoke(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, Object arg6, Object arg7, 1.476 + Object arg8, Object arg9, Object arg10, Object arg11, Object arg12, Object arg13, Object arg14, 1.477 + Object arg15, Object arg16, Object arg17, Object arg18, Object arg19, Object arg20, 1.478 + Object... args) 1.479 + throws Exception{ 1.480 + return fn().invoke(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14, arg15, 1.481 + arg16, arg17, arg18, arg19, arg20, args); 1.482 +} 1.483 + 1.484 +public Object applyTo(ISeq arglist) throws Exception{ 1.485 + return AFn.applyToHelper(this, arglist); 1.486 +} 1.487 + 1.488 +static IFn assoc = new AFn(){ 1.489 + @Override 1.490 + public Object invoke(Object m, Object k, Object v) throws Exception { 1.491 + return RT.assoc(m, k, v); 1.492 + } 1.493 +}; 1.494 +static IFn dissoc = new AFn() { 1.495 + @Override 1.496 + public Object invoke(Object c, Object k) throws Exception { 1.497 + return RT.dissoc(c, k); 1.498 + } 1.499 +}; 1.500 +}