diff --git a/compiler/stz-arg-parser.stanza b/compiler/stz-arg-parser.stanza index 21817cddb..ce2ebc240 100644 --- a/compiler/stz-arg-parser.stanza +++ b/compiler/stz-arg-parser.stanza @@ -95,7 +95,7 @@ defn single? (f:Flag) : public defn parse-args (comms:Collection, default-comm:False|Command, args:Seqable) -> False : ;Get sequence of arguments - val args-seq = to-seq(args) + val args-seq = to-peek-seq(args) if default-comm is False : throw(NoCommand()) when empty?(args-seq) diff --git a/compiler/stz-call-records.stanza b/compiler/stz-call-records.stanza index db0804cfe..c4bc9f5a8 100644 --- a/compiler/stz-call-records.stanza +++ b/compiler/stz-call-records.stanza @@ -57,9 +57,9 @@ public defn callc-records (a1:Tuple, a2:ArgType, backend:Backend) -> Ca add(records, CallRecord(l,ShadowArg(i))) ;Track registers - val reg-counter = to-seq(0 to length(callc-regs(backend))) - val freg-counter = to-seq(0 to length(callc-fregs(backend))) - val mem-counter = to-seq(0 to false) + val reg-counter = to-peek-seq(0 to length(callc-regs(backend))) + val freg-counter = to-peek-seq(0 to length(callc-fregs(backend))) + val mem-counter = to-peek-seq(0 to false) defn next-reg () : val index = next(reg-counter) val id = callc-regs(backend)[index] @@ -104,7 +104,7 @@ public defn callc-records (a1:Tuple, a2:ArgType, backend:Backend) -> Ca (a2:RealArg) : FRegLoc(callc-fret(backend), 0) ;Count number of args used - defn peek? (xs:Seq, default:Int) : default when empty?(xs) else peek(xs) + defn peek? (xs:PeekSeq, default:Int) : default when empty?(xs) else peek(xs) val num-int-args = peek?(reg-counter, length(callc-regs(backend))) val num-real-args = peek?(freg-counter, length(callc-fregs(backend))) val num-mem-args = peek(mem-counter) diff --git a/compiler/stz-dyn-graph.stanza b/compiler/stz-dyn-graph.stanza index 9aa1e9ee5..d155160dc 100644 --- a/compiler/stz-dyn-graph.stanza +++ b/compiler/stz-dyn-graph.stanza @@ -179,8 +179,8 @@ defmulti yield-right (m:Merger, y:Y) -> False defmulti yield-merged (m:Merger, x:X, y:Y) -> False defn merge (merger:Merger, xs:Seqable, ys:Seqable) : - val xs-seq = to-seq(xs) - val ys-seq = to-seq(ys) + val xs-seq = to-peek-seq(xs) + val ys-seq = to-peek-seq(ys) let loop () : match(empty?(xs-seq), empty?(ys-seq)) : diff --git a/compiler/stz-el-to-vm.stanza b/compiler/stz-el-to-vm.stanza index 77f1d8d40..f609daf68 100644 --- a/compiler/stz-el-to-vm.stanza +++ b/compiler/stz-el-to-vm.stanza @@ -1328,7 +1328,7 @@ defn true-obj (iotable:IOTable) : ;============================================================ defn type-parts (t:EType, iotable:IOTable) -> Tuple : - val parts = generate : + val parts = PeekSeq $ generate : ;Break down type into parts defn level (t:EType) : match(t) : diff --git a/compiler/stz-front-end.stanza b/compiler/stz-front-end.stanza index 38654eac9..c93cb0fb8 100644 --- a/compiler/stz-front-end.stanza +++ b/compiler/stz-front-end.stanza @@ -411,7 +411,7 @@ defn FrontEnd (sys:FrontEndInputs) -> FrontEnd : throw(FrontEndErrors(errors)) when not empty?(errors) defn sub-ipackages (objs:Seqable, new-ipackages:Seqable) -> Tuple : - val pkg-seq = to-seq(new-ipackages) + val pkg-seq = to-peek-seq(new-ipackages) val result = to-tuple $ for obj in objs seq? : match(obj) : (obj:IPackage) : diff --git a/compiler/stz-input.stanza b/compiler/stz-input.stanza index e0be61536..2d96de87e 100644 --- a/compiler/stz-input.stanza +++ b/compiler/stz-input.stanza @@ -295,7 +295,7 @@ defn ls-name-args (e:IExp) -> [IExp, List] : defn split-packages (e:IExp, default-imports:Tuple) : ;Flatten sequence of expressions defn flatten (e:IExp) : - generate : + PeekSeq $ generate : let loop (e:IExp = e) : match(e:IBegin) : do(loop, exps(e)) else : yield(e) diff --git a/compiler/stz-langs.stanza b/compiler/stz-langs.stanza index fa9379868..31225c4c7 100644 --- a/compiler/stz-langs.stanza +++ b/compiler/stz-langs.stanza @@ -841,7 +841,7 @@ defsyntax stz-fast-print-lang : defn compile (info:False|FileInfo, format:String, args:List) : ;Break into parts - val parts = generate : + val parts = PeekSeq $ generate : val n = length(format) val args-seq = to-seq(args) let loop (i:Int = 0) : @@ -876,6 +876,5 @@ defn compile (info:False|FileInfo, format:String, args:List) : ;Compile into print statements List $ for p in pieces seq-append : fill-template(`(print(x)), [`x => p]) - - - \ No newline at end of file + + diff --git a/compiler/stz-set-utils.stanza b/compiler/stz-set-utils.stanza index 8fd34818a..6ef47a72d 100644 --- a/compiler/stz-set-utils.stanza +++ b/compiler/stz-set-utils.stanza @@ -49,7 +49,7 @@ public defn subset-of-union? (xs:Tuple, yss:Seqable>) -> True|Fa public defn union (a:Seqable, b:Seqable) -> Seq : generate : - val [sa, sb] = [to-seq(a), to-seq(b)] + val [sa, sb] = [to-peek-seq(a), to-peek-seq(b)] while not empty?(sa) and not empty?(sb) : val [ai, bj] = [peek(sa), peek(sb)] if ai < bj : @@ -64,7 +64,7 @@ public defn union (a:Seqable, b:Seqable) -> Seq : public defn intersect (a:Seqable, b:Seqable) -> Seq : generate : - val [sa, sb] = [to-seq(a), to-seq(b)] + val [sa, sb] = [to-peek-seq(a), to-peek-seq(b)] while not empty?(sa) and not empty?(sb) : val [ai, bj] = [peek(sa), peek(sb)] if ai < bj : diff --git a/compiler/stz-test-framework.stanza b/compiler/stz-test-framework.stanza index 30ba9c488..dbb519ef3 100644 --- a/compiler/stz-test-framework.stanza +++ b/compiler/stz-test-framework.stanza @@ -430,9 +430,9 @@ protected defn print-test-report (exit-on-fail?:True|False) : val s = testing-state() ;Count statistics - val skip-counter = to-seq(0 to false) - val pass-counter = to-seq(0 to false) - val fail-counter = to-seq(0 to false) + val skip-counter = to-peek-seq(0 to false) + val pass-counter = to-peek-seq(0 to false) + val fail-counter = to-peek-seq(0 to false) for r in records(s) do : match(r) : (r:SkippedTest) : next(skip-counter) diff --git a/compiler/stz-vm-normalize.stanza b/compiler/stz-vm-normalize.stanza index c49caa84b..cfedfd7df 100644 --- a/compiler/stz-vm-normalize.stanza +++ b/compiler/stz-vm-normalize.stanza @@ -1409,4 +1409,3 @@ defn InsBuffer (function:VMFunction) : else : i def-table[n] = VMDef(n, t) Local(n) - \ No newline at end of file diff --git a/core/arg-parser.stanza b/core/arg-parser.stanza index 9793ff338..2188ee6c6 100644 --- a/core/arg-parser.stanza +++ b/core/arg-parser.stanza @@ -156,7 +156,7 @@ defn parse-args-and-flags (flags:Tuple, arguments:Tuple) -> name(f) => f ;Sequence of arguments - val argseq = to-seq(arguments) + val argseq = to-peek-seq(arguments) ;Returns true if the given argument is a flag. defn flag? (arg:String) : diff --git a/core/core.stanza b/core/core.stanza index 87a3336a1..d4229b11f 100644 --- a/core/core.stanza +++ b/core/core.stanza @@ -3162,6 +3162,10 @@ protected defn range-bound (s:Lengthable, r:Range) -> [Int, Int] : (e:Int, i:False) : [start(r), e] (e:False, i) : [start(r), length(s)] +protected defn ensure-not-empty (xs:Seq) : + #if-defined(OPTIMIZE) : + fatal("Next on empty seq %_" % [xs]) when empty?(xs) + ;============================================================ ;===================== Hashable ============================= ;============================================================ @@ -5601,9 +5605,6 @@ public defn Generator (thunk : (T -> False, (T -> Void) & (() -> Void)) -> ?) defmethod next (this) : fill() empty() - defmethod peek (this) : - fill() - peek() defmethod empty? (this) : fill() defmethod free (this) : @@ -7077,7 +7078,6 @@ public defmulti to-seq (s:Seqable) -> Seq defmethod to-seq (s:Seq) : s public defmulti next (s:Seq) -> T -public defmulti peek (s:Seq) -> T public defmulti empty? (s:Seq) -> True|False public defmulti free (s:Seq) -> False defmethod free (s:Seq) : false @@ -7106,12 +7106,10 @@ defmethod to-seq (x:List) : defmethod empty? (this) : empty?(l) defmethod next (this) : - val x = peek(this) + ensure-not-empty(this) + val x = head(l) l = tail(l) x - defmethod peek (this) : - fatal("Empty Sequence") when empty?(this) - head(l) defmethod to-seq (xs:IndexedCollection) -> Seq : seq({xs[_]}, 0 to length(xs)) @@ -7123,13 +7121,11 @@ defmethod to-seq (r:Range) : var n = length(r) new Seq & Lengthable : defmethod next (this) : - val i* = peek(this) + ensure-not-empty(this) + val i* = i i = i + step(r) n = n - 1 i* - defmethod peek (this) : - fatal("Empty Sequence") when empty?(this) - i defmethod empty? (this) : n == 0 defmethod length (this) : @@ -7141,8 +7137,6 @@ defmethod to-seq (r:Range) : val i* = i i = i + step(r) i* - defmethod peek (this) : - i defmethod empty? (this) : false @@ -7263,7 +7257,6 @@ defmethod do (f:T -> ?, xs:List) -> False : defn wrap-length (xs:Seq, length:() -> Int) : new Seq & Lengthable : defmethod next (this) : next(xs) - defmethod peek (this) : peek(xs) defmethod empty? (this) : empty?(xs) defmethod length (this) : length() @@ -7271,38 +7264,40 @@ public defn to-collection (f:() -> Seq) -> Collection : new Collection : defmethod to-seq (this) : f() -public defn seq (f:T -> ?S, xs:Seqable) -> Seq : +public defn seq (f:T -> ?R, xs:Seqable) -> Seq : val xs-seq = to-seq(xs) - val rs = repeat-while $ fn () : - if empty?(xs-seq) : None() - else : One(f(next(xs-seq))) - match(xs-seq) : - (xs:Seq&Lengthable) : - wrap-length(rs, {cached(rs) + length(xs)}) - (xs) : rs + val rs = new Seq : + defmethod next (this) : + f(next(xs-seq)) + defmethod empty? (this) : + empty?(xs-seq) + match(xs-seq:Seq&Lengthable) : wrap-length(rs, { length(xs-seq) }) + else : rs public defn seq (f:(T,S) -> ?R, xs:Seqable, ys:Seqable) -> Seq : val xs-seq = to-seq(xs) val ys-seq = to-seq(ys) - val rs = repeat-while $ fn () : - if empty?(xs-seq) or empty?(ys-seq) : None() - else : One(f(next(xs-seq), next(ys-seq))) - match(xs-seq, ys-seq) : - (xs:Seq&Lengthable, ys:Seq&Lengthable) : - wrap-length(rs, {cached(rs) + min(length(xs), length(ys))}) - (xs, ys) : rs + val rs = new Seq : + defmethod next (this) : + f(next(xs-seq), next(ys-seq)) + defmethod empty? (this) : + empty?(xs-seq) or empty?(ys-seq) + match(xs-seq:Seq&Lengthable, ys-seq:Seq&Lengthable) : + wrap-length(rs, { min(length(xs-seq), length(ys-seq)) }) + else : rs public defn seq (f:(T,S,U) -> ?R, xs:Seqable, ys:Seqable, zs:Seqable) -> Seq : val xs-seq = to-seq(xs) val ys-seq = to-seq(ys) val zs-seq = to-seq(zs) - val rs = repeat-while $ fn () : - if empty?(xs-seq) or empty?(ys-seq) or empty?(zs-seq) : None() - else : One(f(next(xs-seq), next(ys-seq), next(zs-seq))) - match(xs-seq, ys-seq, zs-seq) : - (xs:Seq&Lengthable, ys:Seq&Lengthable, zs:Seq&Lengthable) : - wrap-length(rs, {cached(rs) + min(length(xs), min(length(ys), length(zs)))}) - (xs, ys, zs) : rs + val rs = new Seq : + defmethod next (this) : + f(next(xs-seq), next(ys-seq), next(zs-seq)) + defmethod empty? (this) : + empty?(xs-seq) or empty?(ys-seq) or empty?(zs-seq) + match(xs-seq:Seq&Lengthable, ys-seq:Seq&Lengthable, zs-seq:Seq&Lengthable) : + wrap-length(rs, { min(length(xs-seq), min(length(ys-seq), length(zs-seq))) }) + else: rs public defmulti in-reverse (xs:Seqable) -> Seq defmethod in-reverse (xs:Seqable) : @@ -7443,8 +7438,29 @@ public defn split! (xs:Seqable, ss:Seqable) -> [Collection <: Seq +public defmulti peek (s:PeekSeq) -> T + +public defn PeekSeq (xs-seq:Seq) -> PeekSeq : + var item:Sentinel|T = sentinel + defn fill () : (item = next(xs-seq)) when item is Sentinel + new PeekSeq : + defmethod next (this) : + val x = peek(this) + item = sentinel + x + defmethod peek (this) : + fill() + item as T + defmethod empty? (this) : + empty?(xs-seq) and item is Sentinel + +public defn to-peek-seq (xs:Seqable) -> PeekSeq : + match(xs:PeekSeq) : xs + else: PeekSeq $ to-seq $ xs + public defn split (f:T -> True|False, xs-items:Seqable) -> [Seq, Seq] : - val xs = to-seq(xs-items) + val xs = to-peek-seq(xs-items) val a-items = Queue() val b-items = Queue() @@ -7467,11 +7483,8 @@ public defn split (f:T -> True|False, xs-items:Seqable) -> [Seq, Seq< defn queue-seq (items:Queue) : new Seq : defmethod next (this) : - if fill(items) : pop(items) - else : fatal("No more items") - defmethod peek (this) : - if fill(items) : peek(items) - else : fatal("No more items") + fill(items) + pop(items) defmethod empty? (this) : not fill(items) @@ -7491,9 +7504,6 @@ public defn fork (xs-items:Seqable) -> [Seq, Seq] : x else : pop(items) - defmethod peek (this) : - if empty?(items) : peek(xs) - else : peek(items) defmethod empty? (this) : empty?(items) and empty?(xs) @@ -7517,33 +7527,29 @@ public defn fork (xs-items:Seqable, n:Int) -> Tuple> : defmethod next (this) : if empty?(items) : pull(i) else : pop(items) - defmethod peek (this) : - if empty?(items) : peek(xs) - else : peek(items) defmethod empty? (this) : empty?(items) and empty?(xs) public defn take-while (f: T -> True|False, xs:Seqable) : - generate : - for xs-seq in xs do-seq : - defn* loop () : - if not empty?(xs-seq) : - val x = peek(xs-seq) - if f(x) : - next(xs-seq) - yield(x) - loop() - loop() - + generate : + val xs-seq = to-peek-seq(xs) + let loop () : + if not empty?(xs-seq) : + val x = peek(xs-seq) + if f(x) : + next(xs-seq) + yield(x) + loop() + public defn take-until (f: T -> True|False, xs:Seqable) : generate : - for xs-seq in xs do-seq : - defn* loop () : - if not empty?(xs-seq) : - val x = next(xs-seq) - yield(x) - loop() when not f(x) - loop() + val xs-seq = to-seq(xs) + for xs-seq in xs do-seq : + let loop () : + if not empty?(xs-seq) : + val x = next(xs-seq) + yield(x) + loop() when not f(x) public defn take-n (n:Int, xs:Seqable) : ensure-non-negative("length", n) @@ -7551,13 +7557,9 @@ public defn take-n (n:Int, xs:Seqable) : val xs-seq = to-seq(xs) new Seq & Lengthable : defmethod next (this) : - val v = peek(this) - next(xs-seq) + val v = next(xs-seq) len = len - 1 v - defmethod peek (this) : - fatal("Empty Sequence") when len == 0 - peek(xs-seq) defmethod empty? (this) : len == 0 defmethod length (this) : @@ -7570,47 +7572,37 @@ public defn take-up-to-n (n:Int, xs:Seqable) : var len = n val xs-seq = to-seq(xs) new Seq : - defmethod next (this) : - val v = peek(this) - next(xs-seq) - len = len - 1 - v - defmethod peek (this) : - fatal("Empty Sequence") when empty?(this) - peek(xs-seq) - defmethod empty? (this) : - (len == 0) or empty?(xs-seq) - defmethod free (this) : - free(xs-seq) + defmethod next (this) : + len = len - 1 + next(xs-seq) + defmethod empty? (this) : + (len == 0) or empty?(xs-seq) + defmethod free (this) : + free(xs-seq) public defn cat (a:Seqable, b:Seqable) -> Seq : cat-all([a, b]) public defn cat-all (input-xss:Seqable>) -> Seq : val xss = to-seq(input-xss) - var xs:Seq|False|Sentinel = sentinel - defn* load-next-seq () : - if empty?(xss) : - xs = false - else : - xs = to-seq(next(xss)) - fill() - defn* fill () -> Seq|False : - match(xs) : - (xs:False) : false - (xs:Seq) : load-next-seq() when empty?(xs) else xs - (xs:Sentinel) : load-next-seq() - defn fill! () : - match(fill()) : - (xs:Seq) : xs - (xs:False) : fatal("Empty Sequence") + var xs:Seq|False = false + ;Advance to first non empty? seq and return if any available + defn ready? () : + let loop () : + if xs is False or empty?(xs as Seq) : + if empty?(xss) : + false + else : + xs = to-seq(next(xss)) + loop() + else : + true new Seq : defmethod next (this) : - next(fill!()) - defmethod peek (this) : - peek(fill!()) + ready?() + next(xs as Seq) defmethod empty? (this) : - fill() is False + not ready?() defmethod free (this) : match(xs:Seq) : free(xs) free(xss) @@ -7627,27 +7619,24 @@ public defn seq-cat (f:(T,S,U) -> Seqable, xs:Seqable, ys:S public defn all? (pred?: T -> True|False, xs:Seqable) -> True|False : for xs-seq in xs do-seq : - defn* loop () : + let loop () : if empty?(xs-seq) : true else : pred?(next(xs-seq)) and loop() - loop() public defn all? (pred?: (T,S) -> True|False, xs:Seqable, ys:Seqable) -> True|False : for xs-seq in xs do-seq : for ys-seq in ys do-seq : - defn* loop () : + let loop () : if empty?(xs-seq) or empty?(ys-seq) : true else : pred?(next(xs-seq), next(ys-seq)) and loop() - loop() public defn all? (pred?: (T,S,U) -> True|False, xs:Seqable, ys:Seqable, zs:Seqable) -> True|False : for xs-seq in xs do-seq : for ys-seq in ys do-seq : for zs-seq in zs do-seq : - defn* loop () : + let loop () : if empty?(xs-seq) or empty?(ys-seq) or empty?(zs-seq) : true else : pred?(next(xs-seq), next(ys-seq), next(zs-seq)) and loop() - loop() public defn none? (pred?: T -> True|False, xs:Seqable) -> True|False : defn notp (x) : not pred?(x) @@ -7691,13 +7680,9 @@ public defn join (xs0:Seqable, y:?S) -> Seq : var join? = false val rs = new Seq : defmethod next (this) : - fatal("Empty Sequence") when empty?(xs) val result = y when join? else next(xs) join? = not join? result - defmethod peek (this) : - fatal("Empty Sequence") when empty?(xs) - y when join? else peek(xs) defmethod empty? (this) : empty?(xs) match(xs) : @@ -7714,13 +7699,10 @@ public defn interleave (xs0:Seqable, ys0:Seqable) -> Seq : var yield-x? = true val rs = new Seq : defmethod next (this) : - fatal("Empty Sequence") when empty?(this) + ensure-not-empty(this) val result = next(xs) when yield-x? else next(ys) yield-x? = not yield-x? result - defmethod peek (this) : - fatal("Empty Sequence") when empty?(this) - peek(xs) when yield-x? else peek(ys) defmethod empty? (this) : empty?(xs) when yield-x? else empty?(ys) match(xs, ys) : @@ -7758,7 +7740,6 @@ public defn reduce-right (f: (T, T|S) -> ?S, xs:Seqable) -> T|S : public defn repeat (x:?T) -> Seq : new Seq : defmethod next (this) : x - defmethod peek (this) : x defmethod empty? (this) : false public defn repeat (x:?T, n:Int) : @@ -7766,12 +7747,9 @@ public defn repeat (x:?T, n:Int) : var len = n new Seq & Lengthable : defmethod next (this) : - fatal("Empty Sequence") when len == 0 + ensure-not-empty(this) len = len - 1 x - defmethod peek (this) : - fatal("Empty Sequence") when len == 0 - x defmethod empty? (this) : len == 0 defmethod length (this) : @@ -7786,12 +7764,10 @@ public defn repeat-while (f: () -> Maybe) -> RepeatWhileSeq : new RepeatWhileSeq : defmethod next (this) : - val x = peek(this) + fill() + val x = item item = sentinel - x - defmethod peek (this) : - fatal("Empty Sequence") when empty?(this) - value(item as One) + value(x as One) defmethod empty? (this) : fill() item is None @@ -7799,21 +7775,9 @@ public defn repeat-while (f: () -> Maybe) -> RepeatWhileSeq : 1 when item is One else 0 public defn repeatedly (f:() -> ?T) -> Seq : - var item = sentinel - defn fill () : (item = f()) when item is Sentinel - - defn empty () : - val x = item as T - item = sentinel - x - new Seq : defmethod next (this) : - fill() - empty() - defmethod peek (this) : - fill() - item as T + f() defmethod empty? (this) : false @@ -7832,8 +7796,6 @@ public defn zip-all (xs:Seqable>) : val ret-seq = new Seq> : defmethod next (this) : map(next, seqs) - defmethod peek (this) : - map(peek, seqs) defmethod empty? (this) : any?(empty?, seqs) if all?({_ is Lengthable&Seq}, seqs) : diff --git a/core/parser.stanza b/core/parser.stanza index 76d5acd16..8cafeb58b 100644 --- a/core/parser.stanza +++ b/core/parser.stanza @@ -1111,7 +1111,7 @@ defmulti num-indices (i:IndexPool) -> Int defmulti get (i:IndexPool, name:Symbol) -> Int defn IndexPool () : - val indices = to-seq(0 to false) + val indices = to-peek-seq(0 to false) val binders = HashTable() new IndexPool : defmethod next (this, name:Symbol) : diff --git a/core/reader.stanza b/core/reader.stanza index fe8b6b5cd..d62c923fb 100644 --- a/core/reader.stanza +++ b/core/reader.stanza @@ -344,7 +344,7 @@ defn eat-escaped-chars (s:ParseStream, buf:StringBuffer) -> String|False : defn tokenize (s:ParseStream) : ;Generate tokens - generate : + PeekSeq $ generate : ;Eat until next non-ignored character. ;Whitespace and comments are ignored. ;Returns true if line contains comments. @@ -644,8 +644,8 @@ with: defstruct StackBottom <: StackCtxt -defn convert-indentations-to-structural-tokens (tokens:Seq) -> Seq : - generate : +defn convert-indentations-to-structural-tokens (tokens:PeekSeq) -> PeekSeq : + PeekSeq $ generate : ;Initialize stack val stack = Vector() add(stack, Token(StackBottom(), FileInfo("NoFile", 0, 0))) @@ -822,7 +822,7 @@ deftype Parser defmulti parse-list (p:Parser) -> List defmulti parse-1 (p:Parser) -> False|Token -defn Parser (s:Seq) -> Parser : +defn Parser (s:PeekSeq) -> Parser : ;Create shorthands defn shorthand (t:Token, v:List) : val item = item(t) as OpenToken diff --git a/tests/test-seqs.stanza b/tests/test-seqs.stanza new file mode 100644 index 000000000..e4f558db7 --- /dev/null +++ b/tests/test-seqs.stanza @@ -0,0 +1,194 @@ +defpackage stz/test-seqs : + import core + import collections + +defn same? (name:String, a:Equalable, b:Equalable) : + ; println(" %_: %_ =? %_" % [name, a, b]) + if a != b : + println(" %_: %_ != %_" % [name, a, b]) + +defstruct Check : + name: String + run: String -> True|False + +defstruct Test : + name: String + init: Test -> ? + checks: Vector with: (init => Vector()) + +val tests = Vector() + +defn install-test (test:Test) : + init(test)(test) + add(tests, test) + +install-test $ Test("TUPLE", fn (test:Test) : + val i = [1, 2, 3] + val r = to-tuple $ to-seq $ i + add(checks(test), Check("E", same?{_, r, i})) + ) + +install-test $ Test("LIST", fn (test:Test) : + val i = [1, 2, 3] + val r = to-tuple $ to-seq $ to-list $ i + add(checks(test), Check("E", same?{_, r, i})) + ) + +install-test $ Test("RANGE", fn (test:Test) : + val i = 0 to 3 + val o = [0, 1, 2] + val r = to-tuple $ i + add(checks(test), Check("E", same?{_, r, o})) + ) + +install-test $ Test("VECTOR", fn (test:Test) : + val i = Vector() + add(i, 0) + add(i, 1) + add(i, 2) + val o = [0, 1, 2] + val r = to-tuple $ i + add(checks(test), Check("E", same?{_, r, o})) + ) + +install-test $ Test("SEQ-1", fn (test:Test) : + val xs = seq({ _ + 1 }, [1, 2, 3]) + add(checks(test), Check("A", same?{_, next(xs), 2})) + add(checks(test), Check("B", same?{_, next(xs), 3})) + add(checks(test), Check("C", same?{_, next(xs), 4})) + add(checks(test), Check("D", same?{_, empty?(xs), true})) + ) + +install-test $ Test("SEQ-2", fn (test:Test) : + val xs = seq(plus, [1, 2, 3], [2, 3, 4]) + add(checks(test), Check("A", same?{_, next(xs), 3})) + add(checks(test), Check("B", same?{_, next(xs), 5})) + add(checks(test), Check("C", same?{_, next(xs), 7})) + add(checks(test), Check("D", same?{_, empty?(xs), true})) + ) + +install-test $ Test("SEQ-3", fn (test:Test) : + val xs = seq(fn (a, b, c): a + b + c, [1, 2, 3], [2, 3, 4], [3, 4, 5]) + add(checks(test), Check("A", same?{_, next(xs), 6})) + add(checks(test), Check("B", same?{_, next(xs), 9})) + add(checks(test), Check("C", same?{_, next(xs), 12})) + add(checks(test), Check("D", same?{_, empty?(xs), true})) + ) + +install-test $ Test("SEQ-TO-TUPLE", fn (test:Test) : + val xs = seq({ _ + 1 }, [1, 2, 3]) + add(checks(test), Check("A", same?{_, to-tuple(xs), [2, 3, 4]})) + add(checks(test), Check("B", same?{_, empty?(xs), true})) + ) + +install-test $ Test("PEEK-SEQ-1", fn (test:Test) : + val i = [1, 2, 3] + val xs = to-peek-seq $ i + add(checks(test), Check("A", same?{_, peek(xs), 1})) + add(checks(test), Check("B", same?{_, next(xs), 1})) + add(checks(test), Check("C", same?{_, next(xs), 2})) + add(checks(test), Check("D", same?{_, next(xs), 3})) + add(checks(test), Check("D", same?{_, empty?(xs), true})) + ) + +install-test $ Test("TAKE-WHILE", fn (test:Test) : + val i = [1, 2, 3] + val xs = to-peek-seq $ i + val os = take-while({ _ < 3 }, xs) + add(checks(test), Check("A", same?{_, to-tuple(os), [1, 2]})) + add(checks(test), Check("B", same?{_, to-tuple(xs), [3]})) + ) + +install-test $ Test("TAKE-UNTIL", fn (test:Test) : + val i = [1, 2, 3] + val xs = to-peek-seq $ i + val os = take-until({ _ > 2 }, xs) + add(checks(test), Check("A", same?{_, to-tuple(os), [1, 2]})) + add(checks(test), Check("B", same?{_, to-tuple(xs), [3]})) + ) + +install-test $ Test("TAKE-N", fn (test:Test) : + val i = [1, 2, 3] + val xs = (to-seq $ i) as Seq&Lengthable + val os = take-n(2, xs) + add(checks(test), Check("A", same?{_, to-tuple(os), [1, 2]})) + add(checks(test), Check("B", same?{_, to-tuple(xs), [3]})) + ) + +install-test $ Test("TAKE-UP-TO-N", fn (test:Test) : + val i = [1, 2, 3] + val xs = to-seq $ i + val os = take-up-to-n(2, xs) + add(checks(test), Check("A", same?{_, to-tuple(os), [1, 2]})) + add(checks(test), Check("B", same?{_, to-tuple(xs), [3]})) + ) + +install-test $ Test("CAT", fn (test:Test) : + val a = [1, 2, 3] + val b = [4, 5, 6] + val r = [1, 2, 3, 4, 5, 6] + val os = cat(a, b) + add(checks(test), Check("A", same?{_, to-tuple(os), r})) + ) + +install-test $ Test("CAT-ALL", fn (test:Test) : + val a1 = [1, 2, 3] + val b1 = [4, 5, 6] + val c1 = [7, 8, 9] + val r1 = [1, 2, 3, 4, 5, 6, 7, 8, 9] + val os1 = cat-all $ [a1, b1, c1] + add(checks(test), Check("A", same?{_, to-tuple(os1), r1})) + val a2 = [1, 2, 3] + val b2 = [] + val c2 = [4, 5, 6] + val r2 = [1, 2, 3, 4, 5, 6] + val os2 = cat-all $ [a2, b2, c2] + add(checks(test), Check("B", same?{_, to-tuple(os2), r2})) + val a3 = [] + val b3 = [] + val c3 = [1, 2, 3] + val r3 = [1, 2, 3] + val os3 = cat-all $ [a3, b3, c3] + add(checks(test), Check("C", same?{_, to-tuple(os3), r3})) + val a4 = [] + val b4 = [] + val c4 = [] + val r4 = [] + val os4 = cat-all $ [a4, b4, c4] + add(checks(test), Check("D", same?{_, to-tuple(os4), r4})) + ) + +install-test $ Test("JOIN", fn (test:Test) : + val a = [1, 2, 3] + val r = [1, 0, 2, 0, 3] + val os = join(a, 0) + add(checks(test), Check("A", same?{_, to-tuple(os), r})) + ) + +install-test $ Test("INTERLEAVE", fn (test:Test) : + val a1 = [1, 2, 3] + val b1 = [4, 5, 6] + val r1 = [1, 4, 2, 5, 3, 6] + val os1 = interleave(a1, b1) + add(checks(test), Check("A", same?{_, to-tuple(os1), r1})) + val a2 = [1, 2, 3] + val b2 = [4, 5] + val r2 = [1, 4, 2, 5] + val os2 = interleave(a2, b2) + add(checks(test), Check("B", same?{_, to-tuple(os2), r2})) + ) + +install-test $ Test("REPEAT", fn (test:Test) : + val r = [1, 1, 1] + val os = repeat(1, 3) + add(checks(test), Check("A", same?{_, to-tuple(os), r})) + ) + +defn run-all-tests () : + for test in tests do : + println("RUNNING %_ TEST" % [name(test)]) + for check in checks(test) do : + ; println(" RUNNING %_ CHECK" % [name(check)]) + run(check)(name(check)) + +run-all-tests()