Skip to content

Commit 2d9c460

Browse files
author
Robert Henderson
committed
Work in progress from Haskell Exchange Hackathon 2016 (unfinished)
- Refactoring the 'PackageConstraint' and 'UserConstraint' data types, and extending their parser/pretty-printer code to support the proposed qualified constraint syntax (see github issue 3502).
1 parent f48e17b commit 2d9c460

File tree

3 files changed

+144
-66
lines changed

3 files changed

+144
-66
lines changed

cabal-install/Distribution/Client/Targets.hs

+78-37
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ import Distribution.Solver.Types.OptionalStanza
6767
import Distribution.Solver.Types.PackageConstraint
6868
import Distribution.Solver.Types.PackageIndex (PackageIndex)
6969
import qualified Distribution.Solver.Types.PackageIndex as PackageIndex
70+
import Distribution.Solver.Types.PackagePath
7071
import Distribution.Solver.Types.SourcePackage
7172

7273
import qualified Distribution.Client.World as World
@@ -203,8 +204,9 @@ pkgSpecifierConstraints (NamedPackage _ constraints) = map toLpc constraints
203204
pkgSpecifierConstraints (SpecificSourcePackage pkg) =
204205
[LabeledPackageConstraint pc ConstraintSourceUserTarget]
205206
where
206-
pc = PackageConstraintVersion (packageName pkg)
207-
(thisVersion (packageVersion pkg))
207+
pc = PackageConstraint (Q (PackagePath DefaultNamespace Unqualified)
208+
(packageName pkg)) $
209+
PackagePropertyVersion (thisVersion (packageVersion pkg))
208210

209211
-- ------------------------------------------------------------
210212
-- * Parsing and checking user targets
@@ -414,6 +416,12 @@ data PackageTarget pkg =
414416
-- * Converting user targets to package targets
415417
-- ------------------------------------------------------------
416418

419+
dependencyToConstraints :: Dependency -> [PackageConstraint]
420+
dependencyToConstraints (Dependency name vrange) =
421+
[ PackageConstraint (Q defaultPackagePath name) $
422+
PackagePropertyVersion vrange
423+
| not (isAnyVersion vrange) ]
424+
417425
-- | Given a user-specified target, expand it to a bunch of package targets
418426
-- (each of which refers to only one package).
419427
--
@@ -422,19 +430,17 @@ expandUserTarget :: FilePath
422430
-> IO [PackageTarget (PackageLocation ())]
423431
expandUserTarget worldFile userTarget = case userTarget of
424432

425-
UserTargetNamed (Dependency name vrange) ->
426-
let constraints = [ PackageConstraintVersion name vrange
427-
| not (isAnyVersion vrange) ]
428-
in return [PackageTargetNamedFuzzy name constraints userTarget]
433+
UserTargetNamed dep@(Dependency name _) ->
434+
return [PackageTargetNamedFuzzy name (dependencyToConstraints dep) userTarget]
429435

