-- | The main stable interface for the th-serde library, providing QuasiQuoters
-- for defining data types with separated serialization and validation logic.
-- Other modules are considered internal and may change without notice.
--
-- = Overview
--
-- This library helps separate your core data models from their serialization and
-- validation logic. While newtypes are commonly used for this purpose, they become
-- unwieldy with complex data types, especially when dealing with multiple fields
-- that need validation or custom serialization.
--
-- = How It Works
--
-- Given a data type definition with \'via\' annotations, th-serde:
--
-- 1. Generates your core data type with clean, simple fields
-- 2. Creates a \"shadow\" type with the validation/serialization wrappers
-- 3. Provides machinery to convert between them using 'Data.Coerce.coerce'
--
-- Important: Shadow types are generated without any type class implementations.
-- You must implement all needed type classes for shadow types using 'runuserprep'.
-- The QuasiQuoter never automatically derives any instances for shadow types.
--
-- = Example
--
-- Here's a complete example:
--
-- @
-- [serde|
-- .derive
--   Eq Ord Show Read
--
-- -- Your core data type with validation annotations
-- -- Suppose Age, VerifyLength, and VerifyEmail are defined elsewhere
-- data Person
--   age :: Int32 via Age                     -- Validate using Age newtype
--   name :: String via VerifyLength 1 10     -- Must be 1-10 chars
--   email :: String via VerifyEmail          -- Must be valid email
-- |]
-- @
--
-- This generates:
--
-- @
-- -- Your clean business model
-- data Person = Person
--   { age :: Int32    -- Clean types without validation wrappers
--   , name :: String
--   , email :: String
--   } deriving (Eq, Ord, Show, Read)
--
-- -- Auto-generated shadow type for validation
-- data Person\_\_ = Person\_\_
--   { age__ :: Age               -- Fields use validation wrappers
--   , name__ :: VerifyLength 1 10
--   , email__ :: VerifyEmail
--   }
-- @
--
-- = Usage Pattern
--
-- 1. Define your types using the 'serde' QuasiQuoter
-- 2. Call 'runusercoercion' to implement validation/serialization
--
-- = Syntax Reference
--
-- == Deriving Classes
--
-- Use @.derive@ at the start to specify which classes to derive:
--
-- @
-- .derive
--   Eq Ord Show Read  -- These will be derived for all types except shadow types
-- @
--
-- == Data Types
--
-- @
-- data Person                    -- Regular data type
--   field :: Type via Validator  -- Field with validation
--   plain :: Type                -- Field without validation
-- @
--
-- == Newtypes
--
-- Unlike data types, newtypes using 'via' (either in field or type position)
-- will use GHC's @DerivingVia@ mechanism directly instead of creating shadow types.
-- This requires the @DerivingVia@ language extension to be enabled.
--
-- @
-- newtype Age        -- Simple newtype without via
--   value :: Int32   -- Regular field, no shadow type created
--
-- newtype Number Double
--
-- newtype Validated Int32 via Check  -- With validation
-- -- ^ Generates:
-- --   newtype Validated = Validated Int32
-- --     deriving (...) via Check
--
-- newtype Name       -- With record syntax + via
--   getName :: String via Verify
-- -- ^ Generates:
-- --   newtype Name = Name { getName :: String }
-- --     deriving (...) via Verify
-- @
--
-- == Type Aliases
--
-- Type aliases do not participate in the derivation process and are not shadowed.
--
-- @
-- type EmailStr String
-- @
--
-- == Examples
--
-- Examples can be found in the test suite.
module Data.Serde.QQ
  ( serde,
    RunUserCoercion (..),
    runusercoercion,
  )
where

import Data.Serde.Internal.TH
import Language.Haskell.TH.Quote as TH

-- | quasi-quoter for th-serde
serde :: QuasiQuoter
serde :: QuasiQuoter
serde =
  QuasiQuoter
    { quoteExp :: String -> Q Exp
quoteExp = String -> String -> Q Exp
forall a. HasCallStack => String -> a
error String
"serde: quoteExp not implemented",
      quotePat :: String -> Q Pat
quotePat = String -> String -> Q Pat
forall a. HasCallStack => String -> a
error String
"serde: quotePat not implemented",
      quoteType :: String -> Q Type
quoteType = String -> String -> Q Type
forall a. HasCallStack => String -> a
error String
"serde: quoteType not implemented",
      quoteDec :: String -> Q [Dec]
quoteDec = String -> Q [Dec]
runqq1
    }