books.bend source
books.bend on the hub · documented module
import Baseimport ./books_data.bend as Dtype Phase is Data: Scan{} Hit{eq: Bool}# Finite table walk; Phase tag encodes the old mutual recursion.@unsafe def find_alias(ph: Phase, xs: List<D.Alias>, +key: String, held: String) -> Maybe<&2, String>: match ph: case Scan{}: match xs: case Nil{}: None{} case D.Alias{+k, c} <> t: find_alias(Hit{String.eq(k, key)}, t, key, c) case Hit{eq}: match eq: case True{}: Some{held} case False{}: find_alias(Scan{}, xs, key, held)type SpSt is Data: SpCheck{} SpDecide{keep: Bool} SpTake{}def is_space_char(+c: Char) -> Bool: Char.is_space(c)def char1(+c: Char) -> String: String.from_list(c <> Nil{})@unsafe def strip_spaces_go(st: SpSt, rest: String, acc: String) -> String: match st: case SpCheck{}: match rest: case SNil{}: acc case SCon{+h, +t}: strip_spaces_go(SpDecide{Bool.not(Char.is_space(h))}, rest, acc) case SpDecide{keep}: match keep: case True{}: strip_spaces_go(SpTake{}, rest, acc) case False{}: match rest: case SNil{}: acc case SCon{h, t}: strip_spaces_go(SpCheck{}, t, acc) case SpTake{}: match rest: case SNil{}: acc case SCon{+h, +t}: strip_spaces_go(SpCheck{}, t, String.append(acc, char1(h)))def strip_spaces(+s: String) -> String: strip_spaces_go(SpCheck{}, s, "")def resolve_alias(+raw: String) -> Maybe<&2, String>: find_alias(Scan{}, D.alias_table(), strip_spaces(String.to_lower(raw)), "")@unsafe def find_cap(ph: Phase, xs: List<D.Cap>, +key: String, held: U32) -> Maybe<&2, U32>: match ph: case Scan{}: match xs: case Nil{}: None{} case D.Cap{+k, n} <> t: find_cap(Hit{String.eq(k, key)}, t, key, n) case Hit{eq}: match eq: case True{}: Some{held} case False{}: find_cap(Scan{}, xs, key, held)def chapter_count(+book: String) -> Maybe<&2, U32>: find_cap(Scan{}, D.chapter_caps(), book, 0)def verse_count(+book: String, +ch: U32) -> Maybe<&2, U32>: find_cap( Scan{}, D.verse_caps(), String.append(String.append(book, "."), U32.show(ch)), 0 )@unsafe def find_name(ph: Phase, xs: List<D.BookName>, +code: String, held: String) -> String: match ph: case Scan{}: match xs: case Nil{}: held case D.BookName{+c, name} <> t: find_name(Hit{String.eq(c, code)}, t, code, name) case Hit{eq}: match eq: case True{}: held case False{}: find_name(Scan{}, xs, code, held)def display_name(+code: String) -> String: find_name(Scan{}, D.book_names(), code, code)