module Sqel.Names.Data where import Generics.SOP.GGP (GCode, GDatatypeInfoOf) import Generics.SOP.Type.Metadata ( ConstructorInfo (Constructor, Infix, Record), DatatypeInfo (ADT, Newtype), FieldInfo (FieldInfo), ) import Type.Errors (ErrorMessage (Text)) type NatSymbol :: Nat -> Symbol type family NatSymbol n where NatSymbol 0 = "0" NatSymbol 1 = "1" NatSymbol 2 = "2" NatSymbol 3 = "3" NatSymbol 4 = "4" NatSymbol 5 = "5" NatSymbol 6 = "6" NatSymbol 7 = "7" NatSymbol 8 = "8" NatSymbol 9 = "9" NatSymbol 10 = "10" NatSymbol 11 = "11" NatSymbol 12 = "12" NatSymbol 13 = "13" NatSymbol 14 = "14" NatSymbol 15 = "15" NatSymbol 16 = "16" NatSymbol 17 = "17" NatSymbol 18 = "18" NatSymbol 19 = "19" NatSymbol _ = TypeError ('Text "Constructors with more than 20 fields not supported") type ConNsEnum :: Symbol -> Nat -> [Type] -> [Symbol] type family ConNsEnum con n fs where ConNsEnum _ _ '[] = '[] ConNsEnum con n (_ : fs) = AppendSymbol con (NatSymbol n) : ConNsEnum con (n + 1) fs type ConNs :: [FieldInfo] -> [Symbol] type family ConNs fs where ConNs '[] = '[] ConNs ('FieldInfo n : fs) = n : ConNs fs type AdtNs :: [[Type]] -> [ConstructorInfo] -> [(Symbol, Bool, [Symbol])] type family AdtNs ass cons where AdtNs '[] '[] = '[] AdtNs (_ : ass) ('Record conName fs : cons) = '(conName, 'True, ConNs fs) : AdtNs ass cons AdtNs (as : ass) ('Constructor conName : cons) = '(conName, 'False, ConNsEnum conName 0 as) : AdtNs ass cons AdtNs _ ('Infix conName _ _ : _) = TypeError ("Infix constructor not supported: " <> conName) type Ns :: [[Type]] -> DatatypeInfo -> [(Symbol, Bool, [Symbol])] type family Ns ass info where Ns ass ('ADT _ _ cons _) = AdtNs ass cons Ns _ ('Newtype _ name _) = TypeError ("Newtype used for composite column: " <> name) type SumConNames :: Type -> [(Symbol, Bool, [Symbol])] type family SumConNames a where SumConNames a = Ns (GCode a) (GDatatypeInfoOf a) type ProdNames' :: Type -> [(Symbol, Bool, [Symbol])] -> [Symbol] type family ProdNames' a names :: [Symbol] where ProdNames' _ '[ '(_, _, names)] = names ProdNames' a '[] = TypeError ("Tried using empty type as a product: " <> a) ProdNames' a _ = TypeError ("Tried using sum type as a product: " <> a) type family ProdNames (a :: Type) :: [Symbol] where ProdNames a = ProdNames' a (Ns (GCode a) (GDatatypeInfoOf a))