{-# LANGUAGE UndecidableInstances #-} {-# LANGUAGE UndecidableSuperClasses #-} {-# OPTIONS_GHC -Wno-redundant-constraints #-} module CLI.Orchestrator.Client ( cliArgs ) where import Data.Kind (Type) import Data.Proxy (Proxy (Proxy)) import Generics.SOP (All, All2, ConstructorInfo (Record), FieldInfo (FieldInfo), Generic (Code, from), HCollapse (hcollapse), HIndex (hindex), HasDatatypeInfo (datatypeInfo), I (I), IsProductType, K (K), SOP, constructorInfo, constructorName, hcmap, hczipWith, hd, hmap, unI, unSOP, unZ) import Generics.SOP.Constraint (Head) import CLI.Orchestrator.IsArg (IsArg, serializeArg) import CLI.Orchestrator.Utils (Singleton, rangeNP) gargs :: forall a flds. (HasDatatypeInfo a, IsProductType a flds, All IsArg flds) => a -> [String] gargs a = concat $ hcollapse $ case constrMeta of Record _ np -> hczipWith (Proxy @IsArg) (\(I v) (FieldInfo fldName) -> K ["--" ++ fldName, serializeArg v]) dats np _ -> hczipWith (Proxy @IsArg) (\(I v) (K i) -> K ["--" ++ show i, serializeArg v]) dats $ rangeNP @flds where dats = unZ . unSOP . from $ a constrMeta = hd . constructorInfo . datatypeInfo $ Proxy @a class (HasDatatypeInfo a, IsProductType a (FieldsOf a), All IsArg (FieldsOf a)) => Combed a where type FieldsOf a :: [Type] instance (HasDatatypeInfo a, IsProductType a (FieldsOf a), All IsArg (FieldsOf a)) => Combed a where type FieldsOf a = Head (Code a) cliArgs :: forall p. (HasDatatypeInfo p, All Singleton (Code p), All2 Combed (Code p)) => String -> p -> [String] cliArgs outputPath param = constrName : concat (hcollapse res) ++ ["-o", outputPath] where res :: SOP (K [String]) (Code p) res = hcmap (Proxy @Combed) (K . gargs . unI) paramSOP paramSOP = from param constrName = (!! hindex paramSOP) . hcollapse . hmap (K . constructorName) . constructorInfo . datatypeInfo $ Proxy @p