
This kills a few typos and makes things more consistent with more #haskell discussion. build-depends := bexp bexp := package-with-version | cexp '?' '(' bexp ')' | bexp ',' bexp configuration := 'configuration:' cexp cexp := '(' cexp ')' | cexp '||' cexp | cexp '&&' cexp | '!' cexp | 'True' | 'Flag(' string ')' flag := 'flag:' name '=' dexp dexp := cexp extended with { package-with-version, Os(...), Compiler(...) } Some observations: * build-depends don't on packages * order does not matter * most of the problems seem to be solved * see the end how this works for practical problems * False = !True. Can be supported in the parser, but not needed for the semantics. And now for the semantics of the whole thing: ceval :: CExp -> M Bool ceval (COr a b) = liftM2 (||) (ceval a) (ceval b) ceval (CAnd a b) = liftM2 (&&) (ceval a) (ceval b) ceval (CNot x) = liftM not (ceval x) ceval (CTrue) = return True ceval (CFlag s) = isDefinedFlag s beval :: BExp -> M (Map Name Version) beval (BPackage n v) = return $ singleton n v beval (BCond c b) = do e <- ceval c if e then beval b else return empty beval (BSeq a b) = do x <- beval a y <- beval b return $ unionWith intersectVersion x y The flag declarations simply introduce intelligent default *guesses* for the flag values. They don't affect the resolving the conditionals at all (except for flag values). ./setup configure support the following additional options: --no-default-flags don't guess - initialize all flags to False --enable-foo set flag foo to true --disable-foo set flag foo to false --auto-foo use guess to determine flag foo The Art of Guessing Package managers etc can just pass --no-default-flags and specify things manually. This is enough for Gentoo etc. Guesses allow the optional package dependencies, but they are more than guesses and can be easily overridden by the user. Solutions to various problems: 1) fps build-depends: base, Flag(old_fps) ? (base < 2, fps >= 0.8) flag: old_fps = base < 2 configuration: Flag(old_fps) ghc-options: -DOLD_FPS If we are using guessing then 6.4 will use external fps and 6.6 the one in base - correctly. 2) HUnit build-depends: Flag(debug) ? (Flag(Hunit11) ? (HUnit-1.1), !Flag(Huni11) ? (HUnit >= 1, Hunit < 1.1 || > 1.1)) flag: debug = !True flag: HUnit11 = HUnit-1.1 && !(Hunit > 1.1) configuration: Flag(HUnit11) ghc-options: -DHUNIT11 This seems quite complex. But it works - the meaning is: * if debug flag is set then: * if HUnit11 is set depend on on HUnit-1.1 and -DHUNIT11 * if HUnit11 is not set depend on version of HUnit that is >1 and (<1.1 or >1.1) that is not 1.1 * thus the -D is correct * the guess is just a guess and does not affect the semantics - Einar Karttunen