Select the types of activity you want to include in your feed.
Redo `with` syntax.
Similar to redoing `match`, the `when` cases of a `with` expression are now within braces, and the `else` clause is optional and cannot have a binding.
···1010* Something wrong with `or` patterns when running JIT
1111* Allow `with {}` (with a block)
1212* Make blocks and expressions more interchangeable
1313-* Rethink syntax of cases (`with`)
1414- * Add braces like most languages use
1515- * `else yield` is default fallback for `when`
1616- * Remove binding from `else _ then {}` case, as it will be optional and could just be a regular last case
1713* Do a proper standard library design, maybe include a prelude
1814 * Type-agnostic global functions (similar to core, but safe)
1915 * Consistent interfaces to individual core standard modules
+2-1
samples/first_class_resume.tri
···44func doubleInto x into = into (2 * x)
5566proc main!() {
77- exit with divBy 8 0
77+ exit with divBy 8 0 {
88 when 'INF cancel doubleInto 2 (resume)
99 else yield
1010+ }
1011}
+6-3
samples/handler.tri
···33func divBy x y = x / y
4455proc main!() {
66- let x = with divBy 3 0
66+ let x = with divBy 3 0 {
77 when 'NAN cancel 0
88 when 'INF resume 1
99 else yield
1010+ }
10111111- let y = with divBy 4 "y"
1212+ let y = with divBy 4 "y" {
1213 when 'NAN cancel 9
1314 when 'INF resume 2
1415 else yield
1616+ }
15171616- let z = with divBy 4 2
1818+ let z = with divBy 4 2 {
1719 when 'NAN cancel 9
1820 when 'INF resume 4
1921 else yield
2222+ }
20232124 exit x + y + z
2225}
+8-19
spec/src/syntax-and-semantics/effects/index.tex
···2828 \bnfor
2929 } \\
3030 \bnfmore{
3131- \bnfts{\kw{else}}
3232- \bnfsp
3333- \bnfpn{Binding}
3434- \bnfsp
3535- \bnfpn{Handler}
3131+ \bnfpn{EffectHandler}
3632 \bnfor
3737- } \\
3838- \bnfmore{
3933 \bnfts{\kw{else}}
4034 \bnfsp
4141- \bnfpn{Expression}
3535+ \bnfpn{Handler}
4236 } \\
4337 \bnfprod{EffectHandler}{
4438 \bnfts{\kw{when}}
···7064 \bnfmore{
7165 \bnfts{\kw{then}}
7266 \bnfsp
7373- \bnfpn{Expression}
7474- \bnfor
7567 \bnfpn{Block}
7668 \bnfor
7777- } \\
7878- \bnfmore{
7969 \bnfts{\kw{yield}}
8070 \bnfsp
8171 \bnfpn{Expression}
···8575\end{bnf*}
86768777Effect handlers are defined with \kw{when} and are either written in functional
8888-or imperative style. At the end of a chain of handlers, the \kw{else} clause is
8989-included to describe what to do in the case of no handler matching; the default
9090-choice should be \kw{else yield}, but in some situations there may be reason to
9191-do otherwise.
7878+or imperative style. At the end of a chain of handlers, an \kw{else} clause may be
7979+included to describe what to do in the case of no handler matching; if omitted,
8080+the default is as if it were written \kw{else yield}.
92819382Handlers install a contextual handler around a piece of code. When an effect is
9483yielded, the ``nearest'' handler with a matching pattern and guard will be used
···10291to a handler in the parent scope (a re-yielded effect never gets handled by another
10392handler on the same chain).
10493105105-A \kw{cancel} handler will not respond to the yielder, instead completing the entire expression
106106-or statement on which the handler was attached, as if the \kw{with} keyword evaluated
107107-to the value that \kw{cancel} was supplied.
9494+A \kw{cancel} handler will not respond to the yielder, instead completing the entire
9595+expression or statement on which the handler was attached, as if the \kw{with} keyword
9696+evaluated to the value that \kw{cancel} was supplied.
1089710998A \kw{resume} handler will respond with the evaluation of the expression following
11099the keyword. The \kw{yield} that performed the effect will evaluate to that value.
···8899proc main!() {
1010 let mut res = unit
1111- with yielding!()
1111+ with yielding!() {
1212 when 'capture then{
1313 res = (resume)
1414 cancel unit
1515 }
1616 when 'get_value resume 5
1717 else yield
1818+ }
18191920 assert res 5 == 10
2021 assert res 20 == 25
+3-2
testsuite/captured-return-shedding/main.tri
···2233proc inner!() {
44 let ret = (return)
55- with ret 3
55+ with ret 3 {
66 when 'eff then {
77 println!("hello")
88 cancel false
99 }
1010 else yield
1111+ }
1112}
12131314proc outer!() {
···1617}
17181819proc main!() {
1919- assert with outer!() when 'eff cancel true else cancel false
2020+ assert with outer!() { when 'eff cancel true else cancel false }
2021}
+2-2
testsuite/effects-break-after-resume/main.tri
···1010proc main!() {
1111 let mut x = 0
1212 while x < 5 {
1313- with thing!(x)
1313+ with thing!(x) {
1414 when 'a(a) if a > 2 then { break unit }
1515 when 'a(a) then {
1616 let 'b(b) = resume a
1717 debug::dbg!('handler(b))
1818 cancel unit
1919 }
2020- else yield
2020+ }
2121 x += 1
2222 }
2323 assert x == 3
+2-1
testsuite/effects-cancel-mid-resume/main.tri
···77}
8899proc main!() {
1010- let x = with inner!()
1010+ let x = with inner!() {
1111 when 'in then {
1212 if resume 'a
1313 then cancel 1
···1515 }
1616 when 'out cancel false
1717 else yield
1818+ }
1819 assert "final result should be 2 but it was ${x}" as x == 2
1920}
+1-1
testsuite/effects-handle-and-end/main.tri
···33}
4455proc main!() {
66- with body!() when 'eff then {} else yield
66+ with body!() { when 'eff then {} }
77}
+2-1
testsuite/effects-just-cancel/main.tri
···33}
4455proc main!() {
66- let x = with inner!()
66+ let x = with inner!() {
77 when 'eff cancel 2
88 else yield
99+ }
910 assert x == 2
1011}
+2-1
testsuite/effects-just-resume/main.tri
···33}
4455proc main!() {
66- with inner!()
66+ with inner!() {
77 when 'eff resume 1
88 else yield
99+ }
910 assert "Unreachable" as false
1011}
+3-2
testsuite/effects-nested-cancel/main.tri
···66}
7788proc do_things!() {
99- with do_inner!() else yield
99+ with do_inner!() { else yield }
1010 assert "don't go here" as false
1111 return false
1212}
13131414proc main!() {
1515- assert 'hello == with do_things!()
1515+ assert 'hello == with do_things!() {
1616 when 'get_hello cancel 'hello
1717 else yield
1818+ }
1819 println!("Made it to end")
1920}
+6-4
testsuite/effects-nested/main.tri
···12121313proc do_things!() {
1414 return d!(8,
1515- with d!(6, do_inner!())
1616- else eff then {
1515+ with d!(6, do_inner!()) {
1616+ when eff then {
1717 cancel d!(7,
1818 resume d!(4,
1919 yield d!(2, eff)
2020 )
2121 )
2222 }
2323+ }
2324 )
2425}
25262627proc main!() {
2727- assert d!(11, with d!(9, do_things!())
2828+ assert d!(11, with d!(9, do_things!()) {
2829 when 'get_hello cancel d!(10, resume d!(3, 'hello))
2929- else yield)
3030+ else yield
3131+ })
3032 dbg!("Made it to end")
3133}
+1-1
testsuite/effects-none-yielded/main.tri
···33}
4455proc main!() {
66- let y = with body!() else yield
66+ let y = with body!() { else yield }
77 assert y == 5
88}
+2-2
testsuite/effects-resume-multiple/main.tri
···66}
7788proc main!() {
99- let result = with inner!()
99+ let result = with inner!() {
1010 when a:b then {
1111 let first = resume a
1212 let second = resume b
1313 cancel first:second
1414 }
1515- else yield
1515+ }
1616 assert "result is ${result}" as result == 1:2
1717}
+2-1
testsuite/effects-skip-handler/main.tri
···44}
5566proc outer!() {
77- return with inner!()
77+ return with inner!() {
88 when 'done then { return 3 }
99 else yield
1010+ }
1011}
11121213proc main!() {
+2-1
testsuite/effects-through-more-returns/main.tri
···1111}
12121313proc main!() {
1414- let x = with process!()
1414+ let x = with process!() {
1515 when 'both then {
1616 let a = resume true
1717 let b = resume false
1818 cancel a:b
1919 }
2020 else yield
2121+ }
2122 assert x == (('a:'c):('a:'d)):(('b:'c):('b:'d))
2223}
+2-1
testsuite/effects-through-return/main.tri
···1010}
11111212proc main!() {
1313- let result = with inner!()
1313+ let result = with inner!() {
1414 when a:b then {
1515 let first = resume a
1616 let second = resume b
1717 cancel first:second
1818 }
1919 else yield
2020+ }
2021 assert "result is ${result}" as result == 1:2
2122}
+1-1
testsuite/effects-yield-fallback/main.tri
···33}
4455proc main!() {
66- with body!() else yield
66+ with body!() { else yield }
77 exit 1
88}
+2-2
testsuite/effects-yield-in-loop/main.tri
···12121313proc main!() {
1414 let mut x = 0
1515- let result = with the_loop!()
1515+ let result = with the_loop!() {
1616 when 'a(a) then {
1717 let 'b(b) = resume 'b(a)
1818 debug::dbg!('handler(b))
1919 cancel 'b(b + 1)
2020 }
2121- else yield
2121+ }
2222 assert result == 'b(3)
2323}
+2-2
testsuite/effects-yield-into-call/main.tri
···55}
6677proc main!() {
88- with inner!()
88+ with inner!() {
99 when 'a then {
1010 resume 1
1111 become 2
1212 }
1313- else yield
1313+ }
1414}
+3-2
testsuite/effects-yield-nested/main.tri
···66}
7788proc do_things!() {
99- return with do_inner!() else yield
99+ return with do_inner!() { else yield }
1010}
11111212proc main!() {
1313- assert with do_things!()
1313+ assert with do_things!() {
1414 when 'get_hello resume 'hello
1515 else yield
1616+ }
1617 println!("Made it to end")
1718}
+4-4
testsuite/koka-example/main.tri
···55}
6677proc choice!(action) {
88- return with [action!()]
88+ return with [action!()] {
99 when 'choice then {
1010 cancel [..resume false, ..resume true]
1111 }
1212- else yield
1212+ }
1313}
14141515proc surprising!() {
···21212222proc pstate!(init, action) {
2323 let mut state = init
2424- let result = with action!()
2424+ let result = with action!() {
2525 when 'get resume state
2626 when 'set(val) then {
2727 state = val
2828 become unit
2929 }
3030- else yield
3030+ }
3131 return result:state
3232}
3333
···11import "trilogy:io" use println
2233proc inner!() {
44- with return 3
44+ with return 3 {
55 when 'eff then {
66 println!("hello")
77 cancel false
88 }
99 else yield
1010+ }
1011}
11121213proc outer!() {
···1516}
16171718proc main!() {
1818- assert with outer!() when 'eff cancel true else cancel false
1919+ assert with outer!() { when 'eff cancel true else cancel false }
1920}
+2-1
testsuite/recursion-depth-yields/main.tri
···33proc recursive!(i) {
44 if i % 100_000 == 0 { dbg!(i) }
55 if i == 1_000_000 { return unit }
66- with yield 'recurse
66+ with yield 'recurse {
77 when 'recurse resume recursive!(i + 1)
88 else yield
99+ }
910}
10111112proc main!() {
+2-2
testsuite/unison-example/main.tri
···991010proc in_memory_with_map!(action) {
1111 let mut map = {||}
1212- let result = with action!()
1212+ let result = with action!() {
1313 when 'get(k) resume match map {
1414 case {| ^k => v, .._ |} then 'some(v)
1515 else 'none
···1818 map.k = v
1919 become unit
2020 }
2121- else yield
2121+ }
2222 return result:map
2323}
2424
+1-6
trilogy-ir/src/ir/handler.rs
···7474 converter.scope.set_allow_resume_cancel(false);
7575 let else_span = handler.else_token().span;
7676 let effect = Identifier::temporary(converter, else_span);
7777- let pattern = handler
7878- .identifier
7979- .map(|id| Expression::reference(id.span(), Identifier::declare(converter, id)))
8080- .unwrap_or_else(|| Expression::wildcard(else_span));
8181- let pattern = Expression::reference(else_span, effect.clone())
8282- .and(else_span.union(pattern.span), pattern);
7777+ let pattern = Expression::reference(else_span, effect.clone());
8378 let guard = Expression::boolean(else_span, true);
8479 converter.scope.set_allow_resume_cancel(true);
8580 let body = Self::convert_strategy(converter, handler.strategy, effect);
+8-4
trilogy-llvm/src/expression/mod.rs
···338338 self.begin_next_function(next_case_function);
339339 }
340340341341- // A handler is always complete by the syntax requiring an `else` case at the end, so the last
342342- // branch is never reachable.
343343- let unreachable = self.builder.build_unreachable().unwrap();
344344- self.end_continuation_point_as_clean(unreachable);
341341+ self.push_handler_scope(resume);
342342+ let effect = self.use_temporary_clone(effect).unwrap();
343343+ let returned = self.call_yield(effect, "");
344344+ let resumed = self.call_resume(returned, "");
345345+ let cancel = self.allocate_value("");
346346+ self.trilogy_value_clone_into(cancel, self.get_cancel());
347347+ self.call_known_continuation(cancel, resumed);
348348+ self.pop_handler_scope();
345349 }
346350347351 fn compile_assertion(&self, assertion: &ir::Assert, name: &str) -> Option<PointerValue<'ctx>> {
···112112113113test "array reduce" {
114114 assert reduce (+) [1, 2, 3, 4] == 10
115115- assert with (reduce (+) []; false)
116116- when 'mia cancel true
117117- else yield
115115+ assert with (reduce (+) []; false) { when 'mia cancel true }
118116 assert reduce (:) [1, 2, 3] == (1:2):3
119117}
120118···123121124122test "array rreduce" {
125123 assert rreduce (+) [1, 2, 3, 4] == 10
126126- assert with (rreduce (+) []; false)
127127- when 'mia cancel true
128128- else yield
124124+ assert with (rreduce (+) []; false) { when 'mia cancel true }
129125 assert rreduce (:) [1, 2, 3] == (3:2):1
130126}
131127···172168173169test "array first" {
174170 assert first [1, 2, 3] == 1
175175- assert with (first []; false)
176176- when 'mia cancel true
177177- else yield
171171+ assert with (first []; false) { when 'mia cancel true }
178172}
179173180174func last [] = yield 'mia
···182176183177test "array last" {
184178 assert last [1, 2, 3] == 3
185185- assert with (last []; false)
186186- when 'mia cancel true
187187- else yield
179179+ assert with (last []; false) { when 'mia cancel true }
188180}
189181190182func tail [] = yield 'mia
···192184193185test "array tail" {
194186 assert tail [1, 2, 3] == [2, 3]
195195- assert with (tail []; false)
196196- when 'mia cancel true
197197- else yield
187187+ assert with (tail []; false) { when 'mia cancel true }
198188}
199189200190func head [] = yield 'mia
···202192203193test "array head" {
204194 assert head [1, 2, 3] == [1, 2]
205205- assert with (head []; false)
206206- when 'mia cancel true
207207- else yield
195195+ assert with (head []; false) { when 'mia cancel true }
208196}
209197210198func slice i fin (arr and typeof 'array) = core::slice i fin arr
···214202 assert slice 1 2 [1, 2, 3] == [2]
215203 assert slice 1 1 [1, 2, 3] == []
216204 assert slice 1 3 [1, 2, 3] == [2, 3]
217217- assert with (slice (-1) 2 [1, 2, 3]; false)
218218- when 'arg cancel true
219219- else yield
220220- assert with (slice 2 1 [1, 2, 3]; false)
221221- when 'arg cancel true
222222- else yield
223223- assert with (slice 0 5 [1, 2, 3]; false)
224224- when 'mia cancel true
225225- else yield
226226- assert with (slice 5 5 [1, 2, 3]; false)
227227- when 'mia cancel true
228228- else yield
205205+ assert with (slice (-1) 2 [1, 2, 3]; false) { when 'arg cancel true }
206206+ assert with (slice 2 1 [1, 2, 3]; false) { when 'arg cancel true }
207207+ assert with (slice 0 5 [1, 2, 3]; false) { when 'mia cancel true }
208208+ assert with (slice 5 5 [1, 2, 3]; false) { when 'mia cancel true }
229209}
230210231211func take n (arr and typeof 'array) =
···239219 assert take 2 [1, 2, 3] == [1, 2]
240220 assert take 3 [1, 2, 3] == [1, 2, 3]
241221 assert take 12 [1, 2, 3] == [1, 2, 3]
242242- assert with (take (-1) [1, 2, 3]; false)
243243- when 'arg cancel true
244244- else yield
222222+ assert with (take (-1) [1, 2, 3]; false) { when 'arg cancel true }
245223}
246224247225func skip n (arr and typeof 'array) =
···255233 assert skip 2 [1, 2, 3] == [3]
256234 assert skip 3 [1, 2, 3] == []
257235 assert skip 12 [1, 2, 3] == []
258258- assert with (skip (-1) [1, 2, 3]; false)
259259- when 'arg cancel true
260260- else yield
236236+ assert with (skip (-1) [1, 2, 3]; false) { when 'arg cancel true }
261237}
262238263239func drop n (arr and typeof 'array) =
···271247 assert drop 2 [1, 2, 3] == [1]
272248 assert drop 3 [1, 2, 3] == []
273249 assert drop 12 [1, 2, 3] == []
274274- assert with (drop (-1) [1, 2, 3]; false)
275275- when 'arg cancel true
276276- else yield
250250+ assert with (drop (-1) [1, 2, 3]; false) { when 'arg cancel true }
277251}
278252279253func collect iterator =
280254 let arr = [],
281281- with (iterator!(); arr)
255255+ with (iterator!(); arr) {
282256 when 'next(val) then {
283257 push!(arr, val)
284258 become unit
285259 }
286286- else yield
260260+ }
287261288262test "array collect" {
289263 let iterator = do() {
···302276 assert chunks 3 [1, 2, 3, 4, 5, 6, 7, 8, 9] == [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
303277 assert chunks 3 [1, 2, 3, 4, 5, 6, 7] == [[1, 2, 3], [4, 5, 6], [7]]
304278 assert chunks 1 [1, 2, 3] == [[1], [2], [3]]
305305- with chunks 0 when 'arg cancel unit else yield
279279+ with chunks 0 { when 'arg cancel unit }
306280}
307281308282func merge _ a [] = a
+3-2
trilogy/src/stdlib/core.tri
···405405406406 for test_name:test_procedure in tests {
407407 c::print!("test ${test_name} ... ")
408408- with test_procedure!()
408408+ with test_procedure!() {
409409 when 'assertion_failed(msg) then {
410410 c::print!(red "assertion failed")
411411 c::print!(": ${msg}\n")
412412 failures += 1
413413 continue unit
414414 }
415415- else eff then {
415415+ when eff then {
416416 c::print!(red "failure")
417417 c::print!(": unhandled effect yielded from test: ${eff}\n")
418418 failures += 1
419419 continue unit
420420 }
421421+ }
421422 c::print!(green "ok")
422423 c::print!("\n")
423424 successes += 1
+2-2
trilogy/src/stdlib/grid.tri
···8383}
84848585proc shortest_path_length!(grid, from, to) {
8686- return with algorithm::shortest_path_length!(from, to)
8686+ return with algorithm::shortest_path_length!(from, to) {
8787 when 'neighbours(from_pos) resume
8888 adjacent from_pos
8989 |> it::from
9090 |> it::filter (fn p. contains_key p grid)
9191 |> it::map (fn p. p:grid.p)
9292 |> array::collect
9393- else yield
9393+ }
9494}
+2-2
trilogy/src/stdlib/heap.tri
···52525353 func collect iterator =
5454 let heap = [],
5555- with (iterator!(); heap)
5555+ with (iterator!(); heap) {
5656 when 'next(val) then {
5757 push!(heap, val)
5858 become unit
5959 }
6060- else yield
6060+ }
6161}
62626363test "heap push" {
+2-2
trilogy/src/stdlib/io.tri
···4242export readlines
4343proc readlines!() {
4444 while true {
4545- let line = with readline!()
4545+ let line = with readline!() {
4646 when 'eof cancel break unit
4747- else yield
4747+ }
4848 yield 'next(line)
4949 }
5050}
+40-38
trilogy/src/stdlib/iterator.tri
···3131}
32323333test "iterator of" {
3434- assert 3 == with run <| of 3 when 'next(val) cancel val else yield
3535- assert unit == with run <| of 3 when 'next(3) resume 1 else yield
3434+ assert 3 == with run <| of 3 { when 'next(val) cancel val }
3535+ assert unit == with run <| of 3 { when 'next(3) resume 1 }
3636 assert collect <| of 3 == [3]
3737}
3838···48484949func take n it = do() {
5050 let mut i = 0
5151- with it!()
5151+ with it!() {
5252 when 'next(val) if i < n then {
5353 i += 1
5454 become yield 'next(val)
5555 }
5656 when 'next(_) cancel unit
5757- else yield
5757+ }
5858}
59596060test "iterator take" {
···6969func chunks 0 _ = yield 'arg
7070func chunks n it = do() {
7171 let mut chunk = []
7272- with it!()
7272+ with it!() {
7373 when 'next(item) then {
7474 chunk = [..chunk, item]
7575 if array::length chunk == n {
···7878 }
7979 become unit
8080 }
8181- else yield
8181+ }
8282 if chunk != [] { yield 'next(chunk) }
8383}
8484···8686 assert collect <| chunks 3 <| range 1 9 == [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
8787 assert collect <| chunks 3 <| range 1 7 == [[1, 2, 3], [4, 5, 6], [7]]
8888 assert collect <| chunks 1 <| range 1 3 == [[1], [2], [3]]
8989- with chunks 0 when 'arg cancel unit else yield
8989+ with chunks 0 { when 'arg cancel unit }
9090}
91919292func range_step _ _ 0 = yield 'arg
···142142}
143143144144func filter predicate it = do() {
145145- with it!()
145145+ with it!() {
146146 when 'next(val) if predicate val resume yield 'next(val)
147147 when 'next(_) resume unit
148148- else yield
148148+ }
149149}
150150151151test "iterator filter" {
···153153}
154154155155func map f it = do() {
156156- with it!()
156156+ with it!() {
157157 when 'next(val) resume yield 'next(f val)
158158- else yield
158158+ }
159159}
160160161161test "iterator map" {
···163163}
164164165165func flat_map f it = do() {
166166- with it!()
166166+ with it!() {
167167 when 'next(val) then {
168168 let inner = f val
169169 inner!()
170170 become unit
171171 }
172172- else yield
172172+ }
173173}
174174175175test "iterator flat_map" {
···178178179179func scan f a it = do() {
180180 let mut state = a
181181- with it!()
181181+ with it!() {
182182 when 'next(val) then {
183183 state = f state val
184184 become yield 'next(state)
185185 }
186186- else yield
186186+ }
187187}
188188189189test "iterator scan" {
···192192193193func fold f a it =
194194 let mut state = a,
195195- with it!(); state
195195+ with it!(); state {
196196 when 'next(val) then {
197197 state = f state val
198198 become unit
199199 }
200200- else yield
200200+ }
201201202202test "iterator fold" {
203203 assert fold (:) 0 <| range 1 5 == ((((0:1):2):3):4):5
···206206func reduce f it =
207207 let mut state = 'none,
208208 with
209209- it!();
210210- match state {
211211- case 'some(v) then v
212212- else yield 'mia
213213- }
209209+ it!();
210210+ match state {
211211+ case 'some(v) then v
212212+ else yield 'mia
213213+ }
214214+ {
214215 when 'next(val) then {
215216 state = match state {
216217 case 'some(prev) then 'some(f prev val)
···218219 }
219220 become unit
220221 }
221221- else yield
222222+ }
222223223224test "iterator reduce" {
224225 assert reduce (:) <| range 1 5 == (((1:2):3):4):5
225225- assert with reduce (:) <| rangex 0 0 when 'mia cancel true else cancel false
226226+ assert with reduce (:) <| rangex 0 0 { when 'mia cancel true else cancel false }
226227}
227228228229func sum it = fold (+) 0 it
···238239}
239240240241func any predicate it =
241241- with it!(); false
242242+ with it!(); false {
242243 when 'next(val) then {
243244 if predicate val {
244245 return true
245246 }
246247 become unit
247248 }
248248- else yield
249249+ }
249250250251test "iterator any" {
251252 assert any ((==) 2) <| range 1 3
···254255}
255256256257func all predicate it =
257257- with it!(); true
258258+ with it!(); true {
258259 when 'next(val) then {
259260 if !(predicate val) {
260261 return false
261262 }
262263 become unit
263264 }
264264- else yield
265265+ }
265266266267test "iterator all" {
267268 assert !(all (fn x. x < 2) <| range 1 3)
···271272272273func enumerate it = do() {
273274 let mut i = 0
274274- with it!()
275275+ with it!() {
275276 when 'next(v) then {
276277 let j = i
277278 i += 1
278279 become yield 'next(j:v)
279280 }
280280- else yield
281281+ }
281282}
282283283284test "iterator enumerate" {
···285286}
286287287288func find p it =
288288- with it!(); yield 'mia
289289+ with it!(); yield 'mia {
289290 when 'next(v) then {
290291 if p v {
291292 return v
292293 }
293294 become unit
294295 }
295295- else yield
296296+ }
296297297298test "iterator find" {
298299 assert find ((==) 4) <| range 3 5 == 4
299299- assert with find ((==) 4) <| range 1 3 when 'mia cancel true else cancel false
300300+ assert with find ((==) 4) <| range 1 3 { when 'mia cancel true else cancel false }
300301}
301302302303func choose 0 _ = do() yield 'next([])
···311312 assert collect <| choose 0 [1, 2, 3] == [[]]
312313}
313314314314-func for_each f it = with it!(); unit
315315- when 'next(v) then {
316316- f v
317317- become unit
315315+func for_each f it =
316316+ with it!(); unit {
317317+ when 'next(v) then {
318318+ f v
319319+ become unit
320320+ }
318321 }
319319- else yield
320322321323test "iterator for_each" {
322324 let arr = []
+16-16
trilogy/src/stdlib/parsec.tri
···2525func run_parser parser input =
2626 let len = core::length input,
2727 let mut pos = 0,
2828- let result = with parser!()
2828+ let result = with parser!() {
2929 when 'eof if pos == len resume true
3030 when 'eof resume false
3131 when 'pos resume pos
···3939 pos += 1
4040 become unit
4141 }
4242- else yield,
4242+ },
4343 result : core::slice pos len input
44444545## Parses the parser as a single atomic unit, without consuming any of the input on failure.
4646func atomic parser = do() {
4747 let pos = yield 'pos
4848- return with apply parser
4848+ return with apply parser {
4949 when 'reject(_) and rej then {
5050 yield 'reset(pos)
5151 yield rej
5252 }
5353- else yield
5353+ }
5454}
55555656## Transform the output value of a parser without parsing any more input.
···7070## Attempt a parser, returning 'some(result) if it succeeds. If it fails,
7171## returns 'none without consuming any input.
7272func option parser = do()
7373- with 'some(apply <| atomic parser)
7373+ with 'some(apply <| atomic parser) {
7474 when 'reject(_) cancel 'none
7575- else yield
7575+ }
76767777## Attempt each of the list of parsers. Returns the value of the first
7878## parser that succeeds.
7979func choice [] = do() yield 'reject("choice had no options")
8080func choice [parser, ..rest] = do () {
8181- return with apply <| atomic parser
8282- when 'reject(err) cancel with apply <| choice rest
8181+ return with apply <| atomic parser {
8282+ when 'reject(err) cancel with apply <| choice rest {
8383 when 'reject("choice had no options") then {
8484 yield 'reject(err)
8585 end
···8888 yield 'reject("${err}, or ${errs}")
8989 end
9090 }
9191- else yield
9292- else yield
9191+ }
9292+ }
9393}
94949595## Applies the parser as many times as possible, returning an array of
9696## the parsed results.
9797func many parser = do() {
9898- let result = with apply <| atomic parser
9898+ let result = with apply <| atomic parser {
9999 when 'reject(_) then { return [] }
100100- else yield
100100+ }
101101 return [result, ..apply <| many parser]
102102}
103103···248248249249test "parsec digit" {
250250 assert parse digit "123" == '1'
251251- assert with parse digit "A"; false when 'reject(_) cancel true else cancel false
251251+ assert with parse digit "A"; false { when 'reject(_) cancel true else cancel false }
252252}
253253254254## A parser for any base-16 digit.
···259259test "parsec hex_digit" {
260260 assert parse hex_digit "123" == '1'
261261 assert parse hex_digit "abc" == 'a'
262262- assert with parse hex_digit "Z"; false when 'reject(_) cancel true else cancel false
262262+ assert with parse hex_digit "Z"; false { when 'reject(_) cancel true else cancel false }
263263}
264264265265## Parses a base-10 integer from a string, returning the value as a number. A leading `-` sign
···300300301301test "parsec letter" {
302302 assert parse letter "a" == 'a'
303303- assert with parse letter "1"; false when 'reject(_) cancel true else cancel false
303303+ assert with parse letter "1"; false { when 'reject(_) cancel true else cancel false }
304304}
305305306306## A parser for any ASCII whitespace.
···310310311311test "parsec whitespace" {
312312 assert parse whitespace " " == ' '
313313- assert with parse whitespace "1"; false when 'reject(_) cancel true else cancel false
313313+ assert with parse whitespace "1"; false { when 'reject(_) cancel true else cancel false }
314314}
315315316316## A parser for any word (a sequence of word characters `[A-Za-z0-9_]`).
+2-2
trilogy/src/stdlib/record.tri
···29293030func collect iterator =
3131 let record = {||},
3232- with (iterator!(); record)
3232+ with (iterator!(); record) {
3333 when 'next(key:val) then {
3434 record.key = val
3535 become unit
3636 }
3737- else yield
3737+ }
38383939test "record collect" {
4040 let iterator = do() {
+2-2
trilogy/src/stdlib/set.tri
···51515252func collect iterator =
5353 let set = [||],
5454- with (iterator!(); set)
5454+ with (iterator!(); set) {
5555 when 'next(val) then {
5656 push!(set, val)
5757 become unit
5858 }
5959- else yield
5959+ }
60606161test "set collect" {
6262 let iterator = do() {
+9-23
trilogy/src/stdlib/string.tri
···4343 assert slice 1 2 "123" == "2"
4444 assert slice 1 1 "123" == ""
4545 assert slice 1 3 "123" == "23"
4646- assert with (slice (-1) 2 "123"; false)
4747- when 'arg cancel true
4848- else yield
4949- assert with (slice 2 1 "123"; false)
5050- when 'arg cancel true
5151- else yield
5252- assert with (slice 0 5 "123"; false)
5353- when 'mia cancel true
5454- else yield
5555- assert with (slice 5 5 "123"; false)
5656- when 'mia cancel true
5757- else yield
4646+ assert with (slice (-1) 2 "123"; false) { when 'arg cancel true }
4747+ assert with (slice 2 1 "123"; false) { when 'arg cancel true }
4848+ assert with (slice 0 5 "123"; false) { when 'mia cancel true }
4949+ assert with (slice 5 5 "123"; false) { when 'mia cancel true }
5850}
59516052func take n (str and typeof 'string) =
···6860 assert take 2 "123" == "12"
6961 assert take 3 "123" == "123"
7062 assert take 12 "123" == "123"
7171- assert with (take (-1) "123"; false)
7272- when 'arg cancel true
7373- else yield
6363+ assert with (take (-1) "123"; false) { when 'arg cancel true }
7464}
75657666func skip n (str and typeof 'string) =
···8474 assert skip 2 "123" == "3"
8575 assert skip 3 "123" == ""
8676 assert skip 12 "123" == ""
8787- assert with (skip (-1) "123"; false)
8888- when 'arg cancel true
8989- else yield
7777+ assert with (skip (-1) "123"; false) { when 'arg cancel true }
9078}
91799280func drop n (str and typeof 'string) =
···10088 assert drop 2 "123" == "1"
10189 assert drop 3 "123" == ""
10290 assert drop 12 "123" == ""
103103- assert with (drop (-1) "123"; false)
104104- when 'arg cancel true
105105- else yield
9191+ assert with (drop (-1) "123"; false) { when 'arg cancel true }
10692}
1079310894func starts_with prefix string = take (length prefix) string == prefix
···208194209195func collect iterator =
210196 let mut str = "",
211211- with (iterator!(); str)
197197+ with (iterator!(); str) {
212198 when 'next(val) then {
213199 str <>= core::to_string val
214200 become unit
215201 }
216216- else yield
202202+ }
217203218204test "string collect" {
219205 let string_iter = do() {