class Iterator { pub. Bool hasNext; testNext() {} getNext(T next) {} } class Iterable { newIterator(&Iterator iterator) {} } class Nothing { newIterator(&Iterator iterator) { NothingItr.new(iterator); } } class NothingItr { pub. Bool hasNext; testNext() { self.hasNext := false; } getNext(T next) {} } class Range { priv. Int a; priv. Int b; init(Int a, Int b) { self.a := a; self.b := b; } newIterator(&Iterator iterator) { RangeItr.new(iterator); ((RangeItr)iterator).init(self.a, self.b : a, b : _, _); } } class RangeItr { pub. Bool hasNext; init(Int a, Int b) { self.i := a; self.b := b; } testNext() { self.hasNext := ltInt(self.i, self.b); } getNext(Int next) { next := self.i; self.i := add(self.i, 1); } priv. Int i; priv. Int b; } class InfItr { pub. Bool hasNext; testNext() { self.hasNext := true; } } class From { priv. Int s; init(Int s) { self.s := s; } newIterator(&Iterator iterator) { FromItr.new(iterator); ((FromItr)iterator).init(self.s : s : _); } } class FromItr ext. InfItr { priv. Int s; init(Int s) { self.s := s; } clone(&(Iterator, ClonableIterator) iterator) { FromItr.new(iterator); ((FromItr)iterator).s := self.s; } getNext(Int next) { next := self.s; self.s := add(self.s, 1); } } class Take { priv. &Iterable s; priv. Int n; init(&Iterable s, Int n) { self.s := s; self.n := n; } newIterator(&Iterator iterator) { TakeItr.new(iterator); ((TakeItr)iterator).init(self.s, self.n : s, n : _, _); } } class TakeItr { priv. &Iterator i; priv. Int n; pub. Bool hasNext; init(&Iterable s, Int n) { s.newIterator(_ : iterator : self.i); self.n := n; } testNext() { self.hasNext := gtInt(self.n, 0); if ( self.hasNext ) { self.i.testNext(); self.hasNext := self.i.hasNext; } else {} } getNext(T next) { self.i.getNext(_ : next : next); self.n := sub(self.n, 1); } } class Drop { priv. &Iterable s; priv. Int n; init(&Iterable s, Int n) { self.s := s; self.n := n; } newIterator(&Iterator iterator) { DropItr.new(iterator); ((DropItr)iterator).init(self.s, self.n : s, n : _, _); } } class DropItr { priv. &Iterator i; priv. Int n; pub. Bool hasNext; init(&Iterable s, Int n) { s.newIterator(_ : iterator : self.i); self.n := n; } testNext() { self.i.testNext(); var T next; while ( and(gtInt(self.n, 0), self.i.hasNext) ) { self.i.getNext(_ : next : _); self.n := sub(self.n, 1); self.i.testNext(); } end next; self.hasNext := self.i.hasNext; } getNext(T next) { self.i.getNext(_ : next : next); } } class Pred { pub. Bool ok; eval(T x) {} } class Filter { priv. &Iterable s; priv. &Pred p; init(&Iterable s, &Pred p) { self.s := s; self.p := p; } newIterator(&Iterator iterator) { FilterItr.new(iterator); ((FilterItr)iterator).init(self.s, self.p : s, p : _, _); } } class FilterItr { priv. &Iterator i; priv. &Pred p; priv. T next; priv. Bool nextTaken; pub. Bool hasNext; init(&Iterable s, &Pred p) { s.newIterator(_ : iterator : self.i); self.p := p; self.nextTaken := false; } clone(&(Iterator, ClonableIterator) iterator) { FilterItr.new(iterator); ((FilterItr)iterator).i := self.i; ((FilterItr)iterator).p := self.p; ((FilterItr)iterator).next := self.next; ((FilterItr)iterator).nextTaken := self.nextTaken; ((FilterItr)iterator).hasNext := self.hasNext; } testNext() { if ( not(self.nextTaken) ) { self.hasNext := false; var Bool more; more := true; while ( and(not(self.hasNext), more) ) { self.i.testNext(); if ( self.i.hasNext ) { self.i.getNext(_ : next : self.next); self.p.eval(self.next : x : _); self.hasNext := self.p.ok; } else more := false; } end more; self.nextTaken := true; } else {} } getNext(T next) { self.testNext(); next := self.next; self.nextTaken := false; } } class Div { pub. Bool ok; priv. Int divisor; init(Int divisor) { self.divisor := divisor; } eval(Int x) { self.ok := eqInt(0, mod(x, self.divisor)); } } class NotDiv { pub. Bool ok; priv. Int divisor; init(Int divisor) { self.divisor := divisor; } eval(Int x) { self.ok := not(eqInt(0, mod(x, self.divisor))); } } class Concat { priv. &Iterable a; priv. &Iterable b; init(&Iterable a, &Iterable b) { self.a := a; self.b := b; } newIterator(&Iterator iterator) { ConcatItr.new(iterator); ((ConcatItr)iterator).init(self.a, self.b : a, b : _, _); } } class ConcatItr { priv. &Iterator i; priv. &Iterable b; priv. Bool first; pub. Bool hasNext; init(&Iterable a, &Iterable b) { a.newIterator(self.i : iterator : self.i); self.b := b; self.first := true; } testNext() { self.i.testNext(); self.hasNext := self.i.hasNext; if ( and(self.first, not(self.hasNext)) ) { self.b.newIterator(_ : iterator : self.i); self.i.testNext(); self.hasNext := self.i.hasNext; self.first := false; } else {} } getNext(T next) { self.i.getNext(_ : next : next); } } class ClonableIterator { clone(&(Iterator, ClonableIterator) iterator) {} } class Snapshot { priv. &(Iterator, ClonableIterator) i; init(&ClonableIterator i) { i.clone(_ : iterator : self.i); } newIterator(&Iterator iterator) { self.i.clone(_ : iterator : iterator); } } class Sieve { priv. &Iterable s; init(&Iterable s) { self.s := s; } newIterator(&Iterator iterator) { SieveItr.new(iterator); ((SieveItr)iterator).init(self.s : s : _); } } class SieveItr { priv. &Iterator i; priv. Int stage; priv. NotDiv nd; pub. Bool hasNext; init(&Iterable s) { s.newIterator(_ : iterator : self.i); self.stage := 0; } testNext() { if ( eqInt(1, self.stage) ) { var Snapshot snapshot, Filter filter, Sieve sieve; Snapshot.new(snapshot); snapshot.init((&(Iterator, ClonableIterator))self.i : i : _); Filter.new(filter); filter.init(snapshot, self.nd : s, p : _, _); Sieve.new(sieve); sieve.init(filter : s : _); sieve.newIterator(_ : iterator (SieveItr) : self.i); self.stage := 2; end snapshot, filter, sieve; } else {} self.i.testNext(); self.hasNext := self.i.hasNext; } getNext(Int next) { self.i.getNext(_ : next : next); if ( eqInt(0, self.stage) ) { NotDiv.new(self.nd); self.nd.init(next : divisor : _); self.stage := _; // wildcard test self.stage := 1; _ := 2; // wildcard test _ := _; // wildcard test } else {} } } class Static { iterate(&Iterable s) { var &Iterator i; s.newIterator(_ : iterator : i); i.testNext(); while ( i.hasNext ) { var T x; i.getNext(_ : next : x); print x; i.testNext(); end x; } print; end i; } } main { Range range, From from, Concat concat, Sieve sieve; var Static sta; Static.new(sta); Range.new(range); range.init(100, 120 : a, b : _, _); Concat.new(concat); concat.init(range, range : a, b : _, _); sta.iterate(concat : s : _); From.new(from); from.init(2000 : s : _); var Take take, Drop drop, Filter filter, Div d; Take.new(take); take.init(from, 80 : s, n : _, _); Drop.new(drop); drop.init(take, 20 : s, n : _, _); sta.iterate(drop : s : _); Div.new(d); d.init(3 : divisor : _); Filter.new(filter); filter.init(drop, d : s, p : _, _); sta.iterate(filter : s : _); end take, drop, filter, d; var Take take; from.init(2 : s : _); Sieve.new(sieve); sieve.init(from : s : _); Take.new(take); take.init(sieve, 25 : s, n : _, _); sta.iterate(take : s : _); end take; end sta; }