Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CPP macros suitable for partial evaluation #9329

Open
andreasabel opened this issue Oct 13, 2023 · 5 comments
Open

CPP macros suitable for partial evaluation #9329

andreasabel opened this issue Oct 13, 2023 · 5 comments

Comments

@andreasabel
Copy link
Member

I looked into tools that could simplify my codebase by partially evaluating CPP conditionals.
E.g. if I have

#if __GLASGOW_HASKELL__ < 806
...
#if !MIN_VERSION_base(4,11,0)
...

and I no longer support GHC < 8.6 or base < 4.11 then I can get rid of some cruft by partially evaluating the conditions and throw away the conditional together with the branch that is now impossible..

I checked some tools that do some partial evaluation of CPP conditionals:

These tools typically only support setting a symbol to a value, like __GLASGOW_HASKELL__=806. They do not accept predicates, i.e., I cannot set MIN_VERSION_base(4,11,0) to be true.

So if Cabal defined 3 separate symbols to specify a version, instead of a ternary predicate, this would be compatible with such tools.

MAJOR1_VERSION_base=4
MAJOR2_VERSION_base=11
MINOR_VERSION_base=0

This would be usable in Haskell code as such:

#if MAJOR1_VERSION_base >= 4 && MAJOR2_VERSION_base >= 11
...

(One could think of other macro names, like the triple VERSION_EDITION_base, VERSION_MAJOR_base, VERSION_MINOR_base---although the terminology edition for the "major-major" version is not established.)

@phadej
Copy link
Collaborator

phadej commented Oct 14, 2023

Few comments, it's also GHC which defines MIN_VERSION_base macros, e.g. given Ex.hs

{-# LANGUAGE CPP #-}

main :: IO ()
#if MIN_VERSION_base(4,19,0)
main = print True
#else
main = print False
#endif

we have

% runghc-9.8.1 Ex.hs 
True
% runghc-9.6.2 Ex.hs
False

I don't know (or remember) why GHC defines them. Would be get to find out, and check if you'd also like/need to change GHC.


I'd prefer

#define SUPER_VERSION_base 4
#define MAJOR_VERSION_base 19
#define MINOR_VERSION_base 0
#define PATCH_VERSION_base 0

just because I likes justified identifiers :P


I'd appreciate if changes to cabal_macros.h generation were explicitly part of the .cabal format spec, i.e. to get new functionality, you'd need to use more recent cabal-version.

@phadej
Copy link
Collaborator

phadej commented Oct 14, 2023

And not having new features of cabal_macros.h guarded behind cabal-version: ... will result into issues like #9331

This is a reason why I think that cabal_macros.h, Paths_pgkname.hs generating code SHOULD be in Cabal-syntax, as it's the package defining (most of) the file format.

Specifically, if something in Cabal-syntax changes (say, new field) then there probably should be a new cabal-version, and perfectly if we won't need to introduce new cabal-version: (CabalVersionSpec constructors) if nothing changes in Cabal-syntax. The latter is exactly what happened leading to #9331: No change in Cabal-syntax, so no-one thought about having new cabal-version nor cabal-version checks.

@michaelpj
Copy link
Collaborator

I was able to make this work by:

  1. Replacing predicate calls by constant macros.
  2. Using coan (I tried unifdef but it doesn't simplify conditional expressions)

In the end I did something like this to remove all MIN_VERSION_ghc(9,2,*) macros:

rg 'MIN_VERSION_ghc' -l | xargs -I {} bash -c "sed -i -e 's/MIN_VERSION_ghc(9,2,[0-9]*)/ALWAYS_TRUE/g' {} && coan source -r -DALWAYS_TRUE=1 {}"

@michaelpj
Copy link
Collaborator

I couldn't figure out a nice way to deal with __GLASGOW_HASKELL__ < 902, though. Setting it to a particular value would also replace all other __GLASGOW_HASKELL__ comparisons.

@michaelpj
Copy link
Collaborator

The same trick with replacing particular comparisons with a constant would work, though, if the form is consistent enough in your codebase.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants