aoc2023/lib/string.quox

141 lines
4.1 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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 =
λ c ⇒ bool.or (bool.or (eq c space) (eq c tab)) (eq c newline)
def digit? : ω.Char → Bool =
λ c ⇒ bool.and (ge c (from- 0x30)) (le c (from- 0x39))
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 )
}
}
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)
#[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))
}