Files
orchid/src/libs/std/loop.orc
Lawrence Bethlenfalvy ed0d64d52e Almost Alpha
Massive improvements across the board.

One day I'll adopt incremental commits.
2024-02-24 00:31:00 +00:00

76 lines
2.3 KiB
Plaintext

import super::procedural::*
import super::bool::*
import super::fn::(return, identity)
import super::known::*
--[
Bare fixpoint combinator. Due to its many pitfalls, usercode is
recommended to use one of the wrappers such as [recursive] or
[loop_over] instead.
]--
export const Y := \f.(\x.f (x x))(\x.f (x x))
--[
A syntax construct that encapsulates the Y combinator and encourages
single tail recursion. It's possible to use this for multiple or
non-tail recursion by using cps statements, but it's more ergonomic
than [Y] and more flexible than [std::list::fold].
To break out of the loop, use [std::fn::return] in a cps statement
]--
export macro loop_over (..$binds) {
...$body
} =0x5p129=> Y (\r.
def_binds parse_binds (..$binds) do{
...$body;
r apply_binds parse_binds (..$binds)
}
) init_binds parse_binds (..$binds)
-- parse_binds builds a conslist
macro parse_binds (...$item, ...$tail:1) =0x2p250=> (
parse_bind (...$item)
parse_binds (...$tail)
)
macro parse_binds (...$item) =0x1p250=> (
parse_bind (...$item)
()
)
-- while loop
export macro statement (
while ..$condition (..$binds) {
...$body
}
) $next =0x5p129=> loop_over (..$binds) {
cps if (..$condition) then identity else return $next;
...$body;
}
-- parse_bind converts items to pairs
macro parse_bind ($name) =0x1p250=> ($name bind_no_value)
macro parse_bind ($name = ...$value) =0x1p250=> ($name (...$value))
-- def_binds creates name bindings for everything
macro def_binds ( ($name $value) $tail ) ...$body =0x1p250=> (
\$name. def_binds $tail ...$body
)
macro def_binds () ...$body =0x1p250=> ...$body
-- init_binds passes the value for initializers
macro init_binds ( ($name bind_no_value) $tail ) =0x2p250=> $name init_binds $tail
macro init_binds ( ($name $value) $tail ) =0x1p250=> $value init_binds $tail
-- avoid empty templates by assuming that there is a previous token
macro $fn init_binds () =0x1p250=> $fn
-- apply_binds passes the name for initializers
macro apply_binds ( ($name $value) $tail ) =0x1p250=> $name apply_binds $tail
macro $fn apply_binds () =0x1p250=> $fn
--[
Alias for the Y-combinator to avoid some universal pitfalls
]--
export macro recursive $name (..$binds) ...$body =0x5p129=> Y (\$name.
def_binds parse_binds (..$binds) ...$body
) init_binds parse_binds (..$binds)