aoc2023/lib/string.quox

141 lines
4.1 KiB
Plaintext
Raw Normal View History

2023-12-06 21:47:23 -05:00
load "bool.quox"
load "list.quox"
load "maybe.quox"
load "either.quox"
namespace char {
postulate0 Char : ★
#[compile-scheme "(lambda (c) c)"]
postulate dup : Char → [ω.Char]
#[compile-scheme "char->integer"]
postulate to- : Char →
#[compile-scheme "integer->char"]
postulate from- : → Char
def space = from- 0x20
def tab = from- 0x09
def newline = from- 0x0a
def test-via- : (ω. → ω. → Bool) → (ω.Char → ω.Char → Bool) =
λ p c d ⇒ p (to- c) (to- d)
def lt = test-via- nat.lt
def eq = test-via- nat.eq
def gt = test-via- nat.gt
def le = test-via- nat.le
def ne = test-via- nat.ne
def ge = test-via- nat.ge
postulate0 eq-iff-nat : (c d : Char) → Iff (c ≡ d : Char) (to- c ≡ to- d : )
def eq? : DecEq Char =
λ c d ⇒
let0 Ty = (c ≡ d : Char) ∷ ★ in
dec.elim (to- c ≡ to- d : ) (λ _ ⇒ Dec Ty)
(λ y ⇒ Yes Ty ((snd (eq-iff-nat c d)) y))
(λ n ⇒ No Ty (λ y ⇒ n ((fst (eq-iff-nat c d)) y)))
(nat.eq? (to- c) (to- d))
def ws? : ω.Char → Bool =
2023-12-12 14:37:05 -05:00
λ c ⇒ bool.or (bool.or (eq c space) (eq c tab)) (eq c newline)
2023-12-06 21:47:23 -05:00
def digit? : ω.Char → Bool =
2023-12-12 14:37:05 -05:00
λ c ⇒ bool.and (ge c (from- 0x30)) (le c (from- 0x39))
2023-12-06 21:47:23 -05:00
2023-12-12 14:37:05 -05:00
def digit-val : Char → Maybe =
λ c ⇒ case dup c return Maybe of { [c] ⇒
bool.if (Maybe ) (digit? c)
(Just (nat.minus (to- c) 0x30))
(Nothing )
2023-12-06 21:47:23 -05:00
}
}
def0 Char = char.Char
namespace string {
#[compile-scheme "string->list"]
postulate to-scheme-list : String → list.SchemeList Char
def to-list : String → List Char =
λ str ⇒ list.from-scheme Char (to-scheme-list str)
#[compile-scheme "list->string"]
postulate from-scheme-list : list.SchemeList Char → String
def from-list : List Char → String =
λ cs ⇒ from-scheme-list (list.to-scheme Char cs)
def foldl : 0.(A : ★) → A → ω.(A → Char → A) → String → A =
λ A z f str ⇒ list.foldl Char A z f (to-list str)
def split : ω.(ω.Char → Bool) → ω.String → List String =
λ p str ⇒
list.map (List Char) String from-list
(list.split Char p (to-list str))
def break : ω.(ω.Char → Bool) → ω.String → String × String =
λ p str ⇒
letω pair = list.break Char p (to-list str) in
(from-list (fst pair), from-list (snd pair))
def reverse : String → String =
λ str ⇒ from-list (list.reverse Char (to-list str))
#[compile-scheme "(lambda% (a b) (if (string=? a b) 'true 'false))"]
postulate eq : ω.String → ω.String → Bool
def null : ω.String → Bool = eq ""
def not-null : ω.String → Bool = λ s ⇒ bool.not (null s)
2023-12-12 14:37:05 -05:00
#[compile-scheme "(lambda (str) str)"]
postulate dup : String → [ω.String]
postulate0 dup-ok : (str : String) → dup str ≡ [str] : [ω.String]
def dup! : (str : String) → Dup String str =
dup-from-parts String dup dup-ok
def to- : String → Maybe =
letω add-digit : Maybe → Maybe =
maybe.fold ( → Maybe ) (λ d ⇒ Just d)
(λ n d ⇒ Just (nat.plus (nat.times 10 n) d)) in
letω drop : Maybe → Maybe =
maybe.fold (Maybe ) (Nothing )
(λ n ⇒ nat.drop (Maybe ) n (Nothing )) in
letω add-digit-c : Maybe → Char → Maybe =
λ acc c ⇒
maybe.fold (Maybe → Maybe ) drop (λ n acc ⇒ add-digit acc n)
(char.digit-val c) acc in
λ str ⇒
case dup str return Maybe of { [str] ⇒
bool.if (Maybe ) (not-null str)
(foldl (Maybe ) (Just 0) add-digit-c str)
(Nothing )
}
def to--or-0 : String → =
λ str ⇒ maybe.fold 0 (λ x ⇒ x) (to- str)
#[compile-scheme
"(lambda% (yes no str)
(let [(len (string-length str))]
(if (= len 0)
no
(let [(first (string-ref str 0))
(rest (substring str 1 len))]
(% yes first rest)))))"]
postulate uncons' : 0.(A : ★) → ω.A → ω.(Char → String → A) → String → A
def uncons : String → Maybe (Char × String) =
let0 Ret : ★ = Char × String in
uncons' (Maybe Ret) (Nothing Ret) (λ c s ⇒ Just Ret (c, s))
2023-12-06 21:47:23 -05:00
}