comparison src/clojure/lang/RT.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 Mar 25, 2006 4:28:27 PM */
12
13 package clojure.lang;
14
15 import java.util.concurrent.atomic.AtomicInteger;
16 import java.util.concurrent.Callable;
17 import java.util.*;
18 import java.util.regex.Matcher;
19 import java.util.regex.Pattern;
20 import java.io.*;
21 import java.lang.reflect.Array;
22 import java.math.BigDecimal;
23 import java.math.BigInteger;
24 import java.security.AccessController;
25 import java.security.PrivilegedAction;
26 import java.net.URL;
27 import java.net.JarURLConnection;
28 import java.nio.charset.Charset;
29
30 public class RT{
31
32 static final public Boolean T = Boolean.TRUE;//Keyword.intern(Symbol.create(null, "t"));
33 static final public Boolean F = Boolean.FALSE;//Keyword.intern(Symbol.create(null, "t"));
34 static final public String LOADER_SUFFIX = "__init";
35
36 //simple-symbol->class
37 final static IPersistentMap DEFAULT_IMPORTS = map(
38 // Symbol.create("RT"), "clojure.lang.RT",
39 // Symbol.create("Num"), "clojure.lang.Num",
40 // Symbol.create("Symbol"), "clojure.lang.Symbol",
41 // Symbol.create("Keyword"), "clojure.lang.Keyword",
42 // Symbol.create("Var"), "clojure.lang.Var",
43 // Symbol.create("Ref"), "clojure.lang.Ref",
44 // Symbol.create("IFn"), "clojure.lang.IFn",
45 // Symbol.create("IObj"), "clojure.lang.IObj",
46 // Symbol.create("ISeq"), "clojure.lang.ISeq",
47 // Symbol.create("IPersistentCollection"),
48 // "clojure.lang.IPersistentCollection",
49 // Symbol.create("IPersistentMap"), "clojure.lang.IPersistentMap",
50 // Symbol.create("IPersistentList"), "clojure.lang.IPersistentList",
51 // Symbol.create("IPersistentVector"), "clojure.lang.IPersistentVector",
52 Symbol.create("Boolean"), Boolean.class,
53 Symbol.create("Byte"), Byte.class,
54 Symbol.create("Character"), Character.class,
55 Symbol.create("Class"), Class.class,
56 Symbol.create("ClassLoader"), ClassLoader.class,
57 Symbol.create("Compiler"), Compiler.class,
58 Symbol.create("Double"), Double.class,
59 Symbol.create("Enum"), Enum.class,
60 Symbol.create("Float"), Float.class,
61 Symbol.create("InheritableThreadLocal"), InheritableThreadLocal.class,
62 Symbol.create("Integer"), Integer.class,
63 Symbol.create("Long"), Long.class,
64 Symbol.create("Math"), Math.class,
65 Symbol.create("Number"), Number.class,
66 Symbol.create("Object"), Object.class,
67 Symbol.create("Package"), Package.class,
68 Symbol.create("Process"), Process.class,
69 Symbol.create("ProcessBuilder"), ProcessBuilder.class,
70 Symbol.create("Runtime"), Runtime.class,
71 Symbol.create("RuntimePermission"), RuntimePermission.class,
72 Symbol.create("SecurityManager"), SecurityManager.class,
73 Symbol.create("Short"), Short.class,
74 Symbol.create("StackTraceElement"), StackTraceElement.class,
75 Symbol.create("StrictMath"), StrictMath.class,
76 Symbol.create("String"), String.class,
77 Symbol.create("StringBuffer"), StringBuffer.class,
78 Symbol.create("StringBuilder"), StringBuilder.class,
79 Symbol.create("System"), System.class,
80 Symbol.create("Thread"), Thread.class,
81 Symbol.create("ThreadGroup"), ThreadGroup.class,
82 Symbol.create("ThreadLocal"), ThreadLocal.class,
83 Symbol.create("Throwable"), Throwable.class,
84 Symbol.create("Void"), Void.class,
85 Symbol.create("Appendable"), Appendable.class,
86 Symbol.create("CharSequence"), CharSequence.class,
87 Symbol.create("Cloneable"), Cloneable.class,
88 Symbol.create("Comparable"), Comparable.class,
89 Symbol.create("Iterable"), Iterable.class,
90 Symbol.create("Readable"), Readable.class,
91 Symbol.create("Runnable"), Runnable.class,
92 Symbol.create("Callable"), Callable.class,
93 Symbol.create("BigInteger"), BigInteger.class,
94 Symbol.create("BigDecimal"), BigDecimal.class,
95 Symbol.create("ArithmeticException"), ArithmeticException.class,
96 Symbol.create("ArrayIndexOutOfBoundsException"), ArrayIndexOutOfBoundsException.class,
97 Symbol.create("ArrayStoreException"), ArrayStoreException.class,
98 Symbol.create("ClassCastException"), ClassCastException.class,
99 Symbol.create("ClassNotFoundException"), ClassNotFoundException.class,
100 Symbol.create("CloneNotSupportedException"), CloneNotSupportedException.class,
101 Symbol.create("EnumConstantNotPresentException"), EnumConstantNotPresentException.class,
102 Symbol.create("Exception"), Exception.class,
103 Symbol.create("IllegalAccessException"), IllegalAccessException.class,
104 Symbol.create("IllegalArgumentException"), IllegalArgumentException.class,
105 Symbol.create("IllegalMonitorStateException"), IllegalMonitorStateException.class,
106 Symbol.create("IllegalStateException"), IllegalStateException.class,
107 Symbol.create("IllegalThreadStateException"), IllegalThreadStateException.class,
108 Symbol.create("IndexOutOfBoundsException"), IndexOutOfBoundsException.class,
109 Symbol.create("InstantiationException"), InstantiationException.class,
110 Symbol.create("InterruptedException"), InterruptedException.class,
111 Symbol.create("NegativeArraySizeException"), NegativeArraySizeException.class,
112 Symbol.create("NoSuchFieldException"), NoSuchFieldException.class,
113 Symbol.create("NoSuchMethodException"), NoSuchMethodException.class,
114 Symbol.create("NullPointerException"), NullPointerException.class,
115 Symbol.create("NumberFormatException"), NumberFormatException.class,
116 Symbol.create("RuntimeException"), RuntimeException.class,
117 Symbol.create("SecurityException"), SecurityException.class,
118 Symbol.create("StringIndexOutOfBoundsException"), StringIndexOutOfBoundsException.class,
119 Symbol.create("TypeNotPresentException"), TypeNotPresentException.class,
120 Symbol.create("UnsupportedOperationException"), UnsupportedOperationException.class,
121 Symbol.create("AbstractMethodError"), AbstractMethodError.class,
122 Symbol.create("AssertionError"), AssertionError.class,
123 Symbol.create("ClassCircularityError"), ClassCircularityError.class,
124 Symbol.create("ClassFormatError"), ClassFormatError.class,
125 Symbol.create("Error"), Error.class,
126 Symbol.create("ExceptionInInitializerError"), ExceptionInInitializerError.class,
127 Symbol.create("IllegalAccessError"), IllegalAccessError.class,
128 Symbol.create("IncompatibleClassChangeError"), IncompatibleClassChangeError.class,
129 Symbol.create("InstantiationError"), InstantiationError.class,
130 Symbol.create("InternalError"), InternalError.class,
131 Symbol.create("LinkageError"), LinkageError.class,
132 Symbol.create("NoClassDefFoundError"), NoClassDefFoundError.class,
133 Symbol.create("NoSuchFieldError"), NoSuchFieldError.class,
134 Symbol.create("NoSuchMethodError"), NoSuchMethodError.class,
135 Symbol.create("OutOfMemoryError"), OutOfMemoryError.class,
136 Symbol.create("StackOverflowError"), StackOverflowError.class,
137 Symbol.create("ThreadDeath"), ThreadDeath.class,
138 Symbol.create("UnknownError"), UnknownError.class,
139 Symbol.create("UnsatisfiedLinkError"), UnsatisfiedLinkError.class,
140 Symbol.create("UnsupportedClassVersionError"), UnsupportedClassVersionError.class,
141 Symbol.create("VerifyError"), VerifyError.class,
142 Symbol.create("VirtualMachineError"), VirtualMachineError.class,
143 Symbol.create("Thread$UncaughtExceptionHandler"), Thread.UncaughtExceptionHandler.class,
144 Symbol.create("Thread$State"), Thread.State.class,
145 Symbol.create("Deprecated"), Deprecated.class,
146 Symbol.create("Override"), Override.class,
147 Symbol.create("SuppressWarnings"), SuppressWarnings.class
148
149 // Symbol.create("Collection"), "java.util.Collection",
150 // Symbol.create("Comparator"), "java.util.Comparator",
151 // Symbol.create("Enumeration"), "java.util.Enumeration",
152 // Symbol.create("EventListener"), "java.util.EventListener",
153 // Symbol.create("Formattable"), "java.util.Formattable",
154 // Symbol.create("Iterator"), "java.util.Iterator",
155 // Symbol.create("List"), "java.util.List",
156 // Symbol.create("ListIterator"), "java.util.ListIterator",
157 // Symbol.create("Map"), "java.util.Map",
158 // Symbol.create("Map$Entry"), "java.util.Map$Entry",
159 // Symbol.create("Observer"), "java.util.Observer",
160 // Symbol.create("Queue"), "java.util.Queue",
161 // Symbol.create("RandomAccess"), "java.util.RandomAccess",
162 // Symbol.create("Set"), "java.util.Set",
163 // Symbol.create("SortedMap"), "java.util.SortedMap",
164 // Symbol.create("SortedSet"), "java.util.SortedSet"
165 );
166
167 // single instance of UTF-8 Charset, so as to avoid catching UnsupportedCharsetExceptions everywhere
168 static public Charset UTF8 = Charset.forName("UTF-8");
169
170 static public final Namespace CLOJURE_NS = Namespace.findOrCreate(Symbol.create("clojure.core"));
171 //static final Namespace USER_NS = Namespace.findOrCreate(Symbol.create("user"));
172 final static public Var OUT =
173 Var.intern(CLOJURE_NS, Symbol.create("*out*"), new OutputStreamWriter(System.out));
174 final static public Var IN =
175 Var.intern(CLOJURE_NS, Symbol.create("*in*"),
176 new LineNumberingPushbackReader(new InputStreamReader(System.in)));
177 final static public Var ERR =
178 Var.intern(CLOJURE_NS, Symbol.create("*err*"),
179 new PrintWriter(new OutputStreamWriter(System.err), true));
180 final static Keyword TAG_KEY = Keyword.intern(null, "tag");
181 final static public Var AGENT = Var.intern(CLOJURE_NS, Symbol.create("*agent*"), null);
182 final static public Var READEVAL = Var.intern(CLOJURE_NS, Symbol.create("*read-eval*"), T);
183 final static public Var ASSERT = Var.intern(CLOJURE_NS, Symbol.create("*assert*"), T);
184 final static public Var MATH_CONTEXT = Var.intern(CLOJURE_NS, Symbol.create("*math-context*"), null);
185 static Keyword LINE_KEY = Keyword.intern(null, "line");
186 static Keyword FILE_KEY = Keyword.intern(null, "file");
187 static Keyword DECLARED_KEY = Keyword.intern(null, "declared");
188 final static public Var USE_CONTEXT_CLASSLOADER =
189 Var.intern(CLOJURE_NS, Symbol.create("*use-context-classloader*"), T);
190 //final static public Var CURRENT_MODULE = Var.intern(Symbol.create("clojure.core", "current-module"),
191 // Module.findOrCreateModule("clojure/user"));
192
193 final static Symbol LOAD_FILE = Symbol.create("load-file");
194 final static Symbol IN_NAMESPACE = Symbol.create("in-ns");
195 final static Symbol NAMESPACE = Symbol.create("ns");
196 static final Symbol IDENTICAL = Symbol.create("identical?");
197 final static Var CMD_LINE_ARGS = Var.intern(CLOJURE_NS, Symbol.create("*command-line-args*"), null);
198 //symbol
199 final public static Var CURRENT_NS = Var.intern(CLOJURE_NS, Symbol.create("*ns*"),
200 CLOJURE_NS);
201
202 final static Var FLUSH_ON_NEWLINE = Var.intern(CLOJURE_NS, Symbol.create("*flush-on-newline*"), T);
203 final static Var PRINT_META = Var.intern(CLOJURE_NS, Symbol.create("*print-meta*"), F);
204 final static Var PRINT_READABLY = Var.intern(CLOJURE_NS, Symbol.create("*print-readably*"), T);
205 final static Var PRINT_DUP = Var.intern(CLOJURE_NS, Symbol.create("*print-dup*"), F);
206 final static Var WARN_ON_REFLECTION = Var.intern(CLOJURE_NS, Symbol.create("*warn-on-reflection*"), F);
207 final static Var ALLOW_UNRESOLVED_VARS = Var.intern(CLOJURE_NS, Symbol.create("*allow-unresolved-vars*"), F);
208
209 final static Var IN_NS_VAR = Var.intern(CLOJURE_NS, Symbol.create("in-ns"), F);
210 final static Var NS_VAR = Var.intern(CLOJURE_NS, Symbol.create("ns"), F);
211 static final Var PRINT_INITIALIZED = Var.intern(CLOJURE_NS, Symbol.create("print-initialized"));
212 static final Var PR_ON = Var.intern(CLOJURE_NS, Symbol.create("pr-on"));
213 //final static Var IMPORTS = Var.intern(CLOJURE_NS, Symbol.create("*imports*"), DEFAULT_IMPORTS);
214 final static IFn inNamespace = new AFn(){
215 public Object invoke(Object arg1) throws Exception{
216 Symbol nsname = (Symbol) arg1;
217 Namespace ns = Namespace.findOrCreate(nsname);
218 CURRENT_NS.set(ns);
219 return ns;
220 }
221 };
222
223 final static IFn bootNamespace = new AFn(){
224 public Object invoke(Object __form, Object __env,Object arg1) throws Exception{
225 Symbol nsname = (Symbol) arg1;
226 Namespace ns = Namespace.findOrCreate(nsname);
227 CURRENT_NS.set(ns);
228 return ns;
229 }
230 };
231
232 public static List<String> processCommandLine(String[] args){
233 List<String> arglist = Arrays.asList(args);
234 int split = arglist.indexOf("--");
235 if(split >= 0) {
236 CMD_LINE_ARGS.bindRoot(RT.seq(arglist.subList(split + 1, args.length)));
237 return arglist.subList(0, split);
238 }
239 return arglist;
240 }
241
242 // duck typing stderr plays nice with e.g. swank
243 public static PrintWriter errPrintWriter(){
244 Writer w = (Writer) ERR.deref();
245 if (w instanceof PrintWriter) {
246 return (PrintWriter) w;
247 } else {
248 return new PrintWriter(w);
249 }
250 }
251
252 static public final Object[] EMPTY_ARRAY = new Object[]{};
253 static public final Comparator DEFAULT_COMPARATOR = new DefaultComparator();
254
255 private static final class DefaultComparator implements Comparator, Serializable {
256 public int compare(Object o1, Object o2){
257 return Util.compare(o1, o2);
258 }
259
260 private Object readResolve() throws ObjectStreamException {
261 // ensures that we aren't hanging onto a new default comparator for every
262 // sorted set, etc., we deserialize
263 return DEFAULT_COMPARATOR;
264 }
265 }
266
267 static AtomicInteger id = new AtomicInteger(1);
268
269 static public void addURL(Object url) throws Exception{
270 URL u = (url instanceof String) ? (new URL((String) url)) : (URL) url;
271 ClassLoader ccl = Thread.currentThread().getContextClassLoader();
272 if(ccl instanceof DynamicClassLoader)
273 ((DynamicClassLoader)ccl).addURL(u);
274 else
275 throw new IllegalAccessError("Context classloader is not a DynamicClassLoader");
276 }
277
278 static{
279 Keyword dockw = Keyword.intern(null, "doc");
280 Keyword arglistskw = Keyword.intern(null, "arglists");
281 Symbol namesym = Symbol.create("name");
282 OUT.setTag(Symbol.create("java.io.Writer"));
283 CURRENT_NS.setTag(Symbol.create("clojure.lang.Namespace"));
284 AGENT.setMeta(map(dockw, "The agent currently running an action on this thread, else nil"));
285 AGENT.setTag(Symbol.create("clojure.lang.Agent"));
286 MATH_CONTEXT.setTag(Symbol.create("java.math.MathContext"));
287 Var nv = Var.intern(CLOJURE_NS, NAMESPACE, bootNamespace);
288 nv.setMacro();
289 Var v;
290 v = Var.intern(CLOJURE_NS, IN_NAMESPACE, inNamespace);
291 v.setMeta(map(dockw, "Sets *ns* to the namespace named by the symbol, creating it if needed.",
292 arglistskw, list(vector(namesym))));
293 v = Var.intern(CLOJURE_NS, LOAD_FILE,
294 new AFn(){
295 public Object invoke(Object arg1) throws Exception{
296 return Compiler.loadFile((String) arg1);
297 }
298 });
299 v.setMeta(map(dockw, "Sequentially read and evaluate the set of forms contained in the file.",
300 arglistskw, list(vector(namesym))));
301 try {
302 doInit();
303 }
304 catch(Exception e) {
305 throw new RuntimeException(e);
306 }
307 }
308
309
310 static public Var var(String ns, String name){
311 return Var.intern(Namespace.findOrCreate(Symbol.intern(null, ns)), Symbol.intern(null, name));
312 }
313
314 static public Var var(String ns, String name, Object init){
315 return Var.intern(Namespace.findOrCreate(Symbol.intern(null, ns)), Symbol.intern(null, name), init);
316 }
317
318 public static void loadResourceScript(String name) throws Exception{
319 loadResourceScript(name, true);
320 }
321
322 public static void maybeLoadResourceScript(String name) throws Exception{
323 loadResourceScript(name, false);
324 }
325
326 public static void loadResourceScript(String name, boolean failIfNotFound) throws Exception{
327 loadResourceScript(RT.class, name, failIfNotFound);
328 }
329
330 public static void loadResourceScript(Class c, String name) throws Exception{
331 loadResourceScript(c, name, true);
332 }
333
334 public static void loadResourceScript(Class c, String name, boolean failIfNotFound) throws Exception{
335 int slash = name.lastIndexOf('/');
336 String file = slash >= 0 ? name.substring(slash + 1) : name;
337 InputStream ins = baseLoader().getResourceAsStream(name);
338 if(ins != null) {
339 try {
340 Compiler.load(new InputStreamReader(ins, UTF8), name, file);
341 }
342 finally {
343 ins.close();
344 }
345 }
346 else if(failIfNotFound) {
347 throw new FileNotFoundException("Could not locate Clojure resource on classpath: " + name);
348 }
349 }
350
351 static public void init() throws Exception{
352 RT.errPrintWriter().println("No need to call RT.init() anymore");
353 }
354
355 static public long lastModified(URL url, String libfile) throws Exception{
356 if(url.getProtocol().equals("jar")) {
357 return ((JarURLConnection) url.openConnection()).getJarFile().getEntry(libfile).getTime();
358 }
359 else {
360 return url.openConnection().getLastModified();
361 }
362 }
363
364 static void compile(String cljfile) throws Exception{
365 InputStream ins = baseLoader().getResourceAsStream(cljfile);
366 if(ins != null) {
367 try {
368 Compiler.compile(new InputStreamReader(ins, UTF8), cljfile,
369 cljfile.substring(1 + cljfile.lastIndexOf("/")));
370 }
371 finally {
372 ins.close();
373 }
374
375 }
376 else
377 throw new FileNotFoundException("Could not locate Clojure resource on classpath: " + cljfile);
378 }
379
380 static public void load(String scriptbase) throws Exception{
381 load(scriptbase, true);
382 }
383
384 static public void load(String scriptbase, boolean failIfNotFound) throws Exception{
385 String classfile = scriptbase + LOADER_SUFFIX + ".class";
386 String cljfile = scriptbase + ".clj";
387 URL classURL = baseLoader().getResource(classfile);
388 URL cljURL = baseLoader().getResource(cljfile);
389 boolean loaded = false;
390
391 if((classURL != null &&
392 (cljURL == null
393 || lastModified(classURL, classfile) > lastModified(cljURL, cljfile)))
394 || classURL == null) {
395 try {
396 Var.pushThreadBindings(
397 RT.map(CURRENT_NS, CURRENT_NS.deref(),
398 WARN_ON_REFLECTION, WARN_ON_REFLECTION.deref()));
399 loaded = (loadClassForName(scriptbase.replace('/', '.') + LOADER_SUFFIX) != null);
400 }
401 finally {
402 Var.popThreadBindings();
403 }
404 }
405 if(!loaded && cljURL != null) {
406 if(booleanCast(Compiler.COMPILE_FILES.deref()))
407 compile(cljfile);
408 else
409 loadResourceScript(RT.class, cljfile);
410 }
411 else if(!loaded && failIfNotFound)
412 throw new FileNotFoundException(String.format("Could not locate %s or %s on classpath: ", classfile, cljfile));
413 }
414
415 static void doInit() throws Exception{
416 load("clojure/core");
417 load("clojure/zip", false);
418 load("clojure/xml", false);
419 load("clojure/set", false);
420
421 Var.pushThreadBindings(
422 RT.map(CURRENT_NS, CURRENT_NS.deref(),
423 WARN_ON_REFLECTION, WARN_ON_REFLECTION.deref()));
424 try {
425 Symbol USER = Symbol.create("user");
426 Symbol CLOJURE = Symbol.create("clojure.core");
427
428 Var in_ns = var("clojure.core", "in-ns");
429 Var refer = var("clojure.core", "refer");
430 in_ns.invoke(USER);
431 refer.invoke(CLOJURE);
432 maybeLoadResourceScript("user.clj");
433 }
434 finally {
435 Var.popThreadBindings();
436 }
437 }
438
439 static public int nextID(){
440 return id.getAndIncrement();
441 }
442
443
444 ////////////// Collections support /////////////////////////////////
445
446 static public ISeq seq(Object coll){
447 if(coll instanceof ASeq)
448 return (ASeq) coll;
449 else if(coll instanceof LazySeq)
450 return ((LazySeq) coll).seq();
451 else
452 return seqFrom(coll);
453 }
454
455 static ISeq seqFrom(Object coll){
456 if(coll instanceof Seqable)
457 return ((Seqable) coll).seq();
458 else if(coll == null)
459 return null;
460 else if(coll instanceof Iterable)
461 return IteratorSeq.create(((Iterable) coll).iterator());
462 else if(coll.getClass().isArray())
463 return ArraySeq.createFromObject(coll);
464 else if(coll instanceof CharSequence)
465 return StringSeq.create((CharSequence) coll);
466 else if(coll instanceof Map)
467 return seq(((Map) coll).entrySet());
468 else {
469 Class c = coll.getClass();
470 Class sc = c.getSuperclass();
471 throw new IllegalArgumentException("Don't know how to create ISeq from: " + c.getName());
472 }
473 }
474
475 static public ISeq keys(Object coll){
476 return APersistentMap.KeySeq.create(seq(coll));
477 }
478
479 static public ISeq vals(Object coll){
480 return APersistentMap.ValSeq.create(seq(coll));
481 }
482
483 static public IPersistentMap meta(Object x){
484 if(x instanceof IMeta)
485 return ((IMeta) x).meta();
486 return null;
487 }
488
489 public static int count(Object o){
490 if(o instanceof Counted)
491 return ((Counted) o).count();
492 return countFrom(Util.ret1(o, o = null));
493 }
494
495 static int countFrom(Object o){
496 if(o == null)
497 return 0;
498 else if(o instanceof IPersistentCollection) {
499 ISeq s = seq(o);
500 o = null;
501 int i = 0;
502 for(; s != null; s = s.next()) {
503 if(s instanceof Counted)
504 return i + s.count();
505 i++;
506 }
507 return i;
508 }
509 else if(o instanceof CharSequence)
510 return ((CharSequence) o).length();
511 else if(o instanceof Collection)
512 return ((Collection) o).size();
513 else if(o instanceof Map)
514 return ((Map) o).size();
515 else if(o.getClass().isArray())
516 return Array.getLength(o);
517
518 throw new UnsupportedOperationException("count not supported on this type: " + o.getClass().getSimpleName());
519 }
520
521 static public IPersistentCollection conj(IPersistentCollection coll, Object x){
522 if(coll == null)
523 return new PersistentList(x);
524 return coll.cons(x);
525 }
526
527 static public ISeq cons(Object x, Object coll){
528 //ISeq y = seq(coll);
529 if(coll == null)
530 return new PersistentList(x);
531 else if(coll instanceof ISeq)
532 return new Cons(x, (ISeq) coll);
533 else
534 return new Cons(x, seq(coll));
535 }
536
537 static public Object first(Object x){
538 if(x instanceof ISeq)
539 return ((ISeq) x).first();
540 ISeq seq = seq(x);
541 if(seq == null)
542 return null;
543 return seq.first();
544 }
545
546 static public Object second(Object x){
547 return first(next(x));
548 }
549
550 static public Object third(Object x){
551 return first(next(next(x)));
552 }
553
554 static public Object fourth(Object x){
555 return first(next(next(next(x))));
556 }
557
558 static public ISeq next(Object x){
559 if(x instanceof ISeq)
560 return ((ISeq) x).next();
561 ISeq seq = seq(x);
562 if(seq == null)
563 return null;
564 return seq.next();
565 }
566
567 static public ISeq more(Object x){
568 if(x instanceof ISeq)
569 return ((ISeq) x).more();
570 ISeq seq = seq(x);
571 if(seq == null)
572 return PersistentList.EMPTY;
573 return seq.more();
574 }
575
576 //static public Seqable more(Object x){
577 // Seqable ret = null;
578 // if(x instanceof ISeq)
579 // ret = ((ISeq) x).more();
580 // else
581 // {
582 // ISeq seq = seq(x);
583 // if(seq == null)
584 // ret = PersistentList.EMPTY;
585 // else
586 // ret = seq.more();
587 // }
588 // if(ret == null)
589 // ret = PersistentList.EMPTY;
590 // return ret;
591 //}
592
593 static public Object peek(Object x){
594 if(x == null)
595 return null;
596 return ((IPersistentStack) x).peek();
597 }
598
599 static public Object pop(Object x){
600 if(x == null)
601 return null;
602 return ((IPersistentStack) x).pop();
603 }
604
605 static public Object get(Object coll, Object key){
606 if(coll instanceof ILookup)
607 return ((ILookup) coll).valAt(key);
608 return getFrom(coll, key);
609 }
610
611 static Object getFrom(Object coll, Object key){
612 if(coll == null)
613 return null;
614 else if(coll instanceof Map) {
615 Map m = (Map) coll;
616 return m.get(key);
617 }
618 else if(coll instanceof IPersistentSet) {
619 IPersistentSet set = (IPersistentSet) coll;
620 return set.get(key);
621 }
622 else if(key instanceof Number && (coll instanceof String || coll.getClass().isArray())) {
623 int n = ((Number) key).intValue();
624 if(n >= 0 && n < count(coll))
625 return nth(coll, n);
626 return null;
627 }
628
629 return null;
630 }
631
632 static public Object get(Object coll, Object key, Object notFound){
633 if(coll instanceof ILookup)
634 return ((ILookup) coll).valAt(key, notFound);
635 return getFrom(coll, key, notFound);
636 }
637
638 static Object getFrom(Object coll, Object key, Object notFound){
639 if(coll == null)
640 return notFound;
641 else if(coll instanceof Map) {
642 Map m = (Map) coll;
643 if(m.containsKey(key))
644 return m.get(key);
645 return notFound;
646 }
647 else if(coll instanceof IPersistentSet) {
648 IPersistentSet set = (IPersistentSet) coll;
649 if(set.contains(key))
650 return set.get(key);
651 return notFound;
652 }
653 else if(key instanceof Number && (coll instanceof String || coll.getClass().isArray())) {
654 int n = ((Number) key).intValue();
655 return n >= 0 && n < count(coll) ? nth(coll, n) : notFound;
656 }
657 return notFound;
658
659 }
660
661 static public Associative assoc(Object coll, Object key, Object val){
662 if(coll == null)
663 return new PersistentArrayMap(new Object[]{key, val});
664 return ((Associative) coll).assoc(key, val);
665 }
666
667 static public Object contains(Object coll, Object key){
668 if(coll == null)
669 return F;
670 else if(coll instanceof Associative)
671 return ((Associative) coll).containsKey(key) ? T : F;
672 else if(coll instanceof IPersistentSet)
673 return ((IPersistentSet) coll).contains(key) ? T : F;
674 else if(coll instanceof Map) {
675 Map m = (Map) coll;
676 return m.containsKey(key) ? T : F;
677 }
678 else if(key instanceof Number && (coll instanceof String || coll.getClass().isArray())) {
679 int n = ((Number) key).intValue();
680 return n >= 0 && n < count(coll);
681 }
682 return F;
683 }
684
685 static public Object find(Object coll, Object key){
686 if(coll == null)
687 return null;
688 else if(coll instanceof Associative)
689 return ((Associative) coll).entryAt(key);
690 else {
691 Map m = (Map) coll;
692 if(m.containsKey(key))
693 return new MapEntry(key, m.get(key));
694 return null;
695 }
696 }
697
698 //takes a seq of key,val,key,val
699
700 //returns tail starting at val of matching key if found, else null
701 static public ISeq findKey(Keyword key, ISeq keyvals) throws Exception{
702 while(keyvals != null) {
703 ISeq r = keyvals.next();
704 if(r == null)
705 throw new Exception("Malformed keyword argslist");
706 if(keyvals.first() == key)
707 return r;
708 keyvals = r.next();
709 }
710 return null;
711 }
712
713 static public Object dissoc(Object coll, Object key) throws Exception{
714 if(coll == null)
715 return null;
716 return ((IPersistentMap) coll).without(key);
717 }
718
719 static public Object nth(Object coll, int n){
720 if(coll instanceof Indexed)
721 return ((Indexed) coll).nth(n);
722 return nthFrom(Util.ret1(coll, coll = null), n);
723 }
724
725 static Object nthFrom(Object coll, int n){
726 if(coll == null)
727 return null;
728 else if(coll instanceof CharSequence)
729 return Character.valueOf(((CharSequence) coll).charAt(n));
730 else if(coll.getClass().isArray())
731 return Reflector.prepRet(Array.get(coll, n));
732 else if(coll instanceof RandomAccess)
733 return ((List) coll).get(n);
734 else if(coll instanceof Matcher)
735 return ((Matcher) coll).group(n);
736
737 else if(coll instanceof Map.Entry) {
738 Map.Entry e = (Map.Entry) coll;
739 if(n == 0)
740 return e.getKey();
741 else if(n == 1)
742 return e.getValue();
743 throw new IndexOutOfBoundsException();
744 }
745
746 else if(coll instanceof Sequential) {
747 ISeq seq = RT.seq(coll);
748 coll = null;
749 for(int i = 0; i <= n && seq != null; ++i, seq = seq.next()) {
750 if(i == n)
751 return seq.first();
752 }
753 throw new IndexOutOfBoundsException();
754 }
755 else
756 throw new UnsupportedOperationException(
757 "nth not supported on this type: " + coll.getClass().getSimpleName());
758 }
759
760 static public Object nth(Object coll, int n, Object notFound){
761 if(coll instanceof Indexed) {
762 Indexed v = (Indexed) coll;
763 return v.nth(n, notFound);
764 }
765 return nthFrom(coll, n, notFound);
766 }
767
768 static Object nthFrom(Object coll, int n, Object notFound){
769 if(coll == null)
770 return notFound;
771 else if(n < 0)
772 return notFound;
773
774 else if(coll instanceof CharSequence) {
775 CharSequence s = (CharSequence) coll;
776 if(n < s.length())
777 return Character.valueOf(s.charAt(n));
778 return notFound;
779 }
780 else if(coll.getClass().isArray()) {
781 if(n < Array.getLength(coll))
782 return Reflector.prepRet(Array.get(coll, n));
783 return notFound;
784 }
785 else if(coll instanceof RandomAccess) {
786 List list = (List) coll;
787 if(n < list.size())
788 return list.get(n);
789 return notFound;
790 }
791 else if(coll instanceof Matcher) {
792 Matcher m = (Matcher) coll;
793 if(n < m.groupCount())
794 return m.group(n);
795 return notFound;
796 }
797 else if(coll instanceof Map.Entry) {
798 Map.Entry e = (Map.Entry) coll;
799 if(n == 0)
800 return e.getKey();
801 else if(n == 1)
802 return e.getValue();
803 return notFound;
804 }
805 else if(coll instanceof Sequential) {
806 ISeq seq = RT.seq(coll);
807 coll = null;
808 for(int i = 0; i <= n && seq != null; ++i, seq = seq.next()) {
809 if(i == n)
810 return seq.first();
811 }
812 return notFound;
813 }
814 else
815 throw new UnsupportedOperationException(
816 "nth not supported on this type: " + coll.getClass().getSimpleName());
817 }
818
819 static public Object assocN(int n, Object val, Object coll){
820 if(coll == null)
821 return null;
822 else if(coll instanceof IPersistentVector)
823 return ((IPersistentVector) coll).assocN(n, val);
824 else if(coll instanceof Object[]) {
825 //hmm... this is not persistent
826 Object[] array = ((Object[]) coll);
827 array[n] = val;
828 return array;
829 }
830 else
831 return null;
832 }
833
834 static boolean hasTag(Object o, Object tag){
835 return Util.equals(tag, RT.get(RT.meta(o), TAG_KEY));
836 }
837
838 /**
839 * ********************* Boxing/casts ******************************
840 */
841 static public Object box(Object x){
842 return x;
843 }
844
845 static public Character box(char x){
846 return Character.valueOf(x);
847 }
848
849 static public Object box(boolean x){
850 return x ? T : F;
851 }
852
853 static public Object box(Boolean x){
854 return x;// ? T : null;
855 }
856
857 static public Number box(byte x){
858 return x;//Num.from(x);
859 }
860
861 static public Number box(short x){
862 return x;//Num.from(x);
863 }
864
865 static public Number box(int x){
866 return x;//Num.from(x);
867 }
868
869 static public Number box(long x){
870 return x;//Num.from(x);
871 }
872
873 static public Number box(float x){
874 return x;//Num.from(x);
875 }
876
877 static public Number box(double x){
878 return x;//Num.from(x);
879 }
880
881 static public char charCast(Object x){
882 if(x instanceof Character)
883 return ((Character) x).charValue();
884
885 long n = ((Number) x).longValue();
886 if(n < Character.MIN_VALUE || n > Character.MAX_VALUE)
887 throw new IllegalArgumentException("Value out of range for char: " + x);
888
889 return (char) n;
890 }
891
892 static public boolean booleanCast(Object x){
893 if(x instanceof Boolean)
894 return ((Boolean) x).booleanValue();
895 return x != null;
896 }
897
898 static public boolean booleanCast(boolean x){
899 return x;
900 }
901
902 static public byte byteCast(Object x){
903 long n = ((Number) x).longValue();
904 if(n < Byte.MIN_VALUE || n > Byte.MAX_VALUE)
905 throw new IllegalArgumentException("Value out of range for byte: " + x);
906
907 return (byte) n;
908 }
909
910 static public short shortCast(Object x){
911 long n = ((Number) x).longValue();
912 if(n < Short.MIN_VALUE || n > Short.MAX_VALUE)
913 throw new IllegalArgumentException("Value out of range for short: " + x);
914
915 return (short) n;
916 }
917
918 static public int intCast(Object x){
919 if(x instanceof Integer)
920 return ((Integer)x).intValue();
921 if(x instanceof Number)
922 return intCast(((Number) x).longValue());
923 return ((Character) x).charValue();
924 }
925
926 static public int intCast(char x){
927 return x;
928 }
929
930 static public int intCast(byte x){
931 return x;
932 }
933
934 static public int intCast(short x){
935 return x;
936 }
937
938 static public int intCast(int x){
939 return x;
940 }
941
942 static public int intCast(float x){
943 if(x < Integer.MIN_VALUE || x > Integer.MAX_VALUE)
944 throw new IllegalArgumentException("Value out of range for int: " + x);
945 return (int) x;
946 }
947
948 static public int intCast(long x){
949 if(x < Integer.MIN_VALUE || x > Integer.MAX_VALUE)
950 throw new IllegalArgumentException("Value out of range for int: " + x);
951 return (int) x;
952 }
953
954 static public int intCast(double x){
955 if(x < Integer.MIN_VALUE || x > Integer.MAX_VALUE)
956 throw new IllegalArgumentException("Value out of range for int: " + x);
957 return (int) x;
958 }
959
960 static public long longCast(Object x){
961 return ((Number) x).longValue();
962 }
963
964 static public long longCast(int x){
965 return x;
966 }
967
968 static public long longCast(float x){
969 if(x < Long.MIN_VALUE || x > Long.MAX_VALUE)
970 throw new IllegalArgumentException("Value out of range for long: " + x);
971 return (long) x;
972 }
973
974 static public long longCast(long x){
975 return x;
976 }
977
978 static public long longCast(double x){
979 if(x < Long.MIN_VALUE || x > Long.MAX_VALUE)
980 throw new IllegalArgumentException("Value out of range for long: " + x);
981 return (long) x;
982 }
983
984 static public float floatCast(Object x){
985 if(x instanceof Float)
986 return ((Float) x).floatValue();
987
988 double n = ((Number) x).doubleValue();
989 if(n < -Float.MAX_VALUE || n > Float.MAX_VALUE)
990 throw new IllegalArgumentException("Value out of range for float: " + x);
991
992 return (float) n;
993
994 }
995
996 static public float floatCast(int x){
997 return x;
998 }
999
1000 static public float floatCast(float x){
1001 return x;
1002 }
1003
1004 static public float floatCast(long x){
1005 return x;
1006 }
1007
1008 static public float floatCast(double x){
1009 if(x < -Float.MAX_VALUE || x > Float.MAX_VALUE)
1010 throw new IllegalArgumentException("Value out of range for float: " + x);
1011
1012 return (float) x;
1013 }
1014
1015 static public double doubleCast(Object x){
1016 return ((Number) x).doubleValue();
1017 }
1018
1019 static public double doubleCast(int x){
1020 return x;
1021 }
1022
1023 static public double doubleCast(float x){
1024 return x;
1025 }
1026
1027 static public double doubleCast(long x){
1028 return x;
1029 }
1030
1031 static public double doubleCast(double x){
1032 return x;
1033 }
1034
1035 static public IPersistentMap map(Object... init){
1036 if(init == null)
1037 return PersistentArrayMap.EMPTY;
1038 else if(init.length <= PersistentArrayMap.HASHTABLE_THRESHOLD)
1039 return PersistentArrayMap.createWithCheck(init);
1040 return PersistentHashMap.createWithCheck(init);
1041 }
1042
1043 static public IPersistentSet set(Object... init){
1044 return PersistentHashSet.createWithCheck(init);
1045 }
1046
1047 static public IPersistentVector vector(Object... init){
1048 return LazilyPersistentVector.createOwning(init);
1049 }
1050
1051 static public IPersistentVector subvec(IPersistentVector v, int start, int end){
1052 if(end < start || start < 0 || end > v.count())
1053 throw new IndexOutOfBoundsException();
1054 if(start == end)
1055 return PersistentVector.EMPTY;
1056 return new APersistentVector.SubVector(null, v, start, end);
1057 }
1058
1059 /**
1060 * **************************************** list support *******************************
1061 */
1062
1063
1064 static public ISeq list(){
1065 return null;
1066 }
1067
1068 static public ISeq list(Object arg1){
1069 return new PersistentList(arg1);
1070 }
1071
1072 static public ISeq list(Object arg1, Object arg2){
1073 return listStar(arg1, arg2, null);
1074 }
1075
1076 static public ISeq list(Object arg1, Object arg2, Object arg3){
1077 return listStar(arg1, arg2, arg3, null);
1078 }
1079
1080 static public ISeq list(Object arg1, Object arg2, Object arg3, Object arg4){
1081 return listStar(arg1, arg2, arg3, arg4, null);
1082 }
1083
1084 static public ISeq list(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5){
1085 return listStar(arg1, arg2, arg3, arg4, arg5, null);
1086 }
1087
1088 static public ISeq listStar(Object arg1, ISeq rest){
1089 return (ISeq) cons(arg1, rest);
1090 }
1091
1092 static public ISeq listStar(Object arg1, Object arg2, ISeq rest){
1093 return (ISeq) cons(arg1, cons(arg2, rest));
1094 }
1095
1096 static public ISeq listStar(Object arg1, Object arg2, Object arg3, ISeq rest){
1097 return (ISeq) cons(arg1, cons(arg2, cons(arg3, rest)));
1098 }
1099
1100 static public ISeq listStar(Object arg1, Object arg2, Object arg3, Object arg4, ISeq rest){
1101 return (ISeq) cons(arg1, cons(arg2, cons(arg3, cons(arg4, rest))));
1102 }
1103
1104 static public ISeq listStar(Object arg1, Object arg2, Object arg3, Object arg4, Object arg5, ISeq rest){
1105 return (ISeq) cons(arg1, cons(arg2, cons(arg3, cons(arg4, cons(arg5, rest)))));
1106 }
1107
1108 static public ISeq arrayToList(Object[] a) throws Exception{
1109 ISeq ret = null;
1110 for(int i = a.length - 1; i >= 0; --i)
1111 ret = (ISeq) cons(a[i], ret);
1112 return ret;
1113 }
1114
1115 static public Object[] object_array(Object sizeOrSeq){
1116 if(sizeOrSeq instanceof Number)
1117 return new Object[((Number) sizeOrSeq).intValue()];
1118 else
1119 {
1120 ISeq s = RT.seq(sizeOrSeq);
1121 int size = RT.count(s);
1122 Object[] ret = new Object[size];
1123 for(int i = 0; i < size && s != null; i++, s = s.next())
1124 ret[i] = s.first();
1125 return ret;
1126 }
1127 }
1128
1129 static public Object[] toArray(Object coll) throws Exception{
1130 if(coll == null)
1131 return EMPTY_ARRAY;
1132 else if(coll instanceof Object[])
1133 return (Object[]) coll;
1134 else if(coll instanceof Collection)
1135 return ((Collection) coll).toArray();
1136 else if(coll instanceof Map)
1137 return ((Map) coll).entrySet().toArray();
1138 else if(coll instanceof String) {
1139 char[] chars = ((String) coll).toCharArray();
1140 Object[] ret = new Object[chars.length];
1141 for(int i = 0; i < chars.length; i++)
1142 ret[i] = chars[i];
1143 return ret;
1144 }
1145 else if(coll.getClass().isArray()) {
1146 ISeq s = (seq(coll));
1147 Object[] ret = new Object[count(s)];
1148 for(int i = 0; i < ret.length; i++, s = s.next())
1149 ret[i] = s.first();
1150 return ret;
1151 }
1152 else
1153 throw new Exception("Unable to convert: " + coll.getClass() + " to Object[]");
1154 }
1155
1156 static public Object[] seqToArray(ISeq seq){
1157 int len = length(seq);
1158 Object[] ret = new Object[len];
1159 for(int i = 0; seq != null; ++i, seq = seq.next())
1160 ret[i] = seq.first();
1161 return ret;
1162 }
1163
1164 static public Object seqToTypedArray(ISeq seq) throws Exception{
1165 Class type = (seq != null) ? seq.first().getClass() : Object.class;
1166 return seqToTypedArray(type, seq);
1167 }
1168
1169 static public Object seqToTypedArray(Class type, ISeq seq) throws Exception{
1170 Object ret = Array.newInstance(type, length(seq));
1171 for(int i = 0; seq != null; ++i, seq = seq.next())
1172 Array.set(ret, i, seq.first());
1173 return ret;
1174 }
1175
1176 static public int length(ISeq list){
1177 int i = 0;
1178 for(ISeq c = list; c != null; c = c.next()) {
1179 i++;
1180 }
1181 return i;
1182 }
1183
1184 static public int boundedLength(ISeq list, int limit) throws Exception{
1185 int i = 0;
1186 for(ISeq c = list; c != null && i <= limit; c = c.next()) {
1187 i++;
1188 }
1189 return i;
1190 }
1191
1192 ///////////////////////////////// reader support ////////////////////////////////
1193
1194 static Character readRet(int ret){
1195 if(ret == -1)
1196 return null;
1197 return box((char) ret);
1198 }
1199
1200 static public Character readChar(Reader r) throws Exception{
1201 int ret = r.read();
1202 return readRet(ret);
1203 }
1204
1205 static public Character peekChar(Reader r) throws Exception{
1206 int ret;
1207 if(r instanceof PushbackReader) {
1208 ret = r.read();
1209 ((PushbackReader) r).unread(ret);
1210 }
1211 else {
1212 r.mark(1);
1213 ret = r.read();
1214 r.reset();
1215 }
1216
1217 return readRet(ret);
1218 }
1219
1220 static public int getLineNumber(Reader r){
1221 if(r instanceof LineNumberingPushbackReader)
1222 return ((LineNumberingPushbackReader) r).getLineNumber();
1223 return 0;
1224 }
1225
1226 static public LineNumberingPushbackReader getLineNumberingReader(Reader r){
1227 if(isLineNumberingReader(r))
1228 return (LineNumberingPushbackReader) r;
1229 return new LineNumberingPushbackReader(r);
1230 }
1231
1232 static public boolean isLineNumberingReader(Reader r){
1233 return r instanceof LineNumberingPushbackReader;
1234 }
1235
1236 static public String resolveClassNameInContext(String className){
1237 //todo - look up in context var
1238 return className;
1239 }
1240
1241 static public boolean suppressRead(){
1242 //todo - look up in suppress-read var
1243 return false;
1244 }
1245
1246 static public String printString(Object x){
1247 try {
1248 StringWriter sw = new StringWriter();
1249 print(x, sw);
1250 return sw.toString();
1251 }
1252 catch(Exception e) {
1253 throw new RuntimeException(e);
1254 }
1255 }
1256
1257 static public Object readString(String s){
1258 PushbackReader r = new PushbackReader(new StringReader(s));
1259 try {
1260 return LispReader.read(r, true, null, false);
1261 }
1262 catch(Exception e) {
1263 throw new RuntimeException(e);
1264 }
1265 }
1266
1267 static public void print(Object x, Writer w) throws Exception{
1268 //call multimethod
1269 if(PRINT_INITIALIZED.isBound() && RT.booleanCast(PRINT_INITIALIZED.deref()))
1270 PR_ON.invoke(x, w);
1271 //*
1272 else {
1273 boolean readably = booleanCast(PRINT_READABLY.deref());
1274 if(x instanceof Obj) {
1275 Obj o = (Obj) x;
1276 if(RT.count(o.meta()) > 0 &&
1277 ((readably && booleanCast(PRINT_META.deref()))
1278 || booleanCast(PRINT_DUP.deref()))) {
1279 IPersistentMap meta = o.meta();
1280 w.write("#^");
1281 if(meta.count() == 1 && meta.containsKey(TAG_KEY))
1282 print(meta.valAt(TAG_KEY), w);
1283 else
1284 print(meta, w);
1285 w.write(' ');
1286 }
1287 }
1288 if(x == null)
1289 w.write("nil");
1290 else if(x instanceof ISeq || x instanceof IPersistentList) {
1291 w.write('(');
1292 printInnerSeq(seq(x), w);
1293 w.write(')');
1294 }
1295 else if(x instanceof String) {
1296 String s = (String) x;
1297 if(!readably)
1298 w.write(s);
1299 else {
1300 w.write('"');
1301 //w.write(x.toString());
1302 for(int i = 0; i < s.length(); i++) {
1303 char c = s.charAt(i);
1304 switch(c) {
1305 case '\n':
1306 w.write("\\n");
1307 break;
1308 case '\t':
1309 w.write("\\t");
1310 break;
1311 case '\r':
1312 w.write("\\r");
1313 break;
1314 case '"':
1315 w.write("\\\"");
1316 break;
1317 case '\\':
1318 w.write("\\\\");
1319 break;
1320 case '\f':
1321 w.write("\\f");
1322 break;
1323 case '\b':
1324 w.write("\\b");
1325 break;
1326 default:
1327 w.write(c);
1328 }
1329 }
1330 w.write('"');
1331 }
1332 }
1333 else if(x instanceof IPersistentMap) {
1334 w.write('{');
1335 for(ISeq s = seq(x); s != null; s = s.next()) {
1336 IMapEntry e = (IMapEntry) s.first();
1337 print(e.key(), w);
1338 w.write(' ');
1339 print(e.val(), w);
1340 if(s.next() != null)
1341 w.write(", ");
1342 }
1343 w.write('}');
1344 }
1345 else if(x instanceof IPersistentVector) {
1346 IPersistentVector a = (IPersistentVector) x;
1347 w.write('[');
1348 for(int i = 0; i < a.count(); i++) {
1349 print(a.nth(i), w);
1350 if(i < a.count() - 1)
1351 w.write(' ');
1352 }
1353 w.write(']');
1354 }
1355 else if(x instanceof IPersistentSet) {
1356 w.write("#{");
1357 for(ISeq s = seq(x); s != null; s = s.next()) {
1358 print(s.first(), w);
1359 if(s.next() != null)
1360 w.write(" ");
1361 }
1362 w.write('}');
1363 }
1364 else if(x instanceof Character) {
1365 char c = ((Character) x).charValue();
1366 if(!readably)
1367 w.write(c);
1368 else {
1369 w.write('\\');
1370 switch(c) {
1371 case '\n':
1372 w.write("newline");
1373 break;
1374 case '\t':
1375 w.write("tab");
1376 break;
1377 case ' ':
1378 w.write("space");
1379 break;
1380 case '\b':
1381 w.write("backspace");
1382 break;
1383 case '\f':
1384 w.write("formfeed");
1385 break;
1386 case '\r':
1387 w.write("return");
1388 break;
1389 default:
1390 w.write(c);
1391 }
1392 }
1393 }
1394 else if(x instanceof Class) {
1395 w.write("#=");
1396 w.write(((Class) x).getName());
1397 }
1398 else if(x instanceof BigDecimal && readably) {
1399 w.write(x.toString());
1400 w.write('M');
1401 }
1402 else if(x instanceof Var) {
1403 Var v = (Var) x;
1404 w.write("#=(var " + v.ns.name + "/" + v.sym + ")");
1405 }
1406 else if(x instanceof Pattern) {
1407 Pattern p = (Pattern) x;
1408 w.write("#\"" + p.pattern() + "\"");
1409 }
1410 else w.write(x.toString());
1411 }
1412 //*/
1413 }
1414
1415 private static void printInnerSeq(ISeq x, Writer w) throws Exception{
1416 for(ISeq s = x; s != null; s = s.next()) {
1417 print(s.first(), w);
1418 if(s.next() != null)
1419 w.write(' ');
1420 }
1421 }
1422
1423 static public void formatAesthetic(Writer w, Object obj) throws IOException{
1424 if(obj == null)
1425 w.write("null");
1426 else
1427 w.write(obj.toString());
1428 }
1429
1430 static public void formatStandard(Writer w, Object obj) throws IOException{
1431 if(obj == null)
1432 w.write("null");
1433 else if(obj instanceof String) {
1434 w.write('"');
1435 w.write((String) obj);
1436 w.write('"');
1437 }
1438 else if(obj instanceof Character) {
1439 w.write('\\');
1440 char c = ((Character) obj).charValue();
1441 switch(c) {
1442 case '\n':
1443 w.write("newline");
1444 break;
1445 case '\t':
1446 w.write("tab");
1447 break;
1448 case ' ':
1449 w.write("space");
1450 break;
1451 case '\b':
1452 w.write("backspace");
1453 break;
1454 case '\f':
1455 w.write("formfeed");
1456 break;
1457 default:
1458 w.write(c);
1459 }
1460 }
1461 else
1462 w.write(obj.toString());
1463 }
1464
1465 static public Object format(Object o, String s, Object... args) throws Exception{
1466 Writer w;
1467 if(o == null)
1468 w = new StringWriter();
1469 else if(Util.equals(o, T))
1470 w = (Writer) OUT.deref();
1471 else
1472 w = (Writer) o;
1473 doFormat(w, s, ArraySeq.create(args));
1474 if(o == null)
1475 return w.toString();
1476 return null;
1477 }
1478
1479 static public ISeq doFormat(Writer w, String s, ISeq args) throws Exception{
1480 for(int i = 0; i < s.length();) {
1481 char c = s.charAt(i++);
1482 switch(Character.toLowerCase(c)) {
1483 case '~':
1484 char d = s.charAt(i++);
1485 switch(Character.toLowerCase(d)) {
1486 case '%':
1487 w.write('\n');
1488 break;
1489 case 't':
1490 w.write('\t');
1491 break;
1492 case 'a':
1493 if(args == null)
1494 throw new IllegalArgumentException("Missing argument");
1495 RT.formatAesthetic(w, RT.first(args));
1496 args = RT.next(args);
1497 break;
1498 case 's':
1499 if(args == null)
1500 throw new IllegalArgumentException("Missing argument");
1501 RT.formatStandard(w, RT.first(args));
1502 args = RT.next(args);
1503 break;
1504 case '{':
1505 int j = s.indexOf("~}", i); //note - does not nest
1506 if(j == -1)
1507 throw new IllegalArgumentException("Missing ~}");
1508 String subs = s.substring(i, j);
1509 for(ISeq sargs = RT.seq(RT.first(args)); sargs != null;)
1510 sargs = doFormat(w, subs, sargs);
1511 args = RT.next(args);
1512 i = j + 2; //skip ~}
1513 break;
1514 case '^':
1515 if(args == null)
1516 return null;
1517 break;
1518 case '~':
1519 w.write('~');
1520 break;
1521 default:
1522 throw new IllegalArgumentException("Unsupported ~ directive: " + d);
1523 }
1524 break;
1525 default:
1526 w.write(c);
1527 }
1528 }
1529 return args;
1530 }
1531 ///////////////////////////////// values //////////////////////////
1532
1533 static public Object[] setValues(Object... vals){
1534 //ThreadLocalData.setValues(vals);
1535 if(vals.length > 0)
1536 return vals;//[0];
1537 return null;
1538 }
1539
1540
1541 static public ClassLoader makeClassLoader(){
1542 return (ClassLoader) AccessController.doPrivileged(new PrivilegedAction(){
1543 public Object run(){
1544 try{
1545 Var.pushThreadBindings(RT.map(USE_CONTEXT_CLASSLOADER, RT.T));
1546 // getRootClassLoader();
1547 return new DynamicClassLoader(baseLoader());
1548 }
1549 finally{
1550 Var.popThreadBindings();
1551 }
1552 }
1553 });
1554 }
1555
1556 static public ClassLoader baseLoader(){
1557 if(Compiler.LOADER.isBound())
1558 return (ClassLoader) Compiler.LOADER.deref();
1559 else if(booleanCast(USE_CONTEXT_CLASSLOADER.deref()))
1560 return Thread.currentThread().getContextClassLoader();
1561 return Compiler.class.getClassLoader();
1562 }
1563
1564 static public Class classForName(String name) throws ClassNotFoundException{
1565
1566 return Class.forName(name, true, baseLoader());
1567 }
1568
1569 static public Class loadClassForName(String name) throws ClassNotFoundException{
1570 try
1571 {
1572 Class.forName(name, false, baseLoader());
1573 }
1574 catch(ClassNotFoundException e)
1575 {
1576 return null;
1577 }
1578 return Class.forName(name, true, baseLoader());
1579 }
1580
1581 static public float aget(float[] xs, int i){
1582 return xs[i];
1583 }
1584
1585 static public float aset(float[] xs, int i, float v){
1586 xs[i] = v;
1587 return v;
1588 }
1589
1590 static public int alength(float[] xs){
1591 return xs.length;
1592 }
1593
1594 static public float[] aclone(float[] xs){
1595 return xs.clone();
1596 }
1597
1598 static public double aget(double[] xs, int i){
1599 return xs[i];
1600 }
1601
1602 static public double aset(double[] xs, int i, double v){
1603 xs[i] = v;
1604 return v;
1605 }
1606
1607 static public int alength(double[] xs){
1608 return xs.length;
1609 }
1610
1611 static public double[] aclone(double[] xs){
1612 return xs.clone();
1613 }
1614
1615 static public int aget(int[] xs, int i){
1616 return xs[i];
1617 }
1618
1619 static public int aset(int[] xs, int i, int v){
1620 xs[i] = v;
1621 return v;
1622 }
1623
1624 static public int alength(int[] xs){
1625 return xs.length;
1626 }
1627
1628 static public int[] aclone(int[] xs){
1629 return xs.clone();
1630 }
1631
1632 static public long aget(long[] xs, int i){
1633 return xs[i];
1634 }
1635
1636 static public long aset(long[] xs, int i, long v){
1637 xs[i] = v;
1638 return v;
1639 }
1640
1641 static public int alength(long[] xs){
1642 return xs.length;
1643 }
1644
1645 static public long[] aclone(long[] xs){
1646 return xs.clone();
1647 }
1648
1649 static public char aget(char[] xs, int i){
1650 return xs[i];
1651 }
1652
1653 static public char aset(char[] xs, int i, char v){
1654 xs[i] = v;
1655 return v;
1656 }
1657
1658 static public int alength(char[] xs){
1659 return xs.length;
1660 }
1661
1662 static public char[] aclone(char[] xs){
1663 return xs.clone();
1664 }
1665
1666 static public byte aget(byte[] xs, int i){
1667 return xs[i];
1668 }
1669
1670 static public byte aset(byte[] xs, int i, byte v){
1671 xs[i] = v;
1672 return v;
1673 }
1674
1675 static public int alength(byte[] xs){
1676 return xs.length;
1677 }
1678
1679 static public byte[] aclone(byte[] xs){
1680 return xs.clone();
1681 }
1682
1683 static public short aget(short[] xs, int i){
1684 return xs[i];
1685 }
1686
1687 static public short aset(short[] xs, int i, short v){
1688 xs[i] = v;
1689 return v;
1690 }
1691
1692 static public int alength(short[] xs){
1693 return xs.length;
1694 }
1695
1696 static public short[] aclone(short[] xs){
1697 return xs.clone();
1698 }
1699
1700 static public boolean aget(boolean[] xs, int i){
1701 return xs[i];
1702 }
1703
1704 static public boolean aset(boolean[] xs, int i, boolean v){
1705 xs[i] = v;
1706 return v;
1707 }
1708
1709 static public int alength(boolean[] xs){
1710 return xs.length;
1711 }
1712
1713 static public boolean[] aclone(boolean[] xs){
1714 return xs.clone();
1715 }
1716
1717 static public Object aget(Object[] xs, int i){
1718 return xs[i];
1719 }
1720
1721 static public Object aset(Object[] xs, int i, Object v){
1722 xs[i] = v;
1723 return v;
1724 }
1725
1726 static public int alength(Object[] xs){
1727 return xs.length;
1728 }
1729
1730 static public Object[] aclone(Object[] xs){
1731 return xs.clone();
1732 }
1733
1734
1735 }