<commit_before>module Rules.Generate (
    generatePackageCode, generateRules,
    derivedConstantsPath, generatedDependencies
    ) where

import Base
import Expression
import GHC
import Rules.Generators.ConfigHs
import Rules.Generators.GhcAutoconfH
import Rules.Generators.GhcBootPlatformH
import Rules.Generators.GhcPlatformH
import Rules.Generators.GhcVersionH
import Rules.Generators.VersionHs
import Oracles.ModuleFiles
import Rules.Actions
import Rules.Resources (Resources)
import Settings

primopsSource :: FilePath
primopsSource = "compiler/prelude/primops.txt.pp"

primopsTxt :: Stage -> FilePath
primopsTxt stage = targetPath stage compiler -/- "build/primops.txt"

platformH :: Stage -> FilePath
platformH stage = targetPath stage compiler -/- "ghc_boot_platform.h"

derivedConstantsPath :: FilePath
derivedConstantsPath = "includes/dist-derivedconstants/header"

-- TODO: can we drop COMPILER_INCLUDES_DEPS += $(includes_GHCCONSTANTS)?
generatedDependencies :: Stage -> Package -> [FilePath]
generatedDependencies stage pkg
    | pkg == hp2ps    = [ "includes/ghcautoconf.h"
                        , "includes/ghcplatform.h" ]
    | pkg == compiler = let buildPath = targetPath stage compiler -/- "build"
                        in
                        [ "includes/ghcautoconf.h"
                        , "includes/ghcplatform.h"
                        , derivedConstantsPath -/- "DerivedConstants.h"
                        , derivedConstantsPath -/- "GHCConstantsHaskellType.hs"
                        , derivedConstantsPath -/- "GHCConstantsHaskellWrappers.hs"
                        , derivedConstantsPath -/- "GHCConstantsHaskellExports.hs"
                        , platformH stage ]
                        ++
                        fmap (buildPath -/-)
                        [ "primop-vector-uniques.hs-incl"
                        , "primop-data-decl.hs-incl"
                        , "primop-tag.hs-incl"
                        , "primop-list.hs-incl"
                        , "primop-strictness.hs-incl"
                        , "primop-fixity.hs-incl"
                        , "primop-primop-info.hs-incl"
                        , "primop-out-of-line.hs-incl"
                        , "primop-has-side-effects.hs-incl"
                        , "primop-can-fail.hs-incl"
                        , "primop-code-size.hs-incl"
                        , "primop-commutable.hs-incl"
                        , "primop-vector-tys-exports.hs-incl"
                        , "primop-vector-tycons.hs-incl"
                        , "primop-vector-tys.hs-incl" ]
    | otherwise = []

-- The following generators and corresponding source extensions are supported:
knownGenerators :: [ (Builder, String) ]
knownGenerators =  [ (Alex   , ".x"  )
                   , (Happy  , ".y"  )
                   , (Happy  , ".ly" )
                   , (Hsc2Hs , ".hsc") ]

determineBuilder :: FilePath -> Maybe Builder
determineBuilder file = fmap fst $ find (\(_, e) -> e == ext) knownGenerators
  where
    ext = takeExtension file

generate :: FilePath -> PartialTarget -> Expr String -> Action ()
generate file target expr = do
    contents <- interpretPartial target expr
    writeFileChanged file contents
    putSuccess $ "| Successfully generated '" ++ file ++ "'."

generatePackageCode :: Resources -> PartialTarget -> Rules ()
generatePackageCode _ target @ (PartialTarget stage pkg) =
    let buildPath   = targetPath stage pkg -/- "build"
        generated f = (buildPath ++ "//*.hs") ?== f && not ("//autogen/*" ?== f)
        file <~ gen = generate file target gen
    in do
        generated ?> \file -> do
            let pattern = "//" ++ takeBaseName file <.> "*"
            files <- fmap (filter (pattern ?==)) $ moduleFiles stage pkg
            let gens = [ (f, b) | f <- files, Just b <- [determineBuilder f] ]
            when (length gens /= 1) . putError $
                "Exactly one generator expected for " ++ file
                ++ " (found: " ++ show gens ++ ")."
            let (src, builder) = head gens
            need [src]
            build $ fullTarget target builder [src] [file]
            let srcBoot = src -<.> "hs-boot"
            whenM (doesFileExist srcBoot) $
                copyFileChanged srcBoot $ file -<.> "hs-boot"

        -- TODO: needing platformH is ugly and fragile
        when (pkg == compiler) $ primopsTxt stage %> \file -> do
            need [platformH stage, primopsSource]
            build $ fullTarget target HsCpp [primopsSource] [file]

        -- TODO: why different folders for generated files?
        fmap (buildPath -/-)
            [ "GHC/PrimopWrappers.hs"
            , "autogen/GHC/Prim.hs"<commit_msg>Match generator sources exactly, see #69 and #70.<commit_after>module Rules.Generate (
    generatePackageCode, generateRules,
    derivedConstantsPath, generatedDependencies
    ) where

