From f437f8f9a6689557c4c2b881fd738f8ec6d5f716 Mon Sep 17 00:00:00 2001 From: Wolfgang Schell Date: Thu, 12 Apr 2012 23:31:54 +0200 Subject: [PATCH] added EObjectIterator and made ECons Iterable --- src/main/java/erjang/ECons.java | 7 +- src/main/java/erjang/EObjectIterator.java | 58 ++++++ src/test/java/erjang/EObjectIteratorTest.java | 190 ++++++++++++++++++ 3 files changed, 254 insertions(+), 1 deletion(-) create mode 100644 src/main/java/erjang/EObjectIterator.java create mode 100644 src/test/java/erjang/EObjectIteratorTest.java diff --git a/src/main/java/erjang/ECons.java b/src/main/java/erjang/ECons.java index 8e1e303e..debb0f57 100644 --- a/src/main/java/erjang/ECons.java +++ b/src/main/java/erjang/ECons.java @@ -21,6 +21,7 @@ import java.io.ByteArrayOutputStream; import java.nio.ByteBuffer; import java.io.IOException; +import java.util.Iterator; import java.util.List; import java.util.Set; @@ -28,7 +29,7 @@ import erjang.m.ets.EPattern; import erjang.m.ets.ETermPattern; -public abstract class ECons extends EObject { +public abstract class ECons extends EObject implements Iterable { @Override int cmp_order() { @@ -241,4 +242,8 @@ public void collectCharList(CharCollector out) } else tail.collectCharList(out); } + @Override + public Iterator iterator() { + return new EObjectIterator(this); + } } diff --git a/src/main/java/erjang/EObjectIterator.java b/src/main/java/erjang/EObjectIterator.java new file mode 100644 index 00000000..517809c5 --- /dev/null +++ b/src/main/java/erjang/EObjectIterator.java @@ -0,0 +1,58 @@ +package erjang; + +import java.util.Iterator; +import java.util.NoSuchElementException; + + +public class EObjectIterator implements Iterator { + private EObject object = null; + + public EObjectIterator(EObject object) { + this.object = object; + } + + /* (non-Javadoc) + * @see java.util.Iterator#hasNext() + */ + public boolean hasNext() { + if (object == null) { + return false; + } + return !object.isNil(); + } + + /* (non-Javadoc) + * @see java.util.Iterator#next() + */ + public EObject next() { + if ((object == null) + || object.isNil()) { + throw new NoSuchElementException(); + } + + EObject next; + + ECons cons = object.testCons(); + if ((cons != null) + // TODO how to handle EString? return each character? Or return it as single element only? + // for now we don't treat EString as collection, but as single element + && !(cons instanceof EString)) { + next = cons.head(); + object = cons.tail(); + } + else { + // simple object, return it and set next object to null + next = object; + object = null; + } + return next; + } + + /* (non-Javadoc) + * @see java.util.Iterator#remove() + */ + public void remove() { + // not supported + throw new UnsupportedOperationException(); + } +} diff --git a/src/test/java/erjang/EObjectIteratorTest.java b/src/test/java/erjang/EObjectIteratorTest.java new file mode 100644 index 00000000..4925a97a --- /dev/null +++ b/src/test/java/erjang/EObjectIteratorTest.java @@ -0,0 +1,190 @@ +package erjang; + +import java.util.Iterator; +import java.util.NoSuchElementException; + +import junit.framework.TestCase; + +public class EObjectIteratorTest extends TestCase { + public void testNil() throws Exception { + Iterator it = new EObjectIterator(ERT.NIL); + assertNotNull(it); + assertFalse(it.hasNext()); + } + + public void testNull() throws Exception { + Iterator it = new EObjectIterator(null); + assertNotNull(it); + assertFalse(it.hasNext()); + } + + public void testEString() throws Exception { + EString message = EString.fromString("Hello, World!"); + Iterator it = new EObjectIterator(message); + assertNotNull(it); + assertTrue(it.hasNext()); + EObject o = it.next(); + assertNotNull(o); + assertEquals(message, o); + assertFalse(it.hasNext()); + try { + it.next(); + fail("no more elements, iterator should throw exception"); + } + catch (NoSuchElementException t) { + // expected + } + } + + public void testEInt() throws Exception { + EInteger num = ESmall.make(42); + Iterator it = new EObjectIterator(num); + assertNotNull(it); + assertTrue(it.hasNext()); + EObject o = it.next(); + assertNotNull(o); + assertEquals(num, o); + assertFalse(it.hasNext()); + try { + it.next(); + fail("no more elements, iterator should throw exception"); + } + catch (NoSuchElementException t) { + // expected + } + } + + public void testSeqWithSingleNil() throws Exception { + ESeq seq = ESeq.fromArray(new EObject[] { + ERT.NIL + }); + assertEquals(1, seq.length()); + Iterator it = seq.iterator(); + assertNotNull(it); + assertTrue(it.hasNext()); + EObject o = it.next(); + assertNotNull(o); + assertTrue(o.isNil()); + assertEquals(ERT.NIL, o); + assertFalse(it.hasNext()); + try { + it.next(); + fail("no more elements, iterator should throw exception"); + } + catch (NoSuchElementException t) { + // expected + } + } + + public void testSeqWithTwoNils() throws Exception { + ESeq seq = ESeq.fromArray(new EObject[] { + ERT.NIL, + ERT.NIL + }); + assertEquals(2, seq.length()); + Iterator it = seq.iterator(); + assertNotNull(it); + assertTrue(it.hasNext()); + EObject o = it.next(); + assertNotNull(o); + assertTrue(o.isNil()); + assertEquals(ERT.NIL, o); + assertTrue(it.hasNext()); + o = it.next(); + assertNotNull(o); + assertTrue(o.isNil()); + assertEquals(ERT.NIL, o); + assertFalse(it.hasNext()); + try { + it.next(); + fail("no more elements, iterator should throw exception"); + } + catch (NoSuchElementException t) { + // expected + } + } + + public void testSeqWithSingleObject() throws Exception { + EObject first = EString.fromString("Hello"); + ESeq seq = ESeq.fromArray(new EObject[] { + first + }); + assertEquals(1, seq.length()); + Iterator it = seq.iterator(); + assertNotNull(it); + assertTrue(it.hasNext()); + EObject o = it.next(); + assertNotNull(o); + assertEquals(first, o); + assertFalse(it.hasNext()); + try { + it.next(); + fail("no more elements, iterator should throw exception"); + } + catch (NoSuchElementException t) { + // expected + } + } + + public void testSeqWithTwoObjects() throws Exception { + EObject first = EString.fromString("Hello"); + EObject second = EString.fromString("World"); + ESeq seq = ESeq.fromArray(new EObject[] { + first, + second + }); + assertEquals(2, seq.length()); + Iterator it = seq.iterator(); + assertNotNull(it); + assertTrue(it.hasNext()); + EObject o = it.next(); + assertNotNull(o); + assertEquals(first, o); + assertTrue(it.hasNext()); + o = it.next(); + assertNotNull(o); + assertEquals(second, o); + assertFalse(it.hasNext()); + try { + it.next(); + fail("no more elements, iterator should throw exception"); + } + catch (NoSuchElementException t) { + // expected + } + } + + public void testSeqWithThreeObjects() throws Exception { + EObject first = EString.fromString("Hello"); + EObject second = EString.fromString("World"); + EObject third = ESmall.make(42); + ESeq seq = ESeq.fromArray(new EObject[] { + first, + second, + third + }); + assertEquals(3, seq.length()); + Iterator it = seq.iterator(); + assertNotNull(it); + assertTrue(it.hasNext()); + EObject o = it.next(); + assertNotNull(o); + assertEquals(first, o); + assertTrue(it.hasNext()); + o = it.next(); + assertNotNull(o); + assertEquals(second, o); + assertTrue(it.hasNext()); + o = it.next(); + assertNotNull(o); + assertEquals(third, o); + assertFalse(it.hasNext()); + try { + it.next(); + fail("no more elements, iterator should throw exception"); + } + catch (NoSuchElementException t) { + // expected + } + } +}