module Exon.Class.Exon where
import Text.Show (showString)
import Exon.Data.Result (Result (Empty, Result))
import qualified Exon.Data.Segment as Segment
import Exon.Data.Segment (Segment)
data ExonDefault
data KeepWhitespace
class Exon (tag :: Type) (a :: Type) where
isEmpty :: a -> Bool
isEmpty =
Bool -> a -> Bool
forall a b. a -> b -> a
const Bool
False
convertSegment :: Segment a -> Result a
default convertSegment :: IsString a => Segment a -> Result a
convertSegment = \case
Segment.String String
a ->
a -> Result a
forall a. a -> Result a
Result (String -> a
forall a. IsString a => String -> a
fromString String
a)
Segment.Expression a
a | a -> Bool
forall tag a. Exon tag a => a -> Bool
isEmpty @tag a
a ->
Result a
forall a. Result a
Empty
Segment.Expression a
a ->
a -> Result a
forall a. a -> Result a
Result a
a
Segment.Whitespace String
_ ->
Result a
forall a. Result a
Empty
appendSegment :: Result a -> Segment a -> Result a
default appendSegment :: Semigroup a => Result a -> Segment a -> Result a
appendSegment Result a
z Segment a
a =
Result a
z Result a -> Result a -> Result a
forall a. Semigroup a => a -> a -> a
<> Segment a -> Result a
forall tag a. Exon tag a => Segment a -> Result a
convertSegment @tag Segment a
a
insertWhitespace :: Result a -> String -> Segment a -> Result a
default insertWhitespace :: Result a -> String -> Segment a -> Result a
insertWhitespace Result a
s1 String
_ Segment a
s2 =
Result a -> Segment a -> Result a
forall tag a. Exon tag a => Result a -> Segment a -> Result a
appendSegment @tag Result a
s1 Segment a
s2
concatSegments :: NonEmpty (Segment a) -> a
default concatSegments :: Monoid a => NonEmpty (Segment a) -> a
concatSegments (Segment a
h :| [Segment a]
t) =
Result a -> a
forall (t :: * -> *) m. (Foldable t, Monoid m) => t m -> m
fold (Result a -> [Segment a] -> Result a
spin (Segment a -> Result a
forall tag a. Exon tag a => Segment a -> Result a
convertSegment @tag Segment a
h) [Segment a]
t)
where
spin :: Result a -> [Segment a] -> Result a
spin :: Result a -> [Segment a] -> Result a
spin Result a
Empty = \case
[] ->
Result a
forall a. Result a
Empty
Segment.Whitespace String
_ : [Segment a]
ss ->
Result a -> [Segment a] -> Result a
spin Result a
forall a. Result a
Empty [Segment a]
ss
Segment a
s1 : [Segment a]
ss ->
Result a -> [Segment a] -> Result a
spin (Segment a -> Result a
forall tag a. Exon tag a => Segment a -> Result a
convertSegment @tag Segment a
s1) [Segment a]
ss
spin (Result a
s1) = \case
[] ->
a -> Result a
forall a. a -> Result a
Result a
s1
Segment.Whitespace String
_ : (Segment.Expression a
a) : [Segment a]
ss | a -> Bool
forall tag a. Exon tag a => a -> Bool
isEmpty @tag a
a ->
Result a -> [Segment a] -> Result a
spin (a -> Result a
forall a. a -> Result a
Result a
s1) [Segment a]
ss
Segment.Whitespace String
ws : Segment a
s2 : [Segment a]
ss ->
Result a -> [Segment a] -> Result a
spin (Result a -> String -> Segment a -> Result a
forall tag a.
Exon tag a =>
Result a -> String -> Segment a -> Result a
insertWhitespace @tag (a -> Result a
forall a. a -> Result a
Result a
s1) String
ws Segment a
s2) [Segment a]
ss
[Segment.Whitespace _] ->
(a -> Result a
forall a. a -> Result a
Result a
s1)
Segment a
s2 : [Segment a]
ss ->
Result a -> [Segment a] -> Result a
spin (Result a -> Segment a -> Result a
forall tag a. Exon tag a => Result a -> Segment a -> Result a
appendSegment @tag (a -> Result a
forall a. a -> Result a
Result a
s1) Segment a
s2) [Segment a]
ss
instance {-# overlappable #-} (
Monoid a,
IsString a
) => Exon ExonDefault a where
convertKeepWs ::
IsString a =>
Segment a ->
Result a
convertKeepWs :: Segment a -> Result a
convertKeepWs = \case
Segment.String String
a ->
a -> Result a
forall a. a -> Result a
Result (String -> a
forall a. IsString a => String -> a
fromString String
a)
Segment.Expression a
a ->
a -> Result a
forall a. a -> Result a
Result a
a
Segment.Whitespace String
a ->
a -> Result a
forall a. a -> Result a
Result (String -> a
forall a. IsString a => String -> a
fromString String
a)
concatKeepWs ::
∀ tag a .
Monoid a =>
Exon tag a =>
NonEmpty (Segment a) ->
a
concatKeepWs :: NonEmpty (Segment a) -> a
concatKeepWs =
Result a -> a
forall (t :: * -> *) m. (Foldable t, Monoid m) => t m -> m
fold (Result a -> a)
-> (NonEmpty (Segment a) -> Result a) -> NonEmpty (Segment a) -> a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Result a -> Segment a -> Result a)
-> Result a -> NonEmpty (Segment a) -> Result a
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' (forall a. Exon tag a => Result a -> Segment a -> Result a
forall tag a. Exon tag a => Result a -> Segment a -> Result a
appendSegment @tag) Result a
forall a. Result a
Empty
instance Exon ExonDefault String where
convertSegment :: Segment String -> Result String
convertSegment =
Segment String -> Result String
forall a. IsString a => Segment a -> Result a
convertKeepWs
concatSegments :: NonEmpty (Segment String) -> String
concatSegments =
forall a.
(Monoid a, Exon ExonDefault a) =>
NonEmpty (Segment a) -> a
forall tag a. (Monoid a, Exon tag a) => NonEmpty (Segment a) -> a
concatKeepWs @ExonDefault
instance Exon ExonDefault Text where
convertSegment :: Segment Text -> Result Text
convertSegment =
Segment Text -> Result Text
forall a. IsString a => Segment a -> Result a
convertKeepWs
concatSegments :: NonEmpty (Segment Text) -> Text
concatSegments =
forall a.
(Monoid a, Exon ExonDefault a) =>
NonEmpty (Segment a) -> a
forall tag a. (Monoid a, Exon tag a) => NonEmpty (Segment a) -> a
concatKeepWs @ExonDefault
instance Exon ExonDefault LText where
convertSegment :: Segment LText -> Result LText
convertSegment =
Segment LText -> Result LText
forall a. IsString a => Segment a -> Result a
convertKeepWs
concatSegments :: NonEmpty (Segment LText) -> LText
concatSegments =
forall a.
(Monoid a, Exon ExonDefault a) =>
NonEmpty (Segment a) -> a
forall tag a. (Monoid a, Exon tag a) => NonEmpty (Segment a) -> a
concatKeepWs @ExonDefault
instance Exon ExonDefault ByteString where
convertSegment :: Segment ByteString -> Result ByteString
convertSegment =
Segment ByteString -> Result ByteString
forall a. IsString a => Segment a -> Result a
convertKeepWs
concatSegments :: NonEmpty (Segment ByteString) -> ByteString
concatSegments =
forall a.
(Monoid a, Exon ExonDefault a) =>
NonEmpty (Segment a) -> a
forall tag a. (Monoid a, Exon tag a) => NonEmpty (Segment a) -> a
concatKeepWs @ExonDefault
instance Exon ExonDefault LByteString where
convertSegment :: Segment LByteString -> Result LByteString
convertSegment =
Segment LByteString -> Result LByteString
forall a. IsString a => Segment a -> Result a
convertKeepWs
concatSegments :: NonEmpty (Segment LByteString) -> LByteString
concatSegments =
forall a.
(Monoid a, Exon ExonDefault a) =>
NonEmpty (Segment a) -> a
forall tag a. (Monoid a, Exon tag a) => NonEmpty (Segment a) -> a
concatKeepWs @ExonDefault
instance Exon ExonDefault (String -> String) where
convertSegment :: Segment (String -> String) -> Result (String -> String)
convertSegment = \case
Segment.String String
a ->
(String -> String) -> Result (String -> String)
forall a. a -> Result a
Result (String -> String -> String
showString String
a)
Segment.Expression String -> String
a | (String -> String) -> Bool
forall tag a. Exon tag a => a -> Bool
isEmpty @ExonDefault String -> String
a ->
Result (String -> String)
forall a. Result a
Empty
Segment.Expression String -> String
a ->
(String -> String) -> Result (String -> String)
forall a. a -> Result a
Result String -> String
a
Segment.Whitespace String
ws ->
(String -> String) -> Result (String -> String)
forall a. a -> Result a
Result (String -> String -> String
showString String
ws)
appendSegment :: Result (String -> String)
-> Segment (String -> String) -> Result (String -> String)
appendSegment Result (String -> String)
z Segment (String -> String)
a =
case (Result (String -> String)
z, Segment (String -> String) -> Result (String -> String)
forall tag a. Exon tag a => Segment a -> Result a
convertSegment @ExonDefault Segment (String -> String)
a) of
(Result String -> String
z', Result String -> String
a') ->
(String -> String) -> Result (String -> String)
forall a. a -> Result a
Result (String -> String
z' (String -> String) -> (String -> String) -> String -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> String
a')
(Result (String -> String)
z', Result (String -> String)
Empty) ->
Result (String -> String)
z'
(Result (String -> String)
Empty, Result (String -> String)
a') ->
Result (String -> String)
a'
concatSegments :: NonEmpty (Segment (String -> String)) -> String -> String
concatSegments =
forall a.
(Monoid a, Exon ExonDefault a) =>
NonEmpty (Segment a) -> a
forall tag a. (Monoid a, Exon tag a) => NonEmpty (Segment a) -> a
concatKeepWs @ExonDefault