diff options
author | Rich Hickey <richhickey@gmail.com> | 2009-02-02 15:14:48 +0000 |
---|---|---|
committer | Rich Hickey <richhickey@gmail.com> | 2009-02-02 15:14:48 +0000 |
commit | 65528bfe81d605eab6fe3e475ada08f55bcc5ab5 (patch) | |
tree | 784cdb4a36f8e3fa35edf00dab9453d134356bea | |
parent | 961bb483ff08f6508390a6467d0758efe2c1ba85 (diff) |
[lazy] interim checkin
-rw-r--r-- | src/clj/clojure/core.clj | 8 | ||||
-rw-r--r-- | src/clj/clojure/core_print.clj | 8 | ||||
-rw-r--r-- | src/jvm/clojure/lang/ASeq.java | 7 | ||||
-rw-r--r-- | src/jvm/clojure/lang/Compile.java | 4 | ||||
-rw-r--r-- | src/jvm/clojure/lang/Compiler.java | 23 | ||||
-rw-r--r-- | src/jvm/clojure/lang/LazySeq.java | 194 | ||||
-rw-r--r-- | src/jvm/clojure/lang/RT.java | 48 |
7 files changed, 256 insertions, 36 deletions
diff --git a/src/clj/clojure/core.clj b/src/clj/clojure/core.clj index 3d13eba0..fc25a32a 100644 --- a/src/clj/clojure/core.clj +++ b/src/clj/clojure/core.clj @@ -407,7 +407,6 @@ [first-expr & rest-expr] (list 'new 'clojure.lang.LazyCons (list `fn (list [] first-expr) (list* [(gensym)] rest-expr)))) - (defmacro lazy-seq "Takes a body of expressions that returns an ISeq or nil, and yields a Seqable object that will invoke the body only the first time seq @@ -415,7 +414,7 @@ seq calls. Any closed over locals will be cleared prior to the tail call of body." [& body] - (list 'new 'clojure.lang.Delay$Seq (list* '#^{:once true} fn* [] body))) + (list* '#^{:once true :super-name "clojure/lang/LazySeq"} fn* [] body)) (defn concat "Returns a lazy sequence representing the concatenation of the elements in the supplied colls." @@ -1420,8 +1419,9 @@ f should accept number-of-colls arguments." ([f coll] (lazy-seq - (when (seq coll) - (cons (f (first coll)) (map f (more coll)))))) + (let [s (seq coll)] + (when s + (cons (f (first s)) (map f (more s))))))) ([f c1 c2] (lazy-seq (when (and (seq c1) (seq c2)) diff --git a/src/clj/clojure/core_print.clj b/src/clj/clojure/core_print.clj index 59b045b3..b2589f6f 100644 --- a/src/clj/clojure/core_print.clj +++ b/src/clj/clojure/core_print.clj @@ -101,12 +101,12 @@ (print-dup (str o) w)) w)) -(defmethod print-dup clojure.lang.AFn [o, #^Writer w] +(defmethod print-dup clojure.lang.Fn [o, #^Writer w] (print-ctor o (fn [o w]) w)) -(prefer-method print-dup clojure.lang.IPersistentCollection clojure.lang.AFn) -(prefer-method print-dup java.util.Map clojure.lang.AFn) -(prefer-method print-dup java.util.Collection clojure.lang.AFn) +(prefer-method print-dup clojure.lang.IPersistentCollection clojure.lang.Fn) +(prefer-method print-dup java.util.Map clojure.lang.Fn) +(prefer-method print-dup java.util.Collection clojure.lang.Fn) (defmethod print-method Boolean [o, #^Writer w] (.write w (str o))) diff --git a/src/jvm/clojure/lang/ASeq.java b/src/jvm/clojure/lang/ASeq.java index c4f4f7ca..f658ee91 100644 --- a/src/jvm/clojure/lang/ASeq.java +++ b/src/jvm/clojure/lang/ASeq.java @@ -110,8 +110,11 @@ public ISeq cons(Object o){ return new Cons(o, this);
}
-public ISeq rest(){
- return RT.seq(more());
+final public ISeq rest(){
+ Seqable m = more();
+ if(m == null)
+ return null;
+ return m.seq();
}
// java.util.Collection implementation
diff --git a/src/jvm/clojure/lang/Compile.java b/src/jvm/clojure/lang/Compile.java index 0f3948b1..37d2c102 100644 --- a/src/jvm/clojure/lang/Compile.java +++ b/src/jvm/clojure/lang/Compile.java @@ -23,10 +23,10 @@ import java.io.IOException; public class Compile{ private static final String PATH_PROP = "clojure.compile.path"; -private static final Var compile_path = RT.var("clojure.core", "*compile-path*"); -private static final Var compile = RT.var("clojure.core", "compile"); public static void main(String[] args) throws Exception{ + final Var compile_path = RT.var("clojure.core", "*compile-path*"); + final Var compile = RT.var("clojure.core", "compile"); OutputStreamWriter out = (OutputStreamWriter) RT.OUT.get(); PrintWriter err = (PrintWriter) RT.ERR.get(); diff --git a/src/jvm/clojure/lang/Compiler.java b/src/jvm/clojure/lang/Compiler.java index efd52ab6..4e75daff 100644 --- a/src/jvm/clojure/lang/Compiler.java +++ b/src/jvm/clojure/lang/Compiler.java @@ -2818,6 +2818,7 @@ static public class FnExpr implements Expr{ PersistentVector constants; int constantsID; boolean onceOnly = false; + String superName = null; public final IPersistentCollection methods(){ return methods; @@ -2899,7 +2900,11 @@ static public class FnExpr implements Expr{ static Expr parse(C context, ISeq form, String name) throws Exception{ FnExpr fn = new FnExpr(tagOf(form)); FnMethod enclosingMethod = (FnMethod) METHOD.get(); - fn.onceOnly = RT.booleanCast(RT.get(RT.meta(form.first()), Keyword.intern(null, "once"))); + if(((IMeta)form.first()).meta() != null) + { + fn.onceOnly = RT.booleanCast(RT.get(RT.meta(form.first()), Keyword.intern(null, "once"))); + fn.superName = (String) RT.get(RT.meta(form.first()), Keyword.intern(null, "super-name")); + } //fn.thisName = name; String basename = enclosingMethod != null ? (enclosingMethod.fn.name + "$") @@ -3014,7 +3019,8 @@ static public class FnExpr implements Expr{ // ClassVisitor cv = new TraceClassVisitor(new CheckClassAdapter(cw), new PrintWriter(System.out)); //ClassVisitor cv = new TraceClassVisitor(cw, new PrintWriter(System.out)); cv.visit(V1_5, ACC_PUBLIC + ACC_SUPER, internalName, null, - isVariadic() ? "clojure/lang/RestFn" : "clojure/lang/AFunction", null); + superName != null ? superName : + (isVariadic() ? "clojure/lang/RestFn" : "clojure/lang/AFunction"), null); String source = (String) SOURCE.get(); int lineBefore = (Integer) LINE_BEFORE.get(); int lineAfter = (Integer) LINE_AFTER.get() + 1; @@ -3105,7 +3111,9 @@ static public class FnExpr implements Expr{ ctorgen.visitLineNumber(line, ctorgen.mark()); ctorgen.visitLabel(start); ctorgen.loadThis(); - if(isVariadic()) //RestFn ctor takes reqArity arg + if(superName != null) + ctorgen.invokeConstructor(Type.getObjectType(superName),afnctor); + else if(isVariadic()) //RestFn ctor takes reqArity arg { ctorgen.push(variadicMethod.reqParms.count()); ctorgen.invokeConstructor(restFnType, restfnctor); @@ -3176,7 +3184,8 @@ static public class FnExpr implements Expr{ for (int i = 0; i < constants.count(); i++) { - if (constants.nth(i) instanceof String) + Object o = constants.nth(i); + if (o instanceof String) { clinitgen.push((String)constants.nth(i)); } @@ -3185,15 +3194,15 @@ static public class FnExpr implements Expr{ String cs = null; try { - cs = RT.printString(constants.nth(i)); + cs = RT.printString(o); } catch (Exception e) { throw new RuntimeException("Can't embed object in code, maybe print-dup not defined: " - + constants.nth(i)); + + o); } if (cs.length() == 0) - throw new RuntimeException("Can't embed unreadable object in code: " + constants.nth(i)); + throw new RuntimeException("Can't embed unreadable object in code: " + o); if (cs.startsWith("#<")) throw new RuntimeException("Can't embed unreadable object in code: " + cs); diff --git a/src/jvm/clojure/lang/LazySeq.java b/src/jvm/clojure/lang/LazySeq.java new file mode 100644 index 00000000..567be35b --- /dev/null +++ b/src/jvm/clojure/lang/LazySeq.java @@ -0,0 +1,194 @@ +/** + * Copyright (c) Rich Hickey. All rights reserved. + * The use and distribution terms for this software are covered by the + * Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) + * which can be found in the file epl-v10.html at the root of this distribution. + * By using this software in any fashion, you are agreeing to be bound by + * the terms of this license. + * You must not remove this notice, or any other, from this software. + **/ + +/* rich Jan 31, 2009 */ + +package clojure.lang; + +import java.util.*; + +public class LazySeq extends AFn implements Seqable, IPersistentCollection, List, Sequential, Sequence { + static final ISeq DUMMY = new Cons(null, null); + + private ISeq s = DUMMY; + + final synchronized public ISeq seq() { + if(s == DUMMY) + { + try + { + s = (ISeq) invoke(); + } + catch (Exception e) + { + throw new RuntimeException(e); + } + } + return s; + } + + public int count() { + int c = 0; + for (ISeq s = seq(); s != null; s = s.rest()) + ++c; + return c; + } + + public IPersistentCollection cons(Object o) { + return RT.cons(o, seq()); + } + + public IPersistentCollection empty() { + return null; + } + + public boolean equiv(Object o) { + ISeq s = seq(); + return s == o || (s != null && s.equiv(o)); + } + + public int hashCode() { + return Util.hash(seq()); + } + + public boolean equals(Object o) { + ISeq s = seq(); + return s == o || (s != null && s.equals(o)); + } + + +// java.util.Collection implementation + + public Object[] toArray() { + return RT.seqToArray(seq()); + } + + public boolean add(Object o) { + throw new UnsupportedOperationException(); + } + + public boolean remove(Object o) { + throw new UnsupportedOperationException(); + } + + public boolean addAll(Collection c) { + throw new UnsupportedOperationException(); + } + + public void clear() { + throw new UnsupportedOperationException(); + } + + public boolean retainAll(Collection c) { + throw new UnsupportedOperationException(); + } + + public boolean removeAll(Collection c) { + throw new UnsupportedOperationException(); + } + + public boolean containsAll(Collection c) { + for (Object o : c) + { + if (!contains(o)) + return false; + } + return true; + } + + public Object[] toArray(Object[] a) { + if (a.length >= count()) + { + ISeq s = seq(); + for (int i = 0; s != null; ++i, s = s.rest()) + { + a[i] = s.first(); + } + if (a.length > count()) + a[count()] = null; + return a; + } + else + return toArray(); + } + + public int size() { + return count(); + } + + public boolean isEmpty() { + return count() == 0; + } + + public boolean contains(Object o) { + for (ISeq s = seq(); s != null; s = s.rest()) + { + if (Util.equiv(s.first(), o)) + return true; + } + return false; + } + + public Iterator iterator() { + return new SeqIterator(seq()); + } + + //////////// List stuff ///////////////// + private List reify() { + return new ArrayList(this); + } + + public List subList(int fromIndex, int toIndex) { + return reify().subList(fromIndex, toIndex); + } + + public Object set(int index, Object element) { + throw new UnsupportedOperationException(); + } + + public Object remove(int index) { + throw new UnsupportedOperationException(); + } + + public int indexOf(Object o) { + ISeq s = seq(); + for (int i = 0; s != null; s = s.rest(), i++) + { + if (Util.equiv(s.first(), o)) + return i; + } + return -1; + } + + public int lastIndexOf(Object o) { + return reify().lastIndexOf(o); + } + + public ListIterator listIterator() { + return reify().listIterator(); + } + + public ListIterator listIterator(int index) { + return reify().listIterator(index); + } + + public Object get(int index) { + return RT.nth(this, index); + } + + public void add(int index, Object element) { + throw new UnsupportedOperationException(); + } + + public boolean addAll(int index, Collection c) { + throw new UnsupportedOperationException(); + } + +} diff --git a/src/jvm/clojure/lang/RT.java b/src/jvm/clojure/lang/RT.java index d64cfa7d..50a4baae 100644 --- a/src/jvm/clojure/lang/RT.java +++ b/src/jvm/clojure/lang/RT.java @@ -497,7 +497,11 @@ static ISeq seqFrom(Object coll){ else if(coll instanceof Map) return seq(((Map) coll).entrySet()); else - throw new IllegalArgumentException("Don't know how to create ISeq from: " + coll.getClass().getSimpleName()); + { + Class c = coll.getClass(); + Class sc = c.getSuperclass(); + throw new IllegalArgumentException("Don't know how to create ISeq from: " + c.getSimpleName()); + } } static public ISeq keys(Object coll){ @@ -577,22 +581,30 @@ static public ISeq rest(Object x){ } static public Seqable more(Object x){ - Seqable ret = null; if(x instanceof ISeq) - ret = ((ISeq) x).more(); - else - { - ISeq seq = seq(x); - if(seq == null) - ret = PersistentList.EMPTY; - else - ret = seq.more(); - } - if(ret == null) - ret = PersistentList.EMPTY; -// throw new IllegalStateException("nil more"); - return ret; -} + return ((ISeq) x).more(); + ISeq seq = seq(x); + if(seq == null) + return null; + return seq.more(); +} + +//static public Seqable more(Object x){ +// Seqable ret = null; +// if(x instanceof ISeq) +// ret = ((ISeq) x).more(); +// else +// { +// ISeq seq = seq(x); +// if(seq == null) +// ret = PersistentList.EMPTY; +// else +// ret = seq.more(); +// } +// if(ret == null) +// ret = PersistentList.EMPTY; +// return ret; +//} static public ISeq rrest(Object x){ return rest(rest(x)); @@ -1231,7 +1243,9 @@ static public void print(Object x, Writer w) throws Exception{ if(x instanceof Obj) { Obj o = (Obj) x; - if(RT.count(o.meta()) > 0 && readably && booleanCast(PRINT_META.get())) + if(RT.count(o.meta()) > 0 && + ((readably && booleanCast(PRINT_META.get())) + || booleanCast(PRINT_DUP.get()))) { IPersistentMap meta = o.meta(); w.write("#^"); |