~/bend-docscommunity

context.bend source

context.bend on the hub · documented module

# Paragraph-aware verse context (same-chapter; defaults maxBefore=3, maxAfter=3)import Baseimport ./books.bend as Booksimport ./para_data.bend as Paradef unmap_str(p: Map<&2, String> & String) -> String:  match p:    case (_, v):      vdef para_starts_str(+book: String, +ch: U32) -> String:  unmap_str(    Map.get(      String,      "",      Para.para_map(),      String.append(String.append(book, "."), U32.show(ch))    )  )def parse_u32_or0(m: Maybe<&2, U32>) -> U32:  match m:    case None{}:      0    case Some{n}:      ntype PsSt is Data:  PsCheck{}  PsDecide{sp: Bool}  PsTake{}  PsEmit{n: U32, empty_tok: Bool}  PsEnd{empty_tok: Bool}def parse_starts_go(fuel: Nat, st: PsSt, rest: String, +tok: String, acc: List<&2, U32>) -> List<&2, U32>:  match fuel:    case 0n:      acc    case 1n+p:      match st:        case PsCheck{}:          match rest:            case SNil{}:              parse_starts_go(p, PsEnd{String.is_empty(tok)}, rest, tok, acc)            case SCon{+h, +t}:              parse_starts_go(p, PsDecide{Char.is_space(h)}, rest, tok, acc)        case PsEnd{empty_tok}:          match empty_tok:            case True{}:              acc            case False{}:              parse_u32_or0(U32.read(tok)) <> acc        case PsDecide{sp}:          match sp:            case True{}:              parse_starts_go(p, PsEmit{parse_u32_or0(U32.read(tok)), String.is_empty(tok)}, rest, tok, acc)            case False{}:              parse_starts_go(p, PsTake{}, rest, tok, acc)        case PsEmit{+n, empty_tok}:          match empty_tok:            case True{}:              match rest:                case SNil{}:                  acc                case SCon{h, t}:                  parse_starts_go(p, PsCheck{}, t, "", acc)            case False{}:              match rest:                case SNil{}:                  n <> acc                case SCon{h, t}:                  parse_starts_go(p, PsCheck{}, t, "", n <> acc)        case PsTake{}:          match rest:            case SNil{}:              acc            case SCon{+h, +t}:              parse_starts_go(                p,                PsCheck{},                t,                String.append(tok, String.from_list(h <> Nil{})),                acc              )def rev_u32(xs: List<&2, U32>, acc: List<&2, U32>) -> List<&2, U32>:  match xs:    case Nil{}:      acc    case h <> t:      rev_u32(t, h <> acc)def parse_starts(+s: String) -> List<&2, U32>:  rev_u32(    parse_starts_go(      Nat.add(Nat.mul(5n, String.length(s)), 8n),      PsCheck{},      s,      "",      Nil{}    ),    Nil{}  )type FdPh is Data:  FdScan{}  FdTest{n: U32, ok: Bool}def find_para_start(fuel: Nat, ph: FdPh, xs: List<&2, U32>, +v: U32, best: U32) -> U32:  match fuel:    case 0n:      best    case 1n+p:      match ph:        case FdScan{}:          match xs:            case Nil{}:              best            case +n <> t:              find_para_start(p, FdTest{n, U32.is_le(n, v)}, t, v, best)        case FdTest{+n, ok}:          match ok:            case True{}:              find_para_start(p, FdScan{}, xs, v, n)            case False{}:              find_para_start(p, FdScan{}, xs, v, best)def next_para_hit(+n: U32, +found: U32, zero: Bool) -> U32:  match zero:    case True{}:      n    case False{}:      founddef next_para_after(fuel: Nat, ph: FdPh, xs: List<&2, U32>, +v: U32, +found: U32) -> U32:  match fuel:    case 0n:      found    case 1n+p:      match ph:        case FdScan{}:          match xs:            case Nil{}:              found            case +n <> t:              next_para_after(p, FdTest{n, U32.is_gt(n, v)}, t, v, found)        case FdTest{+n, ok}:          match ok:            case True{}:              next_para_hit(n, found, U32.is_zero(found))            case False{}:              next_para_after(p, FdScan{}, xs, v, found)def u32_max_go(+a: U32, +b: U32, le: Bool) -> U32:  match le:    case True{}:      b    case False{}:      adef u32_max(+a: U32, +b: U32) -> U32:  u32_max_go(a, b, U32.is_le(a, b))def u32_min_go(+a: U32, +b: U32, le: Bool) -> U32:  match le:    case True{}:      a    case False{}:      bdef u32_min(+a: U32, +b: U32) -> U32:  u32_min_go(a, b, U32.is_le(a, b))def u32_sub_sat_go(+a: U32, +b: U32, ok: Bool) -> U32:  match ok:    case True{}:      U32.sub(a, b)    case False{}:      0def u32_sub_sat(+a: U32, +b: U32) -> U32:  u32_sub_sat_go(a, b, U32.is_le(b, a))type FrPh is Data:  FrBody{}  FrStep{over: Bool}def fill_range_go(fuel: Nat, ph: FrPh, +cur: U32, +hi: U32, acc: List<&2, U32>) -> List<&2, U32>:  match fuel:    case 0n:      acc    case 1n+p:      match ph:        case FrBody{}:          fill_range_go(p, FrStep{U32.is_gt(cur, hi)}, cur, hi, acc)        case FrStep{over}:          match over:            case True{}:              acc            case False{}:              fill_range_go(p, FrBody{}, U32.add(cur, 1), hi, cur <> acc)def fill_range_cons(fuel: Nat, +cur: U32, +hi: U32, acc: List<&2, U32>) -> List<&2, U32>:  fill_range_go(fuel, FrBody{}, cur, hi, acc)def range_inclusive(+lo: U32, +hi: U32) -> List<&2, U32>:  rev_u32(fill_range_cons(200n, lo, hi, Nil{}), Nil{})def range_inclusive_go(+lo: U32, +hi: U32, empty: Bool) -> List<&2, U32>:  match empty:    case True{}:      Nil{}    case False{}:      range_inclusive(lo, hi)type Ctx is Data:  Ctx{    book: String,    chapter: U32,    verse: U32,    before: List<&2, U32>,    after: List<&2, U32>  }def para_hi_excl_go(+nxt: U32, +ch_max: U32, zero: Bool) -> U32:  match zero:    case True{}:      U32.add(ch_max, 1)    case False{}:      nxtdef para_hi_excl(+nxt: U32, +ch_max: U32) -> U32:  para_hi_excl_go(nxt, ch_max, U32.is_zero(nxt))def chapter_max_or(m: Maybe<&2, U32>) -> U32:  match m:    case None{}:      176    case Some{n}:      ndef mk_ctx(  +book: String,  +ch: U32,  +v: U32,  +para_lo: U32,  +para_hi_excl: U32,  +max_before: U32,  +max_after: U32) -> Ctx:  Ctx{    book,    ch,    v,    range_inclusive_go(      u32_max(u32_sub_sat(v, max_before), para_lo),      u32_sub_sat(v, 1),      U32.is_lt(u32_sub_sat(v, 1), u32_max(u32_sub_sat(v, max_before), para_lo))    ),    range_inclusive_go(      U32.add(v, 1),      u32_min(U32.add(v, max_after), u32_sub_sat(para_hi_excl, 1)),      U32.is_lt(        u32_min(U32.add(v, max_after), u32_sub_sat(para_hi_excl, 1)),        U32.add(v, 1)      )    )  }def expand_verse(  +book: String,  +ch: U32,  +v: U32,  +max_before: U32,  +max_after: U32) -> Ctx:  mk_ctx(    book,    ch,    v,    find_para_start(200n, FdScan{}, parse_starts(para_starts_str(book, ch)), v, 1),    para_hi_excl(      next_para_after(200n, FdScan{}, parse_starts(para_starts_str(book, ch)), v, 0),      chapter_max_or(Books.verse_count(book, ch))    ),    max_before,    max_after  )def expand_default(+book: String, +ch: U32, +v: U32) -> Ctx:  expand_verse(book, ch, v, 3, 3)def show_u32_list(xs: List<&2, U32>, acc: String) -> String:  match xs:    case Nil{}:      acc    case h <> Nil{}:      String.append(acc, U32.show(h))    case h <> t:      show_u32_list(t, String.append(String.append(acc, U32.show(h)), ","))def format_ctx(c: Ctx) -> String:  match c:    case Ctx{+book, +chapter, +verse, +before, +after}:      String.append(        String.append(          String.append(            String.append(book, "."),            String.append(U32.show(chapter), ".")          ),          String.append(U32.show(verse), " before=[")        ),        String.append(          String.append(show_u32_list(before, ""), "] after=["),          String.append(show_u32_list(after, ""), "]")        )      )