import Base
import Expression
import GHC
import Rules.Generators.ConfigHs
import Rules.Generators.GhcAutoconfH
import Rules.Generators.GhcBootPlatformH
import Rules.Generators.GhcPlatformH
import Rules.Generators.GhcVersionH
import Rules.Generators.VersionHs
import Oracles.ModuleFiles
import Rules.Actions
import Rules.Resources (Resources)
import Settings

primopsSource :: FilePath
primopsSource = "compiler/prelude/primops.txt.pp"

primopsTxt :: Stage -> FilePath
primopsTxt stage = targetPath stage compiler -/- "build/primops.txt"

platformH :: Stage -> FilePath
platformH stage = targetPath stage compiler -/- "ghc_boot_platform.h"

derivedConstantsPath :: FilePath
derivedConstantsPath = "includes/dist-derivedconstants/header"

-- TODO: can we drop COMPILER_INCLUDES_DEPS += $(includes_GHCCONSTANTS)?
generatedDependencies :: Stage -> Package -> [FilePath]
generatedDependencies stage pkg
    | pkg == hp2ps    = [ "includes/ghcautoconf.h"
                        , "includes/ghcplatform.h" ]
    | pkg == compiler = let buildPath = targetPath stage compiler -/- "build"
                        in
                        [ "includes/ghcautoconf.h"
                        , "includes/ghcplatform.h"
                        , derivedConstantsPath -/- "DerivedConstants.h"
                        , derivedConstantsPath -/- "GHCConstantsHaskellType.hs"
                        , derivedConstantsPath -/- "GHCConstantsHaskellWrappers.hs"
                        , derivedConstantsPath -/- "GHCConstantsHaskellExports.hs"
                        , platformH stage ]
                        ++
                        fmap (buildPath -/-)
                        [ "primop-vector-uniques.hs-incl"
                        , "primop-data-decl.hs-incl"
                        , "primop-tag.hs-incl"
                        , "primop-list.hs-incl"
                        , "primop-strictness.hs-incl"
                        , "primop-fixity.hs-incl"
                        , "primop-primop-info.hs-incl"
                        , "primop-out-of-line.hs-incl"
                        , "primop-has-side-effects.hs-incl"
                        , "primop-can-fail.hs-incl"
                        , "primop-code-size.hs-incl"
                        , "primop-commutable.hs-incl"
                        , "primop-vector-tys-exports.hs-incl"
                        , "primop-vector-tycons.hs-incl"
                        , "primop-vector-tys.hs-incl" ]
    | otherwise = []

-- The following generators and corresponding source extensions are supported:
knownGenerators :: [ (Builder, String) ]
knownGenerators =  [ (Alex   , ".x"  )
                   , (Happy  , ".y"  )
                   , (Happy  , ".ly" )
                   , (Hsc2Hs , ".hsc") ]

determineBuilder :: FilePath -> Maybe Builder
determineBuilder file = fmap fst $ find (\(_, e) -> e == ext) knownGenerators
  where
    ext = takeExtension file

generate :: FilePath -> PartialTarget -> Expr String -> Action ()
generate file target expr = do
    contents <- interpretPartial target expr
    writeFileChanged file contents
    putSuccess $ "| Successfully generated '" ++ file ++ "'."

generatePackageCode :: Resources -> PartialTarget -> Rules ()
generatePackageCode _ target @ (PartialTarget stage pkg) =
    let buildPath   = targetPath stage pkg -/- "build"
        dropBuild   = drop (length buildPath + 1)
        generated f = (buildPath ++ "//*.hs") ?== f && not ("//autogen/*" ?== f)
        file <~ gen = generate file target gen
    in do
        generated ?> \file -> do
            let srcFile = dropBuild file
                pattern = "//" ++ srcFile <.> "*"
            files <- fmap (filter (pattern ?==)) $ moduleFiles stage pkg
            let gens = [ (f, b) | f <- files, Just b <- [determineBuilder f] ]
            when (length gens /= 1) . putError $
                "Exactly one generator expected for " ++ file
                ++ " (found: " ++ show gens ++ ")."
            let (src, builder) = head gens
            need [src]
            build $ fullTarget target builder [src] [file]
            let srcBoot = src -<.> "hs-boot"
            whenM (doesFileExist srcBoot) $
                copyFileChanged srcBoot $ file -<.> "hs-boot"

        -- TODO: needing platformH is ugly and fragile
        when (pkg == compiler) $ primopsTxt stage %> \file -> do
            need [platformH stage, primopsSource]
            build $ fullTarget target HsCpp [primopsSource] [file]

        -- TODO: why different folders for generated files?
        fmap (buildPath -/-)
            [ "GHC/PrimopWrappers.hs"
            , "autogen/GHC/Prim.hs"
{'fraction_non_alphanumeric': 0.11225238444607484, 'fraction_numerical': 0.0011529189812388638, 'mean_word_length': 1.833976833976834, 'pattern_counts': {'":': 0, '<': 19, '<?xml version=': 0, '>': 39, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3475640', 'n_tokens_mistral': 2723, 'n_tokens_neox': 2604, 'n_words': 621}