packages feed

purekell-0.1.0.0: src/Purekell/Codec.hs

-- | Bidirectional codecs that pair a megaparsec parser with a pretty-printer.
--
-- A 'Codec' bundles a parser and printer for the same type, making it easy
-- to parse source text into an AST and print it back. This is the core
-- abstraction that enables roundtrip translation between languages.
--
-- See "Purekell.Haskell" and "Purekell.PureScript" for concrete codecs.
module Purekell.Codec
  ( Codec (..)
  , runParse
  , runPrint
  , roundtrip
  ) where

import Data.Text (Text)
import Data.Void (Void)
import Text.Megaparsec (Parsec, ParseErrorBundle, parse)

-- | A bidirectional codec pairing a parser and printer for type @a@.
--
-- The parser consumes 'Text' input and produces an @a@; the printer
-- converts an @a@ back to 'Text'. When the parser and printer are
-- inverses, @'roundtrip' codec@ is the identity on well-formed values.
data Codec a = Codec
  { codecParser  :: Parsec Void Text a  -- ^ Megaparsec parser for @a@
  , codecPrinter :: a -> Text           -- ^ Pretty-printer for @a@
  }

-- | Parse source text using a codec's parser.
runParse :: Codec a -> Text -> Either (ParseErrorBundle Text Void) a
runParse c = parse (codecParser c) ""

-- | Print a value using a codec's printer.
runPrint :: Codec a -> a -> Text
runPrint = codecPrinter

-- | Parse, print, and re-parse — testing that printed output is stable.
--
-- @roundtrip codec val@ prints @val@ then parses the result. If the codec
-- is well-behaved, @roundtrip codec val == Right val@.
roundtrip :: Codec a -> a -> Either (ParseErrorBundle Text Void) a
roundtrip c = runParse c . runPrint c