0 | module Text.ILex.Char.Range
2 | import Derive.Prelude
5 | %language ElabReflection
12 | interface Ord a => WithBounds a where
17 | WithBounds Bits8 where
22 | WithBounds Bits16 where
27 | WithBounds Bits32 where
29 | maxBound = 0xffff_ffff
32 | WithBounds Bits64 where
34 | maxBound = 0xffff_ffff_ffff_ffff
45 | data RangeOf : (t : Type) -> Type where
47 | Rng : (low,up : t) -> RangeOf t
49 | %runElab derive "RangeOf" [Show,Eq,Ord]
53 | Range8 = RangeOf Bits8
57 | Range32 = RangeOf Bits32
66 | singleton : t -> RangeOf t
67 | singleton v = Rng v v
70 | isEmpty : RangeOf t -> Bool
71 | isEmpty Empty = True
77 | range : Ord t => (x,y : t) -> RangeOf t
85 | has : Ord t => RangeOf t -> t -> Bool
87 | has (Rng x y) v = x <= v && v <= y
91 | overlap : Ord t => RangeOf t -> RangeOf t -> Bool
92 | overlap r1@(Rng l1 u1) r2@(Rng l2 u2) = has r1 l2 || has r2 l1
97 | span : Ord t => RangeOf t -> RangeOf t -> RangeOf t
98 | span r1@(Rng l1 u1) r2@(Rng l2 u2) = Rng (min l1 l2) (max u1 u2)
104 | intersection : Ord t => RangeOf t -> RangeOf t -> RangeOf t
105 | intersection (Rng l1 u1) (Rng l2 u2) =
106 | if l1 <= l2 then range l2 (min u1 u2) else range l1 (min u2 u1)
107 | intersection _ _ = Empty
109 | parameters {0 t : Type}
114 | fromTill : (x,y : t) -> RangeOf t
117 | True => range x (y-1)
120 | afterTo : (x,y : t) -> RangeOf t
123 | True => range (x+1) y
129 | adjacent : RangeOf t -> RangeOf t -> Bool
130 | adjacent (Rng l1 u1) (Rng l2 u2) =
131 | (u1 < l2 && (u1+1) == l2) || (u2 < l1 && (u2+1) == l1)
132 | adjacent _ _ = False
139 | union : RangeOf t -> RangeOf t -> Either (RangeOf t) (RangeOf t,RangeOf t)
140 | union r1@(Rng l1 u1) r2@(Rng l2 u2) =
141 | if overlap r1 r2 || adjacent r1 r2
142 | then Left (span r1 r2)
143 | else Right (min r1 r2, max r1 r2)
144 | union Empty r = Left r
145 | union l Empty = Left l
152 | difference : RangeOf t -> RangeOf t -> Either (RangeOf t) (RangeOf t,RangeOf t)
153 | difference r1@(Rng l1 u1) r2@(Rng l2 u2) =
154 | case overlap r1 r2 of
156 | let x@(Rng _ _) := fromTill l1 l2 | Empty => Left (afterTo u2 u1)
157 | y@(Rng _ _) := afterTo u2 u1 | Empty => Left x
158 | in Right (min x y, max x y)
160 | difference Empty r = Left Empty
161 | difference l Empty = Left l
165 | codepoint : Range32
166 | codepoint = Rng 0 0x10ffff
170 | surrogate : Range32
171 | surrogate = Rng 0xd800 0xdfff
175 | charRange : (x,y : Char) -> Range32
176 | charRange x y = range (cast x) (cast y)
180 | fullRange : WithBounds t => RangeOf t
181 | fullRange = Rng minBound maxBound
185 | isFull : WithBounds t => RangeOf t -> Bool
186 | isFull = (== fullRange)
189 | lowerBound : WithBounds t => RangeOf t -> t
190 | lowerBound (Rng l _) = l
191 | lowerBound Empty = maxBound
194 | upperBound : WithBounds t => RangeOf t -> t
195 | upperBound (Rng _ u) = u
196 | upperBound Empty = minBound