Import upstream version 1.11.1+git20221207.1.527b330+ds
Debian Janitor
1 year, 4 months ago
0 | Hi! This project does not accept pull requests. | |
1 | ||
2 | Please see the guidelines for contribution on how to file issues or provide patches: | |
3 | ||
4 | https://github.com/clojure/clojure/blob/master/CONTRIBUTING.md |
0 | *.jar | |
1 | target | |
2 | clojure.iws | |
3 | clojure.ipr | |
4 | nbproject/private/ | |
5 | maven-classpath | |
6 | maven-classpath.properties | |
7 | .idea/ | |
8 | *.iml |
4 | 4 | <artifactId>clojure</artifactId> |
5 | 5 | <name>clojure</name> |
6 | 6 | <packaging>jar</packaging> |
7 | <version>1.11.1</version> | |
7 | <version>1.12.0-master-SNAPSHOT</version> | |
8 | 8 | |
9 | 9 | <url>http://clojure.org/</url> |
10 | 10 | <description>Clojure core environment and runtime library.</description> |
29 | 29 | <connection>scm:git:git@github.com:clojure/clojure.git</connection> |
30 | 30 | <developerConnection>scm:git:git@github.com:clojure/clojure.git</developerConnection> |
31 | 31 | <url>git@github.com:clojure/clojure.git</url> |
32 | <tag>clojure-1.11.1</tag> | |
32 | <tag>HEAD</tag> | |
33 | 33 | </scm> |
34 | 34 | |
35 | 35 | <properties> |
2923 | 2923 | (cons (first s) (take-while pred (rest s)))))))) |
2924 | 2924 | |
2925 | 2925 | (defn drop |
2926 | "Returns a lazy sequence of all but the first n items in coll. | |
2926 | "Returns a laziness-preserving sequence of all but the first n items in coll. | |
2927 | 2927 | Returns a stateful transducer when no collection is provided." |
2928 | 2928 | {:added "1.0" |
2929 | 2929 | :static true} |
2940 | 2940 | result |
2941 | 2941 | (rf result input)))))))) |
2942 | 2942 | ([n coll] |
2943 | (let [step (fn [n coll] | |
2944 | (let [s (seq coll)] | |
2945 | (if (and (pos? n) s) | |
2946 | (recur (dec n) (rest s)) | |
2947 | s)))] | |
2948 | (lazy-seq (step n coll))))) | |
2943 | (if (instance? clojure.lang.IDrop coll) | |
2944 | (or (.drop ^clojure.lang.IDrop coll n) ()) | |
2945 | (let [step (fn [n coll] | |
2946 | (let [s (seq coll)] | |
2947 | (if (and (pos? n) s) | |
2948 | (recur (dec n) (rest s)) | |
2949 | s)))] | |
2950 | (lazy-seq (step n coll)))))) | |
2949 | 2951 | |
2950 | 2952 | (defn drop-last |
2951 | 2953 | "Return a lazy sequence of all but the last n (default 1) items in coll" |
3166 | 3168 | {:added "1.0" |
3167 | 3169 | :static true} |
3168 | 3170 | [coll n] |
3171 | (if (instance? clojure.lang.IDrop coll) | |
3172 | (.drop ^clojure.lang.IDrop coll n) | |
3169 | 3173 | (loop [n n xs (seq coll)] |
3170 | 3174 | (if (and xs (pos? n)) |
3171 | 3175 | (recur (dec n) (next xs)) |
3172 | xs))) | |
3176 | xs)))) | |
3173 | 3177 | |
3174 | 3178 | (defn nthrest |
3175 | 3179 | "Returns the nth rest of coll, coll when n is 0." |
3176 | 3180 | {:added "1.3" |
3177 | 3181 | :static true} |
3178 | 3182 | [coll n] |
3183 | (if (instance? clojure.lang.IDrop coll) | |
3184 | (or (.drop ^clojure.lang.IDrop coll n) ()) | |
3179 | 3185 | (loop [n n xs coll] |
3180 | 3186 | (if-let [xs (and (pos? n) (seq xs))] |
3181 | 3187 | (recur (dec n) (rest xs)) |
3182 | xs))) | |
3188 | xs)))) | |
3183 | 3189 | |
3184 | 3190 | (defn partition |
3185 | 3191 | "Returns a lazy sequence of lists of n items each, at offsets step |
6237 | 6243 | ([m k f x y z & more] |
6238 | 6244 | (assoc m k (apply f (get m k) x y z more)))) |
6239 | 6245 | |
6240 | (defn empty? | |
6241 | "Returns true if coll has no items - same as (not (seq coll)). | |
6242 | Please use the idiom (seq x) rather than (not (empty? x))" | |
6243 | {:added "1.0" | |
6244 | :static true} | |
6245 | [coll] (not (seq coll))) | |
6246 | ||
6247 | 6246 | (defn coll? |
6248 | 6247 | "Returns true if x implements IPersistentCollection" |
6249 | 6248 | {:added "1.0" |
6298 | 6297 | {:added "1.0" |
6299 | 6298 | :static true} |
6300 | 6299 | [coll] (instance? clojure.lang.Counted coll)) |
6300 | ||
6301 | (defn empty? | |
6302 | "Returns true if coll has no items. To check the emptiness of a seq, | |
6303 | please use the idiom (seq x) rather than (not (empty? x))" | |
6304 | {:added "1.0" | |
6305 | :static true} | |
6306 | [coll] | |
6307 | (if (counted? coll) | |
6308 | (zero? (count coll)) | |
6309 | (not (seq coll)))) | |
6301 | 6310 | |
6302 | 6311 | (defn reversible? |
6303 | 6312 | "Returns true if coll implements Reversible" |
7337 | 7346 | (when-let [s (seq coll)] |
7338 | 7347 | (let [seg (doall (take n s))] |
7339 | 7348 | (cons seg (partition-all n step (nthrest s step)))))))) |
7349 | ||
7350 | (defn splitv-at | |
7351 | "Returns a vector of [(into [] (take n) coll) (drop n coll)]" | |
7352 | {:added "1.12"} | |
7353 | [n coll] | |
7354 | [(into [] (take n) coll) (drop n coll)]) | |
7355 | ||
7356 | (defn partitionv | |
7357 | "Returns a lazy sequence of vectors of n items each, at offsets step | |
7358 | apart. If step is not supplied, defaults to n, i.e. the partitions | |
7359 | do not overlap. If a pad collection is supplied, use its elements as | |
7360 | necessary to complete last partition upto n items. In case there are | |
7361 | not enough padding elements, return a partition with less than n items." | |
7362 | {:added "1.12"} | |
7363 | ([n coll] | |
7364 | (partitionv n n coll)) | |
7365 | ([n step coll] | |
7366 | (lazy-seq | |
7367 | (when-let [s (seq coll)] | |
7368 | (let [p (into [] (take n) s)] | |
7369 | (when (= n (count p)) | |
7370 | (cons p (partitionv n step (nthrest s step)))))))) | |
7371 | ([n step pad coll] | |
7372 | (lazy-seq | |
7373 | (when-let [s (seq coll)] | |
7374 | (let [p (into [] (take n) s)] | |
7375 | (if (= n (count p)) | |
7376 | (cons p (partitionv n step pad (nthrest s step))) | |
7377 | (list (into [] (take n) (concat p pad))))))))) | |
7378 | ||
7379 | (defn partitionv-all | |
7380 | "Returns a lazy sequence of vector partitions, but may include | |
7381 | partitions with fewer than n items at the end. | |
7382 | Returns a stateful transducer when no collection is provided." | |
7383 | {:added "1.12"} | |
7384 | ([n] | |
7385 | (partition-all n)) | |
7386 | ([n coll] | |
7387 | (partitionv-all n n coll)) | |
7388 | ([n step coll] | |
7389 | (lazy-seq | |
7390 | (when-let [s (seq coll)] | |
7391 | (let [seg (into [] (take n) coll)] | |
7392 | (cons seg (partitionv-all n step (drop step s)))))))) | |
7340 | 7393 | |
7341 | 7394 | (defn shuffle |
7342 | 7395 | "Return a random permutation of coll" |
15 | 15 | import java.util.Comparator; |
16 | 16 | |
17 | 17 | public abstract class AFunction extends AFn implements IObj, Comparator, Fn, Serializable { |
18 | ||
19 | private static final long serialVersionUID = 4469383498184457675L; | |
18 | 20 | |
19 | 21 | public volatile MethodImplCache __methodImplCache; |
20 | 22 |
14 | 14 | import java.io.StringWriter; |
15 | 15 | |
16 | 16 | public abstract class AMapEntry extends APersistentVector implements IMapEntry{ |
17 | ||
18 | private static final long serialVersionUID = -5007980429903443802L; | |
17 | 19 | |
18 | 20 | public Object nth(int i){ |
19 | 21 | if(i == 0) |
13 | 13 | import java.util.*; |
14 | 14 | |
15 | 15 | public abstract class APersistentMap extends AFn implements IPersistentMap, Map, Iterable, Serializable, MapEquivalence, IHashEq { |
16 | ||
17 | private static final long serialVersionUID = 6736310834519110267L; | |
18 | ||
16 | 19 | int _hash; |
17 | 20 | int _hasheq; |
18 | 21 |
17 | 17 | import java.util.Set; |
18 | 18 | |
19 | 19 | public abstract class APersistentSet extends AFn implements IPersistentSet, Collection, Set, Serializable, IHashEq { |
20 | ||
21 | private static final long serialVersionUID = 889908853183699706L; | |
22 | ||
20 | 23 | int _hash; |
21 | 24 | int _hasheq; |
22 | 25 | final IPersistentMap impl; |
18 | 18 | List, |
19 | 19 | RandomAccess, Comparable, |
20 | 20 | Serializable, IHashEq { |
21 | ||
22 | private static final long serialVersionUID = 4667575149454420891L; | |
23 | ||
21 | 24 | int _hash; |
22 | 25 | int _hasheq; |
23 | 26 |
13 | 13 | import java.util.*; |
14 | 14 | |
15 | 15 | public abstract class ASeq extends Obj implements ISeq, Sequential, List, Serializable, IHashEq { |
16 | ||
17 | private static final long serialVersionUID = 4748650717905139299L; | |
18 | ||
16 | 19 | transient int _hash; |
17 | 20 | transient int _hasheq; |
18 | 21 |
14 | 14 | */ |
15 | 15 | public class ArityException extends IllegalArgumentException { |
16 | 16 | |
17 | private static final long serialVersionUID = 2265783180488869950L; | |
18 | ||
17 | 19 | final public int actual; |
18 | 20 | |
19 | 21 | final public String name; |
14 | 14 | import java.io.Serializable; |
15 | 15 | |
16 | 16 | public final class ArrayChunk implements IChunk, Serializable { |
17 | ||
18 | private static final long serialVersionUID = -8302142882294545702L; | |
17 | 19 | |
18 | 20 | final Object[] array; |
19 | 21 | final int off; |
15 | 15 | import java.math.BigDecimal; |
16 | 16 | |
17 | 17 | public final class BigInt extends Number implements IHashEq{ |
18 | ||
19 | private static final long serialVersionUID = 5097771279236135022L; | |
18 | 20 | |
19 | 21 | final public long lpart; |
20 | 22 | final public BigInteger bipart; |
12 | 12 | package clojure.lang; |
13 | 13 | |
14 | 14 | final public class ChunkedCons extends ASeq implements IChunkedSeq{ |
15 | ||
16 | private static final long serialVersionUID = 2773920188566401743L; | |
15 | 17 | |
16 | 18 | final IChunk chunk; |
17 | 19 | final ISeq _more; |
409 | 409 | public final Expr meta; |
410 | 410 | public final boolean initProvided; |
411 | 411 | public final boolean isDynamic; |
412 | public final boolean shadowsCoreMapping; | |
413 | 412 | public final String source; |
414 | 413 | public final int line; |
415 | 414 | public final int column; |
418 | 417 | final static Method setMetaMethod = Method.getMethod("void setMeta(clojure.lang.IPersistentMap)"); |
419 | 418 | final static Method setDynamicMethod = Method.getMethod("clojure.lang.Var setDynamic(boolean)"); |
420 | 419 | final static Method symintern = Method.getMethod("clojure.lang.Symbol intern(String, String)"); |
421 | final static Method internVar = Method.getMethod("clojure.lang.Var refer(clojure.lang.Symbol, clojure.lang.Var)"); | |
422 | ||
423 | public DefExpr(String source, int line, int column, Var var, Expr init, Expr meta, boolean initProvided, boolean isDynamic, boolean shadowsCoreMapping){ | |
420 | ||
421 | public DefExpr(String source, int line, int column, Var var, Expr init, Expr meta, boolean initProvided, boolean isDynamic){ | |
424 | 422 | this.source = source; |
425 | 423 | this.line = line; |
426 | 424 | this.column = column; |
428 | 426 | this.init = init; |
429 | 427 | this.meta = meta; |
430 | 428 | this.isDynamic = isDynamic; |
431 | this.shadowsCoreMapping = shadowsCoreMapping; | |
432 | 429 | this.initProvided = initProvided; |
433 | 430 | } |
434 | 431 | |
474 | 471 | |
475 | 472 | public void emit(C context, ObjExpr objx, GeneratorAdapter gen){ |
476 | 473 | objx.emitVar(gen, var); |
477 | ||
478 | if (shadowsCoreMapping) | |
479 | { | |
480 | gen.dup(); | |
481 | gen.getField(VAR_TYPE, "ns", NS_TYPE); | |
482 | gen.swap(); | |
483 | gen.dup(); | |
484 | gen.getField(VAR_TYPE, "sym", SYMBOL_TYPE); | |
485 | gen.swap(); | |
486 | gen.invokeVirtual(NS_TYPE, internVar); | |
487 | } | |
488 | ||
489 | 474 | if(isDynamic) |
490 | 475 | { |
491 | 476 | gen.push(isDynamic); |
543 | 528 | Var v = lookupVar(sym, true); |
544 | 529 | if(v == null) |
545 | 530 | throw Util.runtimeException("Can't refer to qualified var that doesn't exist"); |
546 | boolean shadowsCoreMapping = false; | |
547 | 531 | if(!v.ns.equals(currentNS())) |
548 | 532 | { |
549 | 533 | if(sym.ns == null) |
550 | 534 | { |
551 | 535 | v = currentNS().intern(sym); |
552 | shadowsCoreMapping = true; | |
553 | 536 | registerVar(v); |
554 | 537 | } |
555 | 538 | // throw Util.runtimeException("Name conflict, can't def " + sym + " because namespace: " + currentNS().name + |
593 | 576 | Expr meta = mm.count()==0 ? null:analyze(context == C.EVAL ? context : C.EXPRESSION, mm); |
594 | 577 | return new DefExpr((String) SOURCE.deref(), lineDeref(), columnDeref(), |
595 | 578 | v, analyze(context == C.EVAL ? context : C.EXPRESSION, RT.third(form), v.sym.name), |
596 | meta, RT.count(form) == 3, isDynamic, shadowsCoreMapping); | |
579 | meta, RT.count(form) == 3, isDynamic); | |
597 | 580 | } |
598 | 581 | } |
599 | 582 | } |
14 | 14 | import java.io.Serializable; |
15 | 15 | |
16 | 16 | final public class Cons extends ASeq implements Serializable { |
17 | ||
18 | private static final long serialVersionUID = 6682587018567831263L; | |
17 | 19 | |
18 | 20 | private final Object _first; |
19 | 21 | private final ISeq _more; |
12 | 12 | /* Alex Miller, Dec 5, 2014 */ |
13 | 13 | |
14 | 14 | public class Cycle extends ASeq implements IReduce, IPending { |
15 | ||
16 | private static final long serialVersionUID = 4007270937279943908L; | |
15 | 17 | |
16 | 18 | private final ISeq all; // never null |
17 | 19 | private final ISeq prev; |
16 | 16 | import java.util.Enumeration; |
17 | 17 | |
18 | 18 | public class EnumerationSeq extends ASeq{ |
19 | ||
20 | private static final long serialVersionUID = 5227192199685595994L; | |
21 | ||
19 | 22 | final Enumeration iter; |
20 | 23 | final State state; |
21 | 24 |
15 | 15 | * exception classes. |
16 | 16 | */ |
17 | 17 | public class ExceptionInfo extends RuntimeException implements IExceptionInfo { |
18 | ||
19 | private static final long serialVersionUID = -1073473305916521986L; | |
20 | ||
18 | 21 | public final IPersistentMap data; |
19 | 22 | |
20 | 23 | public ExceptionInfo(String s, IPersistentMap data) { |
12 | 12 | package clojure.lang; |
13 | 13 | |
14 | 14 | public class FnLoaderThunk extends RestFn{ |
15 | ||
16 | private static final long serialVersionUID = 2194257205455463687L; | |
15 | 17 | |
16 | 18 | final Var v; |
17 | 19 | final ClassLoader loader; |
0 | /** | |
1 | * Copyright (c) Rich Hickey. All rights reserved. | |
2 | * The use and distribution terms for this software are covered by the | |
3 | * Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) | |
4 | * which can be found in the file epl-v10.html at the root of this distribution. | |
5 | * By using this software in any fashion, you are agreeing to be bound by | |
6 | * the terms of this license. | |
7 | * You must not remove this notice, or any other, from this software. | |
8 | **/ | |
9 | ||
10 | package clojure.lang; | |
11 | ||
12 | /** | |
13 | * Persistent or algorithmically defined collections can implement IDrop to provide | |
14 | * a means of dropping N items that is more efficient than sequential walking. | |
15 | */ | |
16 | public interface IDrop{ | |
17 | /** | |
18 | * Returns a collection that is Sequential, ISeq, and IReduceInit. It is also | |
19 | * useful if the returned coll implements IDrop for subsequent use in a | |
20 | * partition-like scenario. | |
21 | * | |
22 | * If n is <= 0, return this. | |
23 | * If n drops to or past the end of the collection, return null. | |
24 | * | |
25 | * @param n Items to drop | |
26 | * @return Collection that is Sequential, ISeq, and IReduceInit | |
27 | */ | |
28 | Sequential drop(int n); | |
29 | } |
12 | 12 | /* Alex Miller, Dec 5, 2014 */ |
13 | 13 | |
14 | 14 | public class Iterate extends ASeq implements IReduce, IPending { |
15 | ||
16 | private static final long serialVersionUID = -78221705247226450L; | |
15 | 17 | |
16 | 18 | private static final Object UNREALIZED_SEED = new Object(); |
17 | 19 | private final IFn f; // never null |
14 | 14 | import java.util.Iterator; |
15 | 15 | |
16 | 16 | public class IteratorSeq extends ASeq{ |
17 | ||
18 | private static final long serialVersionUID = -2631916503522522760L; | |
19 | ||
17 | 20 | final Iterator iter; |
18 | 21 | final State state; |
19 | 22 |
15 | 15 | |
16 | 16 | public final class LazySeq extends Obj implements ISeq, Sequential, List, IPending, IHashEq{ |
17 | 17 | |
18 | private static final long serialVersionUID = 7700080124382322592L; | |
19 | ||
18 | 20 | private IFn fn; |
19 | 21 | private Object sv; |
20 | 22 | private ISeq s; |
15 | 15 | import java.util.NoSuchElementException; |
16 | 16 | |
17 | 17 | /** |
18 | * Implements the special common case of a finite range based on long start, end, and step. | |
18 | * Implements the special common case of a finite range based on long start, end, and step, | |
19 | * with no more than Integer.MAX_VALUE items. | |
19 | 20 | */ |
20 | public class LongRange extends ASeq implements Counted, IChunkedSeq, IReduce { | |
21 | ||
22 | private static final int CHUNK_SIZE = 32; | |
21 | public class LongRange extends ASeq implements Counted, IChunkedSeq, IReduce, IDrop { | |
22 | ||
23 | private static final long serialVersionUID = -1467242400566893909L; | |
23 | 24 | |
24 | 25 | // Invariants guarantee this is never an empty or infinite seq |
25 | 26 | // assert(start != end && step != 0) |
26 | 27 | final long start; |
27 | 28 | final long end; |
28 | 29 | final long step; |
29 | final BoundsCheck boundsCheck; | |
30 | private volatile LongChunk _chunk; // lazy | |
31 | private volatile ISeq _chunkNext; // lazy | |
32 | private volatile ISeq _next; // cached | |
33 | ||
34 | private static interface BoundsCheck extends Serializable { | |
35 | boolean exceededBounds(long val); | |
36 | } | |
37 | ||
38 | private static BoundsCheck positiveStep(final long end) { | |
39 | return new BoundsCheck() { | |
40 | public boolean exceededBounds(long val){ | |
41 | return (val >= end); | |
42 | } | |
43 | }; | |
44 | } | |
45 | ||
46 | private static BoundsCheck negativeStep(final long end) { | |
47 | return new BoundsCheck() { | |
48 | public boolean exceededBounds(long val){ | |
49 | return (val <= end); | |
50 | } | |
51 | }; | |
52 | } | |
53 | ||
54 | private LongRange(long start, long end, long step, BoundsCheck boundsCheck){ | |
30 | final int count; | |
31 | ||
32 | private LongRange(long start, long end, long step, int count){ | |
55 | 33 | this.start = start; |
56 | 34 | this.end = end; |
57 | 35 | this.step = step; |
58 | this.boundsCheck = boundsCheck; | |
59 | } | |
60 | ||
61 | private LongRange(long start, long end, long step, BoundsCheck boundsCheck, LongChunk chunk, ISeq chunkNext){ | |
62 | this.start = start; | |
63 | this.end = end; | |
64 | this.step = step; | |
65 | this.boundsCheck = boundsCheck; | |
66 | this._chunk = chunk; | |
67 | this._chunkNext = chunkNext; | |
68 | } | |
69 | ||
70 | private LongRange(IPersistentMap meta, long start, long end, long step, BoundsCheck boundsCheck, LongChunk chunk, ISeq chunkNext){ | |
36 | this.count = count; | |
37 | } | |
38 | ||
39 | private LongRange(IPersistentMap meta, long start, long end, long step, int count){ | |
71 | 40 | super(meta); |
72 | 41 | this.start = start; |
73 | 42 | this.end = end; |
74 | 43 | this.step = step; |
75 | this.boundsCheck = boundsCheck; | |
76 | this._chunk = chunk; | |
77 | this._chunkNext = chunkNext; | |
44 | this.count = count; | |
45 | } | |
46 | ||
47 | // returns exact size of remaining items OR throws ArithmeticException for overflow case | |
48 | static long rangeCount(long start, long end, long step) { | |
49 | // (1) count = ceiling ( (end - start) / step ) | |
50 | // (2) ceiling(a/b) = (a+b+o)/b where o=-1 for positive stepping and +1 for negative stepping | |
51 | // thus: count = end - start + step + o / step | |
52 | return Numbers.add(Numbers.add(Numbers.minus(end, start), step), step > 0 ? -1 : 1) / step; | |
78 | 53 | } |
79 | 54 | |
80 | 55 | public static ISeq create(long end) { |
81 | if(end > 0) | |
82 | return new LongRange(0L, end, 1L, positiveStep(end)); | |
83 | return PersistentList.EMPTY; | |
56 | if(end > 0) { | |
57 | try { | |
58 | return new LongRange(0L, end, 1L, Math.toIntExact(rangeCount(0L, end, 1L))); | |
59 | } catch(ArithmeticException e) { | |
60 | return Range.create(end); // count > Integer.MAX_VALUE | |
61 | } | |
62 | } else { | |
63 | return PersistentList.EMPTY; | |
64 | } | |
84 | 65 | } |
85 | 66 | |
86 | 67 | public static ISeq create(long start, long end) { |
87 | if(start >= end) | |
68 | if(start >= end) { | |
88 | 69 | return PersistentList.EMPTY; |
89 | return new LongRange(start, end, 1L, positiveStep(end)); | |
70 | } else { | |
71 | try { | |
72 | return new LongRange(start, end, 1L, Math.toIntExact(rangeCount(start, end, 1L))); | |
73 | } catch(ArithmeticException e) { | |
74 | return Range.create(start, end); | |
75 | } | |
76 | } | |
90 | 77 | } |
91 | 78 | |
92 | 79 | public static ISeq create(final long start, long end, long step) { |
93 | 80 | if(step > 0) { |
94 | 81 | if(end <= start) return PersistentList.EMPTY; |
95 | return new LongRange(start, end, step, positiveStep(end)); | |
82 | try { | |
83 | return new LongRange(start, end, step, Math.toIntExact(rangeCount(start, end, step))); | |
84 | } catch(ArithmeticException e) { | |
85 | return Range.create(start, end, step); | |
86 | } | |
96 | 87 | } else if(step < 0) { |
97 | 88 | if(end >= start) return PersistentList.EMPTY; |
98 | return new LongRange(start, end, step, negativeStep(end)); | |
89 | try { | |
90 | return new LongRange(start, end, step, Math.toIntExact(rangeCount(start, end, step))); | |
91 | } catch(ArithmeticException e) { | |
92 | return Range.create(start, end, step); | |
93 | } | |
99 | 94 | } else { |
100 | 95 | if(end == start) return PersistentList.EMPTY; |
101 | 96 | return Repeat.create(start); |
105 | 100 | public Obj withMeta(IPersistentMap meta){ |
106 | 101 | if(meta == _meta) |
107 | 102 | return this; |
108 | return new LongRange(meta, start, end, step, boundsCheck, _chunk, _chunkNext); | |
103 | return new LongRange(meta, start, end, step, count); | |
109 | 104 | } |
110 | 105 | |
111 | 106 | public Object first() { |
112 | 107 | return start; |
113 | 108 | } |
114 | 109 | |
115 | public void forceChunk() { | |
116 | if(_chunk != null) return; | |
117 | ||
118 | long count; | |
119 | try { | |
120 | count = rangeCount(start, end, step); | |
121 | } catch(ArithmeticException e) { | |
122 | // size of total range is > Long.MAX_VALUE so must step to count | |
123 | // this only happens in pathological range cases like: | |
124 | // (range -9223372036854775808 9223372036854775807 9223372036854775807) | |
125 | count = steppingCount(start, end, step); | |
126 | } | |
127 | ||
128 | if (count > CHUNK_SIZE) { // not last chunk | |
129 | long nextStart = start + (step * CHUNK_SIZE); // cannot overflow, must be < end | |
130 | _chunkNext = new LongRange(nextStart, end, step, boundsCheck); | |
131 | _chunk = new LongChunk(start, step, CHUNK_SIZE); | |
132 | } else { // last chunk | |
133 | _chunk = new LongChunk(start, step, (int) count); // count must be <= CHUNK_SIZE | |
134 | } | |
135 | } | |
136 | ||
137 | 110 | public ISeq next() { |
138 | if(_next != null) | |
139 | return _next; | |
140 | ||
141 | forceChunk(); | |
142 | if(_chunk.count() > 1) { | |
143 | LongChunk smallerChunk = _chunk.dropFirst(); | |
144 | _next = new LongRange(smallerChunk.first(), end, step, boundsCheck, smallerChunk, _chunkNext); | |
145 | return _next; | |
146 | } | |
147 | return chunkedNext(); | |
111 | if(count > 1) { | |
112 | return new LongRange(start + step, end, step, count-1); | |
113 | } else { | |
114 | return null; | |
115 | } | |
148 | 116 | } |
149 | 117 | |
150 | 118 | public IChunk chunkedFirst() { |
151 | forceChunk(); | |
152 | return _chunk; | |
119 | return new LongChunk(start, step, count); | |
153 | 120 | } |
154 | 121 | |
155 | 122 | public ISeq chunkedNext() { |
156 | return chunkedMore().seq(); | |
123 | return null; | |
157 | 124 | } |
158 | 125 | |
159 | 126 | public ISeq chunkedMore() { |
160 | forceChunk(); | |
161 | if(_chunkNext == null) | |
162 | return PersistentList.EMPTY; | |
163 | return _chunkNext; | |
164 | } | |
165 | ||
166 | // fallback count mechanism for pathological cases | |
167 | // returns either exact count or CHUNK_SIZE+1 | |
168 | long steppingCount(long start, long end, long step) { | |
169 | long count = 1; | |
170 | long s = start; | |
171 | while(count <= CHUNK_SIZE) { | |
172 | try { | |
173 | s = Numbers.add(s, step); | |
174 | if(boundsCheck.exceededBounds(s)) | |
175 | break; | |
176 | else | |
177 | count++; | |
178 | } catch(ArithmeticException e) { | |
179 | break; | |
180 | } | |
181 | } | |
127 | return PersistentList.EMPTY; | |
128 | } | |
129 | ||
130 | public Sequential drop(int n) { | |
131 | if(n <= 0) { | |
132 | return this; | |
133 | } else if(n < count) { | |
134 | return new LongRange(start+(step*n), end, step, count - n); | |
135 | } else { | |
136 | return null; | |
137 | } | |
138 | } | |
139 | ||
140 | public int count() { | |
182 | 141 | return count; |
183 | } | |
184 | ||
185 | // returns exact size of remaining items OR throws ArithmeticException for overflow case | |
186 | long rangeCount(long start, long end, long step) { | |
187 | // (1) count = ceiling ( (end - start) / step ) | |
188 | // (2) ceiling(a/b) = (a+b+o)/b where o=-1 for positive stepping and +1 for negative stepping | |
189 | // thus: count = end - start + step + o / step | |
190 | return Numbers.add(Numbers.add(Numbers.minus(end, start), step), this.step > 0 ? -1 : 1) / step; | |
191 | } | |
192 | ||
193 | public int count() { | |
194 | try { | |
195 | long c = rangeCount(start, end, step); | |
196 | if(c > Integer.MAX_VALUE) { | |
197 | return Numbers.throwIntOverflow(); | |
198 | } else { | |
199 | return (int) c; | |
200 | } | |
201 | } catch(ArithmeticException e) { | |
202 | // rare case from large range or step, fall back to iterating and counting | |
203 | Iterator iter = this.iterator(); | |
204 | long count = 0; | |
205 | while(iter.hasNext()) { | |
206 | iter.next(); | |
207 | count++; | |
208 | } | |
209 | ||
210 | if(count > Integer.MAX_VALUE) | |
211 | return Numbers.throwIntOverflow(); | |
212 | else | |
213 | return (int)count; | |
214 | } | |
215 | 142 | } |
216 | 143 | |
217 | 144 | public Object reduce(IFn f) { |
218 | 145 | Object acc = start; |
219 | 146 | long i = start + step; |
220 | while(! boundsCheck.exceededBounds(i)) { | |
147 | int n = count; | |
148 | while(n > 1) { | |
221 | 149 | acc = f.invoke(acc, i); |
222 | 150 | if (acc instanceof Reduced) return ((Reduced)acc).deref(); |
223 | 151 | i += step; |
152 | n--; | |
224 | 153 | } |
225 | 154 | return acc; |
226 | 155 | } |
227 | 156 | |
228 | 157 | public Object reduce(IFn f, Object val) { |
229 | 158 | Object acc = val; |
159 | int n = count; | |
230 | 160 | long i = start; |
231 | 161 | do { |
232 | 162 | acc = f.invoke(acc, i); |
233 | 163 | if (RT.isReduced(acc)) return ((Reduced)acc).deref(); |
234 | 164 | i += step; |
235 | } while(! boundsCheck.exceededBounds(i)); | |
165 | n--; | |
166 | } while(n > 0); | |
236 | 167 | return acc; |
237 | 168 | } |
238 | 169 | |
242 | 173 | |
243 | 174 | class LongRangeIterator implements Iterator { |
244 | 175 | private long next; |
245 | private boolean hasNext; | |
176 | private int remaining; | |
246 | 177 | |
247 | 178 | public LongRangeIterator() { |
248 | 179 | this.next = start; |
249 | this.hasNext = true; | |
180 | this.remaining = count; | |
250 | 181 | } |
251 | 182 | |
252 | 183 | public boolean hasNext() { |
253 | return hasNext; | |
184 | return remaining > 0; | |
254 | 185 | } |
255 | 186 | |
256 | 187 | public Object next() { |
257 | if (hasNext) { | |
188 | if (remaining > 0) { | |
258 | 189 | long ret = next; |
259 | try { | |
260 | next = Numbers.add(next, step); | |
261 | hasNext = ! boundsCheck.exceededBounds(next); | |
262 | } catch(ArithmeticException e) { | |
263 | hasNext = false; | |
264 | } | |
190 | next = next + step; | |
191 | remaining = remaining - 1; | |
265 | 192 | return ret; |
266 | 193 | } else { |
267 | 194 | throw new NoSuchElementException(); |
321 | 248 | } |
322 | 249 | |
323 | 250 | } |
324 | }⏎ | |
251 | } |
12 | 12 | import java.util.Iterator; |
13 | 13 | |
14 | 14 | public class MapEntry extends AMapEntry{ |
15 | ||
16 | private static final long serialVersionUID = -3752414622414469244L; | |
17 | ||
15 | 18 | final Object _key; |
16 | 19 | final Object _val; |
17 | 20 |
17 | 17 | import java.util.concurrent.atomic.AtomicReference; |
18 | 18 | |
19 | 19 | public class Namespace extends AReference implements Serializable { |
20 | ||
21 | private static final long serialVersionUID = -3134444395801383865L; | |
22 | ||
20 | 23 | final public Symbol name; |
21 | 24 | transient final AtomicReference<IPersistentMap> mappings = new AtomicReference<IPersistentMap>(); |
22 | 25 | transient final AtomicReference<IPersistentMap> aliases = new AtomicReference<IPersistentMap>(); |
46 | 49 | return mappings.get(); |
47 | 50 | } |
48 | 51 | |
52 | /** | |
53 | * An interned mapping is one where a var's ns matches the current ns and its sym matches the mapping key. | |
54 | * Once established, interned mappings should never change. | |
55 | */ | |
56 | private boolean isInternedMapping(Symbol sym, Object o){ | |
57 | return(o instanceof Var && | |
58 | ((Var) o).ns == this && | |
59 | ((Var) o).sym.equals(sym)); | |
60 | } | |
61 | ||
49 | 62 | public Var intern(Symbol sym){ |
50 | 63 | if(sym.ns != null) |
51 | 64 | { |
52 | 65 | throw new IllegalArgumentException("Can't intern namespace-qualified symbol"); |
53 | 66 | } |
67 | ||
54 | 68 | IPersistentMap map = getMappings(); |
55 | 69 | Object o; |
56 | 70 | Var v = null; |
62 | 76 | mappings.compareAndSet(map, newMap); |
63 | 77 | map = getMappings(); |
64 | 78 | } |
65 | if(o instanceof Var && ((Var) o).ns == this) | |
79 | if(isInternedMapping(sym, o)) | |
66 | 80 | return (Var) o; |
67 | 81 | |
68 | 82 | if(v == null) |
69 | 83 | v = new Var(this, sym); |
70 | 84 | |
71 | warnOrFailOnReplace(sym, o, v); | |
72 | ||
73 | ||
74 | while(!mappings.compareAndSet(map, map.assoc(sym, v))) | |
75 | map = getMappings(); | |
76 | ||
77 | return v; | |
78 | } | |
79 | ||
80 | private void warnOrFailOnReplace(Symbol sym, Object o, Object v){ | |
81 | if (o instanceof Var) | |
82 | { | |
83 | Namespace ns = ((Var)o).ns; | |
84 | if (ns == this || (v instanceof Var && ((Var)v).ns == RT.CLOJURE_NS)) | |
85 | return; | |
86 | if (ns != RT.CLOJURE_NS) | |
87 | throw new IllegalStateException(sym + " already refers to: " + o + " in namespace: " + name); | |
88 | } | |
89 | RT.errPrintWriter().println("WARNING: " + sym + " already refers to: " + o + " in namespace: " + name | |
90 | + ", being replaced by: " + v); | |
85 | if(checkReplacement(sym, o, v)){ | |
86 | while (!mappings.compareAndSet(map, map.assoc(sym, v))) | |
87 | map = getMappings(); | |
88 | ||
89 | return v; | |
90 | } | |
91 | ||
92 | return (Var) o; | |
93 | } | |
94 | ||
95 | /* | |
96 | This method checks if a namespace's mapping is applicable and warns on problematic cases. | |
97 | It will return a boolean indicating if a mapping is replaceable. | |
98 | The semantics of what constitutes a legal replacement mapping is summarized as follows: | |
99 | ||
100 | | classification | in namespace ns | newval = anything other than ns/name | newval = ns/name | | |
101 | |----------------+------------------------+--------------------------------------+-------------------------------------| | |
102 | | native mapping | name -> ns/name | no replace, warn-if newval not-core | no replace, warn-if newval not-core | | |
103 | | alias mapping | name -> other/whatever | warn + replace | warn + replace | | |
104 | */ | |
105 | private boolean checkReplacement(Symbol sym, Object old, Object neu){ | |
106 | if(old instanceof Var) { | |
107 | Namespace ons = ((Var)old).ns; | |
108 | Namespace nns = neu instanceof Var ? ((Var) neu).ns : null; | |
109 | ||
110 | if(isInternedMapping(sym, old)){ | |
111 | if(nns != RT.CLOJURE_NS){ | |
112 | RT.errPrintWriter().println("REJECTED: attempt to replace interned var " | |
113 | + old + " with " + neu + " in " + name + ", you must ns-unmap first"); | |
114 | return false; | |
115 | } | |
116 | else | |
117 | return false; | |
118 | } | |
119 | } | |
120 | RT.errPrintWriter().println("WARNING: " + sym + " already refers to: " + old + " in namespace: " + name | |
121 | + ", being replaced by: " + neu); | |
122 | return true; | |
91 | 123 | } |
92 | 124 | |
93 | 125 | Object reference(Symbol sym, Object val){ |
95 | 127 | { |
96 | 128 | throw new IllegalArgumentException("Can't intern namespace-qualified symbol"); |
97 | 129 | } |
130 | ||
98 | 131 | IPersistentMap map = getMappings(); |
99 | 132 | Object o; |
100 | 133 | while((o = map.valAt(sym)) == null) |
106 | 139 | if(o == val) |
107 | 140 | return o; |
108 | 141 | |
109 | warnOrFailOnReplace(sym, o, val); | |
110 | ||
111 | while(!mappings.compareAndSet(map, map.assoc(sym, val))) | |
112 | map = getMappings(); | |
113 | ||
114 | return val; | |
115 | ||
142 | if(checkReplacement(sym, o, val)){ | |
143 | while (!mappings.compareAndSet(map, map.assoc(sym, val))) | |
144 | map = getMappings(); | |
145 | ||
146 | return val; | |
147 | } | |
148 | ||
149 | return o; | |
116 | 150 | } |
117 | 151 | |
118 | 152 | public static boolean areDifferentInstancesOfSameClassName(Class cls1, Class cls2) { |
15 | 15 | |
16 | 16 | public abstract class Obj implements IObj, Serializable { |
17 | 17 | |
18 | private static final long serialVersionUID = 802029099426284526L; | |
19 | ||
18 | 20 | final IPersistentMap _meta; |
19 | 21 | |
20 | 22 | public Obj(IPersistentMap meta){ |
26 | 26 | * <p>null keys and values are ok, but you won't be able to distinguish a null value via valAt - use contains/entryAt</p> |
27 | 27 | */ |
28 | 28 | |
29 | public class PersistentArrayMap extends APersistentMap implements IObj, IEditableCollection, IMapIterable, IKVReduce{ | |
29 | public class PersistentArrayMap extends APersistentMap implements IObj, IEditableCollection, IMapIterable, IKVReduce, IDrop{ | |
30 | ||
31 | private static final long serialVersionUID = -2074065891090893601L; | |
30 | 32 | |
31 | 33 | final Object[] array; |
32 | 34 | static final int HASHTABLE_THRESHOLD = 16; |
347 | 349 | return null; |
348 | 350 | } |
349 | 351 | |
352 | public Sequential drop(int n) { | |
353 | if(array.length > 0) { | |
354 | return ((Seq) seq()).drop(n); | |
355 | } else { | |
356 | return null; | |
357 | } | |
358 | } | |
359 | ||
350 | 360 | public IPersistentMap meta(){ |
351 | 361 | return _meta; |
352 | 362 | } |
353 | 363 | |
354 | static class Seq extends ASeq implements Counted{ | |
364 | static class Seq extends ASeq implements Counted, IReduce, IDrop { | |
355 | 365 | final Object[] array; |
356 | 366 | final int i; |
357 | 367 | |
380 | 390 | return (array.length - i) / 2; |
381 | 391 | } |
382 | 392 | |
393 | public Sequential drop(int n) { | |
394 | if(n < count()) { | |
395 | return new Seq(array, i + (2 * n)); | |
396 | } else { | |
397 | return null; | |
398 | } | |
399 | } | |
400 | ||
383 | 401 | public Obj withMeta(IPersistentMap meta){ |
384 | 402 | if(meta() == meta) |
385 | 403 | return this; |
386 | 404 | return new Seq(meta, array, i); |
387 | 405 | } |
406 | ||
407 | public Iterator iterator() { | |
408 | return new Iter(array, i-2, APersistentMap.MAKE_ENTRY); | |
409 | } | |
410 | ||
411 | public Object reduce(IFn f) { | |
412 | if(i < array.length) { | |
413 | Object acc = MapEntry.create(array[i], array[i+1]); | |
414 | for(int j=i+2;j < array.length;j+=2){ | |
415 | acc = f.invoke(acc, MapEntry.create(array[j], array[j+1])); | |
416 | if(RT.isReduced(acc)) | |
417 | return ((IDeref)acc).deref(); | |
418 | } | |
419 | return acc; | |
420 | } else { | |
421 | return f.invoke(); | |
422 | } | |
423 | } | |
424 | ||
425 | public Object reduce(IFn f, Object init) { | |
426 | Object acc = init; | |
427 | for(int j=i;j < array.length;j+=2){ | |
428 | acc = f.invoke(acc, MapEntry.create(array[j], array[j+1])); | |
429 | if(RT.isReduced(acc)) | |
430 | return ((IDeref)acc).deref(); | |
431 | } | |
432 | return acc; | |
433 | } | |
388 | 434 | } |
389 | 435 | |
390 | 436 | static class Iter implements Iterator{ |
391 | IFn f; | |
392 | Object[] array; | |
437 | final IFn f; | |
438 | final Object[] array; | |
393 | 439 | int i; |
394 | 440 | |
395 | 441 | //for iterator |
25 | 25 | */ |
26 | 26 | |
27 | 27 | public class PersistentHashMap extends APersistentMap implements IEditableCollection, IObj, IMapIterable, IKVReduce { |
28 | ||
29 | private static final long serialVersionUID = -8682496769319143320L; | |
28 | 30 | |
29 | 31 | final int count; |
30 | 32 | final INode root; |
14 | 14 | import java.util.List; |
15 | 15 | |
16 | 16 | public class PersistentHashSet extends APersistentSet implements IObj, IEditableCollection { |
17 | ||
18 | private static final long serialVersionUID = 6973890746204954938L; | |
17 | 19 | |
18 | 20 | static public final PersistentHashSet EMPTY = new PersistentHashSet(null, PersistentHashMap.EMPTY); |
19 | 21 |
14 | 14 | |
15 | 15 | public class PersistentList extends ASeq implements IPersistentList, IReduce, List, Counted { |
16 | 16 | |
17 | private static final long serialVersionUID = -8833289659955219995L; | |
18 | ||
17 | 19 | private final Object _first; |
18 | 20 | private final IPersistentList _rest; |
19 | 21 | private final int _count; |
22 | 22 | */ |
23 | 23 | |
24 | 24 | public class PersistentQueue extends Obj implements IPersistentList, Collection, Counted, IHashEq{ |
25 | ||
26 | private static final long serialVersionUID = 8247184423915313132L; | |
25 | 27 | |
26 | 28 | final public static PersistentQueue EMPTY = new PersistentQueue(null, 0, null, null); |
27 | 29 |
17 | 17 | import java.util.NoSuchElementException; |
18 | 18 | |
19 | 19 | public class PersistentStructMap extends APersistentMap implements IObj{ |
20 | ||
21 | private static final long serialVersionUID = -2701411408470234065L; | |
20 | 22 | |
21 | 23 | public static class Def implements Serializable{ |
22 | 24 | final ISeq keys; |
18 | 18 | import java.util.NoSuchElementException; |
19 | 19 | import java.util.concurrent.atomic.AtomicReference; |
20 | 20 | |
21 | public class PersistentVector extends APersistentVector implements IObj, IEditableCollection, IReduce, IKVReduce{ | |
21 | public class PersistentVector extends APersistentVector implements IObj, IEditableCollection, IReduce, IKVReduce, IDrop{ | |
22 | ||
23 | private static final long serialVersionUID = -7896022351281214157L; | |
22 | 24 | |
23 | 25 | public static class Node implements Serializable { |
24 | 26 | transient public final AtomicReference<Thread> edit; |
362 | 364 | return init; |
363 | 365 | } |
364 | 366 | |
365 | static public final class ChunkedSeq extends ASeq implements IChunkedSeq,Counted{ | |
367 | public Sequential drop(int n) { | |
368 | if(n < 0) { | |
369 | return this; | |
370 | } else if(n < cnt) { | |
371 | int offset = n%32; | |
372 | return new ChunkedSeq(this, this.arrayFor(n), n-offset, offset); | |
373 | } else { | |
374 | return null; | |
375 | } | |
376 | } | |
377 | ||
378 | static public final class ChunkedSeq extends ASeq implements IChunkedSeq,Counted,IReduce,IDrop{ | |
366 | 379 | |
367 | 380 | public final PersistentVector vec; |
368 | 381 | final Object[] node; |
426 | 439 | |
427 | 440 | public int count(){ |
428 | 441 | return vec.cnt - (i + offset); |
442 | } | |
443 | ||
444 | public Iterator iterator() { | |
445 | return vec.rangedIterator(i +offset, vec.cnt); | |
446 | } | |
447 | ||
448 | public Object reduce(IFn f) { | |
449 | Object acc; | |
450 | if (i +offset < vec.cnt) | |
451 | acc = node[offset]; | |
452 | else | |
453 | return f.invoke(); | |
454 | ||
455 | for(int j=offset+1;j<node.length;++j){ | |
456 | acc = f.invoke(acc,node[j]); | |
457 | if(RT.isReduced(acc)) | |
458 | return ((IDeref)acc).deref(); | |
459 | } | |
460 | ||
461 | int step = 0; | |
462 | for(int ii = i +node.length; ii<vec.cnt; ii+=step){ | |
463 | Object[] array = vec.arrayFor(ii); | |
464 | for(int j = 0;j<array.length;++j){ | |
465 | acc = f.invoke(acc,array[j]); | |
466 | if(RT.isReduced(acc)) | |
467 | return ((IDeref)acc).deref(); | |
468 | } | |
469 | step = array.length; | |
470 | } | |
471 | return acc; | |
472 | } | |
473 | ||
474 | public Object reduce(IFn f, Object init) { | |
475 | Object acc = init; | |
476 | for(int j=offset;j<node.length;++j){ | |
477 | acc = f.invoke(acc,node[j]); | |
478 | if(RT.isReduced(acc)) | |
479 | return ((IDeref)acc).deref(); | |
480 | } | |
481 | ||
482 | int step = 0; | |
483 | for(int ii = i +node.length; ii<vec.cnt; ii+=step){ | |
484 | Object[] array = vec.arrayFor(ii); | |
485 | for(int j = 0;j<array.length;++j){ | |
486 | acc = f.invoke(acc,array[j]); | |
487 | if(RT.isReduced(acc)) | |
488 | return ((IDeref)acc).deref(); | |
489 | } | |
490 | step = array.length; | |
491 | } | |
492 | return acc; | |
493 | } | |
494 | ||
495 | public Sequential drop(int n) { | |
496 | int o = offset + n; | |
497 | if(o < node.length) { // in current array | |
498 | return new ChunkedSeq(vec, node, i, o); | |
499 | } else { | |
500 | int i = this.i +o; | |
501 | if(i < vec.cnt) { // in vec | |
502 | Object[] array = vec.arrayFor(i); | |
503 | int newOffset = i%32; | |
504 | return new ChunkedSeq(vec, vec.arrayFor(i), i-newOffset, newOffset); | |
505 | } else { | |
506 | return null; | |
507 | } | |
508 | } | |
429 | 509 | } |
430 | 510 | } |
431 | 511 |
17 | 17 | */ |
18 | 18 | public class Range extends ASeq implements IChunkedSeq, IReduce { |
19 | 19 | |
20 | private static final long serialVersionUID = -71973733672395145L; | |
21 | ||
20 | 22 | private static final int CHUNK_SIZE = 32; |
21 | 23 | |
22 | 24 | // Invariants guarantee this is never an "empty" seq |
98 | 100 | public Obj withMeta(IPersistentMap meta){ |
99 | 101 | if(meta == _meta) |
100 | 102 | return this; |
101 | return new Range(meta, end, start, step, boundsCheck, _chunk, _chunkNext); | |
103 | return new Range(meta, start, end, step, boundsCheck, _chunk, _chunkNext); | |
102 | 104 | } |
103 | 105 | |
104 | 106 | public Object first(){ |
16 | 16 | import java.math.MathContext; |
17 | 17 | |
18 | 18 | public class Ratio extends Number implements Comparable{ |
19 | ||
20 | private static final long serialVersionUID = -576272795628662988L; | |
21 | ||
19 | 22 | final public BigInteger numerator; |
20 | 23 | final public BigInteger denominator; |
21 | 24 |
11 | 11 | |
12 | 12 | /* Alex Miller, Dec 5, 2014 */ |
13 | 13 | |
14 | public class Repeat extends ASeq implements IReduce { | |
14 | public class Repeat extends ASeq implements IReduce, IDrop { | |
15 | ||
16 | private static final long serialVersionUID = -5140377547192202551L; | |
15 | 17 | |
16 | 18 | private static final long INFINITE = -1; |
17 | 19 | |
96 | 98 | } |
97 | 99 | } |
98 | 100 | |
101 | public Sequential drop(int n) { | |
102 | if(count == INFINITE) { | |
103 | return this; | |
104 | } else { | |
105 | long droppedCount = count-n; | |
106 | if(droppedCount > 0) { | |
107 | return new Repeat(droppedCount, val); | |
108 | } else { | |
109 | return null; | |
110 | } | |
111 | } | |
99 | 112 | } |
113 | ||
114 | } |
9 | 9 | package clojure.lang; |
10 | 10 | |
11 | 11 | public abstract class RestFn extends AFunction{ |
12 | ||
13 | private static final long serialVersionUID = -4319097849151802009L; | |
14 | ||
12 | 15 | abstract public int getRequiredArity(); |
13 | 16 | |
14 | 17 | protected Object doInvoke(Object args) { |
11 | 11 | |
12 | 12 | package clojure.lang; |
13 | 13 | |
14 | public class StringSeq extends ASeq implements IndexedSeq{ | |
14 | import java.util.Iterator; | |
15 | import java.util.NoSuchElementException; | |
16 | ||
17 | public class StringSeq extends ASeq implements IndexedSeq,IDrop,IReduceInit{ | |
18 | ||
19 | private static final long serialVersionUID = 7975525539139301753L; | |
20 | ||
15 | 21 | public final CharSequence s; |
16 | 22 | public final int i; |
17 | 23 | |
50 | 56 | public int count(){ |
51 | 57 | return s.length() - i; |
52 | 58 | } |
59 | ||
60 | public Sequential drop(int n) { | |
61 | int ii = i + n; | |
62 | if (ii < s.length()) { | |
63 | return new StringSeq(_meta, s, ii); | |
64 | } else { | |
65 | return null; | |
66 | } | |
53 | 67 | } |
68 | ||
69 | public Object reduce(IFn f, Object start) { | |
70 | Object acc = start; | |
71 | for(int ii=i; ii < s.length(); ii++) { | |
72 | acc = f.invoke(acc, s.charAt(ii)); | |
73 | if(RT.isReduced(acc)) | |
74 | return ((IDeref)acc).deref(); | |
75 | } | |
76 | return acc; | |
77 | } | |
78 | ||
79 | } |
16 | 16 | |
17 | 17 | |
18 | 18 | public class Symbol extends AFn implements IObj, Comparable, Named, Serializable, IHashEq{ |
19 | ||
20 | private static final long serialVersionUID = 1191039485148212259L; | |
21 | ||
19 | 22 | final String ns; |
20 | 23 | final String name; |
21 | 24 | private int _hasheq; |
17 | 17 | |
18 | 18 | |
19 | 19 | public final class Var extends ARef implements IFn, IRef, Settable, Serializable{ |
20 | ||
21 | private static final long serialVersionUID = 8368961370796295279L; | |
20 | 22 | |
21 | 23 | static class TBox{ |
22 | 24 |
8 | 8 | ; Author: Stuart Halloway |
9 | 9 | |
10 | 10 | (ns clojure.test-clojure.rt |
11 | (:require clojure.set) | |
11 | (:require [clojure.string :as string] | |
12 | clojure.set) | |
12 | 13 | (:use clojure.test clojure.test-helper)) |
13 | 14 | |
14 | 15 | (defn bare-rt-print |
74 | 75 | (.bindRoot #'example-var 0) |
75 | 76 | (is (not (contains? (meta #'example-var) :macro)))) |
76 | 77 | |
77 | (deftest last-var-wins-for-core | |
78 | (deftest ns-intern-policies | |
78 | 79 | (testing "you can replace a core name, with warning" |
79 | 80 | (let [ns (temp-ns) |
80 | replacement (gensym)] | |
81 | (with-err-string-writer (intern ns 'prefers replacement)) | |
81 | replacement (gensym) | |
82 | e1 (with-err-string-writer (intern ns 'prefers replacement))] | |
83 | (is (string/starts-with? e1 "WARNING")) | |
82 | 84 | (is (= replacement @('prefers (ns-publics ns)))))) |
83 | (testing "you can replace a name you defined before" | |
85 | (testing "you can replace a defined alias" | |
84 | 86 | (let [ns (temp-ns) |
85 | 87 | s (gensym) |
86 | 88 | v1 (intern ns 'foo s) |
87 | v2 (intern ns 'bar s)] | |
88 | (with-err-string-writer (.refer ns 'flatten v1)) | |
89 | (.refer ns 'flatten v2) | |
89 | v2 (intern ns 'bar s) | |
90 | e1 (with-err-string-writer (.refer ns 'flatten v1)) | |
91 | e2 (with-err-string-writer (.refer ns 'flatten v2))] | |
92 | (is (string/starts-with? e1 "WARNING")) | |
93 | (is (string/starts-with? e2 "WARNING")) | |
90 | 94 | (is (= v2 (ns-resolve ns 'flatten))))) |
91 | (testing "you cannot intern over an existing non-core name" | |
92 | (let [ns (temp-ns 'clojure.set) | |
93 | replacement (gensym)] | |
94 | (is (thrown? IllegalStateException | |
95 | (intern ns 'subset? replacement))) | |
96 | (is (nil? ('subset? (ns-publics ns)))) | |
97 | (is (= #'clojure.set/subset? ('subset? (ns-refers ns)))))) | |
98 | (testing "you cannot refer over an existing non-core name" | |
99 | (let [ns (temp-ns 'clojure.set) | |
100 | replacement (gensym)] | |
101 | (is (thrown? IllegalStateException | |
102 | (.refer ns 'subset? #'clojure.set/intersection))) | |
103 | (is (nil? ('subset? (ns-publics ns)))) | |
104 | (is (= #'clojure.set/subset? ('subset? (ns-refers ns))))))) | |
95 | (testing "you cannot replace an interned var" | |
96 | (let [ns1 (temp-ns) | |
97 | ns2 (temp-ns) | |
98 | v1 (intern ns1 'foo 1) | |
99 | v2 (intern ns2 'foo 2) | |
100 | e1 (with-err-string-writer (.refer ns1 'foo v2))] | |
101 | (is (string/starts-with? e1 "REJECTED")) | |
102 | (is (= v1 (ns-resolve ns1 'foo)))))) | |
103 |
780 | 780 | |
781 | 781 | (partition 5 [1 2 3]) () |
782 | 782 | |
783 | (partition 4 4 [0 0 0] (range 10)) '((0 1 2 3) (4 5 6 7) (8 9 0 0)) | |
784 | ||
783 | 785 | ; (partition 0 [1 2 3]) (repeat nil) ; infinite sequence of nil |
784 | 786 | (partition -1 [1 2 3]) () |
785 | 787 | (partition -2 [1 2 3]) () ) |
795 | 797 | (is (= (assoc (array-map (repeat 1 :x) :y) '(:x) :z) {'(:x) :z})) |
796 | 798 | (is (= (assoc (hash-map (repeat 1 :x) :y) '(:x) :z) {'(:x) :z}))) |
797 | 799 | |
800 | (deftest test-partitionv | |
801 | (are [x y] (= x y) | |
802 | (partitionv 2 [1 2 3]) '((1 2)) | |
803 | (partitionv 2 [1 2 3 4]) '((1 2) (3 4)) | |
804 | (partitionv 2 []) () | |
805 | ||
806 | (partitionv 2 3 [1 2 3 4 5 6 7]) '((1 2) (4 5)) | |
807 | (partitionv 2 3 [1 2 3 4 5 6 7 8]) '((1 2) (4 5) (7 8)) | |
808 | (partitionv 2 3 []) () | |
809 | ||
810 | (partitionv 1 []) () | |
811 | (partitionv 1 [1 2 3]) '((1) (2) (3)) | |
812 | ||
813 | (partitionv 4 4 [0 0 0] (range 10)) '([0 1 2 3] [4 5 6 7] [8 9 0 0]) | |
814 | ||
815 | (partitionv 5 [1 2 3]) () | |
816 | ||
817 | (partitionv -1 [1 2 3]) () | |
818 | (partitionv -2 [1 2 3]) () )) | |
798 | 819 | |
799 | 820 | (deftest test-iterate |
800 | 821 | (are [x y] (= x y) |
985 | 1006 | () '(1 2) |
986 | 1007 | [] [1 2] |
987 | 1008 | {} {:a 1 :b 2} |
988 | #{} #{1 2} )) | |
1009 | #{} #{1 2}) | |
1010 | ||
1011 | ; CLJ-2718 | |
1012 | (is (= '(:a) (drop 1 (repeat 2 :a)))) | |
1013 | (is (= () (drop 2 (repeat 2 :a)))) | |
1014 | (is (= () (drop 3 (repeat 2 :a))))) | |
989 | 1015 | |
990 | 1016 | (defspec longrange-equals-range 1000 |
991 | 1017 | (prop/for-all [start gen/int |
1056 | 1082 | |
1057 | 1083 | (reduce + (iterator-seq (.iterator (range 100)))) 4950 |
1058 | 1084 | (reduce + (iterator-seq (.iterator (range 0.0 100.0 1.0)))) 4950.0 )) |
1085 | ||
1086 | (deftest range-meta | |
1087 | (are [r] (= r (with-meta r {:a 1})) | |
1088 | (range 10) | |
1089 | (range 5 10) | |
1090 | (range 5 10 1) | |
1091 | (range 10.0) | |
1092 | (range 5.0 10.0) | |
1093 | (range 5.0 10.0 1.0))) | |
1059 | 1094 | |
1060 | 1095 | (deftest range-test |
1061 | 1096 | (let [threads 10 |
1118 | 1153 | {} |
1119 | 1154 | #{} |
1120 | 1155 | "" |
1121 | (into-array []) ) | |
1156 | (into-array []) | |
1157 | (transient []) | |
1158 | (transient #{}) | |
1159 | (transient {})) | |
1122 | 1160 | |
1123 | 1161 | (are [x] (not (empty? x)) |
1124 | 1162 | '(1 2) |
1127 | 1165 | {:a 1 :b 2} |
1128 | 1166 | #{1 2} |
1129 | 1167 | "abc" |
1130 | (into-array [1 2]) )) | |
1168 | (into-array [1 2]) | |
1169 | (transient [1]) | |
1170 | (transient #{1}) | |
1171 | (transient {1 2}))) | |
1131 | 1172 | |
1132 | 1173 | |
1133 | 1174 | (deftest test-every? |
1330 | 1371 | (is (= (partition-all 4 2 [1 2 3 4 5 6 7 8 9]) |
1331 | 1372 | [[1 2 3 4] [3 4 5 6] [5 6 7 8] [7 8 9] [9]]))) |
1332 | 1373 | |
1374 | (deftest test-partitionv-all | |
1375 | (is (= (partitionv-all 4 [1 2 3 4 5 6 7 8 9]) | |
1376 | [[1 2 3 4] [5 6 7 8] [9]])) | |
1377 | (is (= (partitionv-all 4 2 [1 2 3 4 5 6 7 8 9]) | |
1378 | [[1 2 3 4] [3 4 5 6] [5 6 7 8] [7 8 9] [9]]))) | |
1379 | ||
1333 | 1380 | (deftest test-shuffle-invariants |
1334 | 1381 | (is (= (count (shuffle [1 2 3 4])) 4)) |
1335 | 1382 | (let [shuffled-seq (shuffle [1 2 3 4])] |
1457 | 1504 | :kf #(some-> % :k #{0 1 2}) |
1458 | 1505 | :vf :item)))))) |
1459 | 1506 | |
1507 | (deftest test-reduce-on-coll-seqs | |
1508 | ;; reduce on seq of coll, both with and without an init | |
1509 | (are [coll expected expected-init] | |
1510 | (and | |
1511 | (= expected-init (reduce conj [:init] (seq coll))) | |
1512 | (= expected (reduce conj (seq coll)))) | |
1513 | ;; (seq [ ... ]) | |
1514 | [] [] [:init] | |
1515 | [1] 1 [:init 1] | |
1516 | [[1] 2] [1 2] [:init [1] 2] | |
1517 | ||
1518 | ;; (seq { ... }) | |
1519 | {} [] [:init] | |
1520 | {1 1} [1 1] [:init [1 1]] | |
1521 | {1 1 2 2} [1 1 [2 2]] [:init [1 1] [2 2]] | |
1522 | ||
1523 | ;; (seq (hash-map ... )) | |
1524 | (hash-map) [] [:init] | |
1525 | (hash-map 1 1) [1 1] [:init [1 1]] | |
1526 | (hash-map 1 1 2 2) [1 1 [2 2]] [:init [1 1] [2 2]] | |
1527 | ||
1528 | ;; (seq (sorted-map ... )) | |
1529 | (sorted-map) [] [:init] | |
1530 | (sorted-map 1 1) [1 1] [:init [1 1]] | |
1531 | (sorted-map 1 1 2 2) [1 1 [2 2]] [:init [1 1] [2 2]]) | |
1532 | ||
1533 | (are [coll expected expected-init] | |
1534 | (and | |
1535 | (= expected-init (reduce + 100 (seq coll))) | |
1536 | (= expected (reduce + (seq coll)))) | |
1537 | ||
1538 | ;; (seq (range ...)) | |
1539 | (range 0) 0 100 | |
1540 | (range 1 2) 1 101 | |
1541 | (range 1 3) 3 103)) | |
1542 | ||
1460 | 1543 | (defspec iteration-seq-equals-reduce 1000 |
1461 | 1544 | (prop/for-all [initk gen/int |
1462 | 1545 | seed gen/int] |