0 | module Text.ByteBounds
2 | import Data.Array.Core
4 | import Data.ByteString
5 | import Derive.Prelude
6 | import public Text.Bounds
7 | import public Text.FC
8 | import public Text.ParseError
11 | %language ElabReflection
19 | record BytePos where
23 | %runElab derive "BytePos" [Show,Eq,Ord,FromInteger]
25 | public export %inline
26 | Interpolation BytePos where
27 | interpolate = show . pos
32 | incLen : Nat -> BytePos -> BytePos
33 | incLen (S n) (BP p) = BP (n+p)
41 | endPos : (from, till : Nat) -> BytePos
43 | case prim__lt_Integer (cast from) (cast till) of
49 | offsetTo : (ref,p : BytePos) -> BytePos
50 | offsetTo ref p = BP (p.pos `minus` ref.pos)
59 | data ByteBounds : Type where
60 | BB : (start, end : BytePos) -> ByteBounds
63 | %runElab derive "ByteBounds" [Show,Eq]
66 | Interpolation ByteBounds where
67 | interpolate (BB s e) = if s == e then "\{s}" else "\{s}--\{e}"
68 | interpolate NoBB = ""
71 | Semigroup ByteBounds where
74 | BB s1 e1 <+> BB s2 e2 = BB (min s1 s2) (max e1 e2)
77 | Monoid ByteBounds where
81 | interface MapBounds (0 a : Type) where
82 | mapBounds : (ByteBounds -> ByteBounds) -> a -> a
85 | clearBounds : MapBounds a => a -> a
86 | clearBounds = mapBounds (const NoBB)
89 | MapBounds ByteBounds where mapBounds = id
92 | MapBounds a => MapBounds (Maybe a) where
93 | mapBounds = map . mapBounds
96 | MapBounds a => MapBounds (List a) where
97 | mapBounds = map . mapBounds
100 | MapBounds a => MapBounds (SnocList a) where
101 | mapBounds = map . mapBounds
104 | MapBounds a => MapBounds b => MapBounds (a,b) where
105 | mapBounds f (x,y) = (mapBounds f x, mapBounds f y)
108 | MapBounds a => MapBounds b => MapBounds (Either a b) where
109 | mapBounds f (Left x) = Left $
mapBounds f x
110 | mapBounds f (Right x) = Right $
mapBounds f x
113 | fromPos : Cast t ByteBounds => BytePos -> t -> ByteBounds
114 | fromPos p x = BB p p <+> cast x
117 | tillPos : Cast t ByteBounds => t -> BytePos -> ByteBounds
118 | tillPos x p = cast x <+> BB p p
121 | Cast BytePos ByteBounds where cast b = BB b b
129 | record ByteBounded ty where
132 | bounds : ByteBounds
134 | %runElab derive "ByteBounded" [Show,Eq]
137 | fromBytePos : ByteBounded a -> BytePos -> ByteBounded a
138 | fromBytePos (B v $
BB (BP s) (BP e)) (BP p) = B v $
BB (BP $
s+p) (BP $
e+p)
139 | fromBytePos (B v NoBB) p = B v $
BB p p
142 | app : ByteBounded (a -> b) -> ByteBounded a -> ByteBounded b
143 | app (B vf b1) (B va b2) = B (vf va) (b1 <+> b2)
146 | bind : ByteBounded a -> (a -> ByteBounded b) -> ByteBounded b
149 | in B vb (b1 <+> b2)
152 | Functor ByteBounded where
153 | map f (B val bs) = B (f val) bs
156 | Applicative ByteBounded where
157 | pure v = B v neutral
161 | Monad ByteBounded where
165 | Foldable ByteBounded where
166 | foldr c n b = c b.val n
167 | foldl c n b = c n b.val
168 | foldMap f b = f b.val
173 | Traversable ByteBounded where
174 | traverse f (B v bs) = (`B` bs) <$> f v
177 | MapBounds (ByteBounded a) where mapBounds f = {bounds $= f}
184 | record PositionMap where
188 | arr : IArray size Position
190 | %runElab derive "PositionMap" [Show]
193 | Eq PositionMap where
194 | PM _ x == PM _ y = heq x y
197 | bytePositionMapFrom : Position -> ByteString -> PositionMap
198 | bytePositionMapFrom p (BS n bv) = PM (S n) $
positionMapFrom p bv
201 | stringPositionMapFrom : Position -> String -> PositionMap
202 | stringPositionMapFrom p = bytePositionMapFrom p . fromString
205 | bytePositionMap : ByteString -> PositionMap
206 | bytePositionMap (BS n bv) = PM (S n) $
positionMap bv
209 | stringPositionMap : String -> PositionMap
210 | stringPositionMap = bytePositionMap . fromString
212 | parameters {auto pm : PositionMap}
214 | position : BytePos -> Maybe Position
217 | Just0 x => Just $
atNat pm.arr n @{x}
218 | Nothing0 => Nothing
221 | toBounds : ByteBounds -> Bounds
222 | toBounds NoBB = NoBounds
223 | toBounds (BB x y) =
224 | let Just px := position x | _ => NoBounds
225 | Just py := position y | _ => NoBounds
229 | toBounded : ByteBounded a -> Bounded a
230 | toBounded (B v bs) = B v $
toBounds bs
233 | 0 BBErr : Type -> Type
234 | BBErr e = ByteBounded (InnerError e)
237 | injectBBErr : Cast e f => ByteBounded e -> BBErr f
238 | injectBBErr = map (Custom . cast)
243 | toParseError : Origin -> String -> BBErr e -> ParseError e
244 | toParseError o s err =
245 | let mp := stringPositionMap s
246 | in toParseError o s (toBounded err)
253 | record ByteContext where
256 | bounds : ByteBounds
258 | %runElab derive "ByteContext" [Show,Eq]
261 | Interpolation ByteContext where
262 | interpolate (BC o NoBB) = interpolate o
263 | interpolate (BC o bs) = "\{o}: \{bs}"
266 | MapBounds ByteContext where mapBounds f = {bounds $= f}
269 | record ByteError e where
272 | bounds : ByteBounds
273 | content : Maybe ByteString
276 | %runElab derive "ByteError" [Show,Eq]
279 | MapBounds (ByteError e) where mapBounds f = {bounds $= f}
282 | 0 ByteErr : Type -> Type
283 | ByteErr = ByteError . InnerError
286 | byteError : Origin -> ByteBounded e -> ByteError e
287 | byteError o (B err bs) = BE o bs Nothing err
289 | boundsPart : ByteBounds -> String
290 | boundsPart NoBB = ""
291 | boundsPart (BB s e) =
293 | True => ", byte \{s}"
294 | False => ", bytes \{s}--\{e}"
297 | prettyByteErr : Interpolation e => ByteError e -> String
298 | prettyByteErr (BE o bb m err) =
300 | Nothing => "Error at \{o}\{boundsPart bb}: \{err}"
302 | let mp := bytePositionMap bs
303 | in interpolate $
toParseError o (toString bs) (toBounded $
B err bb)
306 | Interpolation e => Interpolation (ByteError e) where
307 | interpolate = prettyByteErr