430436
UserTargetWorld -> do
431437
worldPkgs <- World.getContents worldFile
432438
--TODO: should we warn if there are no world targets?
433439
return [ PackageTargetNamed name constraints userTarget
434-
| World.WorldPkgInfo (Dependency name vrange) flags <- worldPkgs
435-
, let constraints = [ PackageConstraintVersion name vrange
436-
| not (isAnyVersion vrange) ]
437-
++ [ PackageConstraintFlags name flags
440+
| World.WorldPkgInfo dep@(Dependency name _) flags <- worldPkgs
441+
, let constraints = dependencyToConstraints dep
442+
++ [ PackageConstraint (Q defaultPackagePath name) $
443+
PackagePropertyFlags flags
438444
| not (null flags) ] ]
439445

440446
UserTargetLocalDir dir ->
@@ -701,40 +707,75 @@ extraPackageNameEnv names = PackageNameEnv pkgNameLookup
701707
-- * Package constraints
702708
-- ------------------------------------------------------------
703709

704-
data UserConstraint =
705-
UserConstraintVersion PackageName VersionRange
706-
| UserConstraintInstalled PackageName
707-
| UserConstraintSource PackageName
708-
| UserConstraintFlags PackageName FlagAssignment
709-
| UserConstraintStanzas PackageName [OptionalStanza]
710-
deriving (Eq, Show, Generic)
710+
-- | Restricted version of 'Qualifier' that a user may specify on the command line.
711+
data UserQualifier =
712+
-- | Top-level dependency.
713+
UserUnqualified
714+
715+
-- | Setup dependency.
716+
| UserSetup PackageName
717+
718+
-- | Executable dependency.
719+
| UserExe PackageName PackageName
720+
721+
fromUserQualifier :: UserQualifier -> Qualifier
722+
fromUserQualifier UserUnqualified = Unqualified
723+
fromUserQualifier (UserSetup name) = Setup name
724+
fromUserQualifier (UserExe name1 name2) = Exe name1 name2
725+
726+
-- | A version of 'PackageProperty' that a user may specify on the command
727+
-- line (currently, it has identical representation to 'PackageProperty').
728+
newtype UserProperty = UserProperty PackageProperty
729+
730+
-- | Per-package constraints. Package constraints must be respected by the
731+
-- solver. Multiple constraints for each package can be given, though obviously
732+
-- it is possible to construct conflicting constraints (eg impossible version
733+
-- range or inconsistent flag assignment).
734+
--
735+
instance Text UserProperty where
736+
disp (PackagePropertyVersion verrange) = disp verrange
737+
disp PackagePropertyInstalled = Disp.text "installed"
738+
disp PackagePropertySource = Disp.text "source"
739+
disp (PackagePropertyFlags flags) = dispFlagAssignment flags
740+
disp (PackagePropertyStanzas stanzas) = dispStanzas stanzas
741+
where
742+
dispStanzas = Disp.hsep . map dispStanza
743+
dispStanza TestStanzas = Disp.text "test"
744+
dispStanza BenchStanzas = Disp.text "bench"
745+
746+
parse =
747+
((parse >>= return . PackagePropertyVersion)
748+
+++ (do skipSpaces1
749+
_ <- Parse.string "installed"
750+
return (PackagePropertyInstalled))
751+
+++ (do skipSpaces1
752+
_ <- Parse.string "source"
753+
return (PackagePropertySource))
754+
+++ (do skipSpaces1
755+
_ <- Parse.string "test"
756+
return (PackagePropertyStanzas [TestStanzas]))
757+
+++ (do skipSpaces1
758+
_ <- Parse.string "bench"
759+
return (PackagePropertyStanzas [BenchStanzas])))
760+
<++ (do skipSpaces1
761+
flags <- parseFlagAssignment
762+
return (PackagePropertyFlags flags))
711763

712-
instance Binary UserConstraint
764+
-- | A restricted version of PackageConstraint that the user can specify on the
765+
-- command line.
766+
newtype UserConstraint = UserConstraint UserQualifier PackageName PackageProperty
767+
deriving (Eq, Show)
713768

714769
userConstraintPackageName :: UserConstraint -> PackageName
715-
userConstraintPackageName uc = case uc of
716-
UserConstraintVersion name _ -> name
717-
UserConstraintInstalled name -> name
718-
UserConstraintSource name -> name
719-
UserConstraintFlags name _ -> name
720-
UserConstraintStanzas name _ -> name
770+
userConstraintPackageName (UserConstraint _ name _ = name
721771

722772
userToPackageConstraint :: UserConstraint -> PackageConstraint
723-
-- At the moment, the types happen to be directly equivalent
724-
userToPackageConstraint uc = case uc of
725-
UserConstraintVersion name ver -> PackageConstraintVersion name ver
726-
UserConstraintInstalled name -> PackageConstraintInstalled name
727-
UserConstraintSource name -> PackageConstraintSource name
728-
UserConstraintFlags name flags -> PackageConstraintFlags name flags
729-
UserConstraintStanzas name stanzas -> PackageConstraintStanzas name stanzas
773+
userToPackageConstraint (UserConstraint qual name pp) =
774+
PackageConstraint (Q (fromUserQualifier qual) name) pp
730775

731776
renamePackageConstraint :: PackageName -> PackageConstraint -> PackageConstraint
732-
renamePackageConstraint name pc = case pc of
733-
PackageConstraintVersion _ ver -> PackageConstraintVersion name ver
734-
PackageConstraintInstalled _ -> PackageConstraintInstalled name
735-
PackageConstraintSource _ -> PackageConstraintSource name
736-
PackageConstraintFlags _ flags -> PackageConstraintFlags name flags
737-
PackageConstraintStanzas _ stanzas -> PackageConstraintStanzas name stanzas
777+
renamePackageConstraint name (PackageConstraint (Q path _) pp) =
778+
PackageConstraint (Q path name) pp
738779

739780
readUserConstraint :: String -> Either String UserConstraint
740781
readUserConstraint str =

cabal-install/Distribution/Solver/Types/PackageConstraint.hs

+32-13
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,54 @@
11
{-# LANGUAGE DeriveGeneric #-}
22
module Distribution.Solver.Types.PackageConstraint (
3+
PackageProperty(..),
34
PackageConstraint(..),
4-
showPackageConstraint,
5+
-- showPackageConstraint,
56
) where
67

78
import Distribution.Compat.Binary (Binary(..))
89
import Distribution.PackageDescription (FlagAssignment, FlagName(..))
910
import Distribution.Package (PackageName)
1011
import Distribution.Solver.Types.OptionalStanza
11-
import Distribution.Text (display)
12+
import Distribution.Solver.Types.PackagePath (Qualified)
13+
import Distribution.Text (Text(..), display)
1214
import Distribution.Version (VersionRange, simplifyVersionRange)
1315
import GHC.Generics (Generic)
1416

15-
-- | Per-package constraints. Package constraints must be respected by the
16-
-- solver. Multiple constraints for each package can be given, though obviously
17-
-- it is possible to construct conflicting constraints (eg impossible version
18-
-- range or inconsistent flag assignment).
19-
--
17+
18+
data PackageProperty
19+
= PackagePropertyVersion VersionRange
20+
| PackagePropertyInstalled
21+
| PackagePropertySource
22+
| PackagePropertyFlags FlagAssignment
23+
| PackagePropertyStanzas [OptionalStanza]
24+
deriving (Eq, Show, Generic)
25+
26+
instance Binary PackageProperty
27+
2028
data PackageConstraint
21-
= PackageConstraintVersion PackageName VersionRange
22-
| PackageConstraintInstalled PackageName
23-
| PackageConstraintSource PackageName
24-
| PackageConstraintFlags PackageName FlagAssignment
25-
| PackageConstraintStanzas PackageName [OptionalStanza]
29+
= PackageConstraint (Qualified PackageName) PackageProperty
2630
deriving (Eq, Show, Generic)
2731

2832
instance Binary PackageConstraint
2933

34+
dispPackageProperty :: PackageProperty -> Disp.Doc
35+
disp (PackagePropertyVersion verrange) = disp verrange
36+
disp PackagePropertyInstalled = Disp.text "installed"
37+
disp PackagePropertySource = Disp.text "source"
38+
disp (PackagePropertyFlags flags) = dispFlagAssignment flags
39+
disp (PackagePropertyStanzas stanzas) = dispStanzas stanzas
40+
where
41+
dispStanzas = Disp.hsep . map dispStanza
42+
dispStanza TestStanzas = Disp.text "test"
43+
dispStanza BenchStanzas = Disp.text "bench"
44+
45+
dispPackageConstraint :: PackageConstraint -> Disp.Doc
46+
dispPackageConstraint (PackageConstraint (Q path name) pp) =
47+
48+
3049
-- | Provide a textual representation of a package constraint
3150
-- for debugging purposes.
32-
--
51+
3352
showPackageConstraint :: PackageConstraint -> String
3453
showPackageConstraint (PackageConstraintVersion pn vr) =
3554
display pn ++ " " ++ display (simplifyVersionRange vr)

cabal-install/Distribution/Solver/Types/PackagePath.hs

+34-16
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,25 @@
1+
{-# LANGUAGE DeriveGeneric #-}
12
module Distribution.Solver.Types.PackagePath
23
( PackagePath(..)
34
, Namespace(..)
45
, Qualifier(..)
56
, QPN
67
, Qualified(..)
78
, showQPN
9+
, defaultPackagePath
810
) where
911

12+
import Distribution.Compat.Binary (Binary(..))
1013
import Distribution.Package
11-
import Distribution.Text
14+
import GHC.Generics (Generic)
15+
import qualified Text.PrettyPrint as Disp
1216

1317
-- | A package path consists of a namespace and a package path inside that
1418
-- namespace.
1519
data PackagePath = PackagePath Namespace Qualifier
16-
deriving (Eq, Ord, Show)
20+
deriving (Eq, Ord, Show, Generic)
21+
22+
instance Binary PackagePath
1723

1824
-- | Top-level namespace
1925
--
@@ -27,7 +33,9 @@ data Namespace =
2733
--
2834
-- For now we just number these (rather than giving them more structure).
2935
| Independent Int
30-
deriving (Eq, Ord, Show)
36+
deriving (Eq, Ord, Show, Generic)
37+
38+
instance Binary Namespace
3139

3240
-- | Qualifier of a package within a namespace (see 'PackagePath')
3341
data Qualifier =
@@ -59,17 +67,15 @@ data Qualifier =
5967
-- tracked only @pn2@, that would require us to pick only one
6068
-- version of an executable over the entire install plan.)
6169
| Exe PackageName PackageName
62-
deriving (Eq, Ord, Show)
70+
deriving (Eq, Generic, Ord, Show)
6371

64-
-- | String representation of a package path.
65-
--
66-
-- NOTE: The result of 'showPP' is either empty or results in a period, so that
67-
-- it can be prepended to a package name.
68-
showPP :: PackagePath -> String
69-
showPP (PackagePath ns q) =
72+
instance Binary Qualifier
73+
74+
dispPP :: PackagePath -> Disp.Doc
75+
dispPP (PackagePath ns q) =
7076
case ns of
7177
DefaultNamespace -> go q
72-
Independent i -> show i ++ "." ++ go q
78+
Independent i -> Disp.int i <> Disp.char '.' <> go q
7379
where
7480
-- Print the qualifier
7581
--
@@ -78,14 +84,23 @@ showPP (PackagePath ns q) =
7884
-- So we want to print something like @"A.base"@, where the @"A."@ part
7985
-- is the qualifier and @"base"@ is the actual dependency (which, for the
8086
-- 'Base' qualifier, will always be @base@).
81-
go Unqualified = ""
82-
go (Setup pn) = display pn ++ "-setup."
83-
go (Exe pn pn2) = display pn ++ "-" ++ display pn2 ++ "-exe."
84-
go (Base pn) = display pn ++ "."
87+
go Unqualified = empty
88+
go (Setup pn) = disp pn <> Disp.text ":setup."
89+
go (Exe pn pn2) = disp pn <> Disp.char ':' <> disp pn2 <> Disp.text ":exe."
90+
go (Base pn) = display pn <> Disp.char '.'
91+
92+
-- | String representation of a package path.
93+
--
94+
-- NOTE: The result of 'showPP' is either empty or results in a period, so that
95+
-- it can be prepended to a package name.
96+
showPP :: PackagePath -> String
97+
showPP = display . dispPP
8598

8699
-- | A qualified entity. Pairs a package path with the entity.
87100
data Qualified a = Q PackagePath a
88-
deriving (Eq, Ord, Show)
101+
deriving (Eq, Ord, Show, Generic)
102+
103+
instance Binary a => Binary (Qualified a)
89104

90105
-- | Standard string representation of a qualified entity.
91106
showQ :: (a -> String) -> (Qualified a -> String)
@@ -97,3 +112,6 @@ type QPN = Qualified PackageName
97112
-- | String representation of a qualified package path.
98113
showQPN :: QPN -> String
99114
showQPN = showQ display
115+
116+
defaultPackagePath :: PackagePath
117+
defaultPackagePath = PackagePath DefaultNamespace Unqualified

0 commit comments

Comments
 (0)