diff --git a/.ci/docker/build-and-publish-docker-image.sh b/.ci/docker/build-and-publish-docker-image.sh index a5f36bd5f5..30fbea6eed 100755 --- a/.ci/docker/build-and-publish-docker-image.sh +++ b/.ci/docker/build-and-publish-docker-image.sh @@ -13,9 +13,9 @@ elif [[ "$1" != "" ]]; then echo "Unrecognized argument: $1" >&2 exit 1 fi -UBUNTU_VERSION=jammy-20260217 -GHC_VERSIONS=("9.12.4" "9.10.3" "9.8.4" "9.6.7") -CABAL_VERSIONS=("3.14.2.0" "3.14.2.0" "3.14.2.0" "3.14.2.0") +UBUNTU_VERSION=jammy-20260410 +GHC_VERSIONS=( "9.14.1" "9.12.4" "9.10.3" "9.8.4" "9.6.7") +CABAL_VERSIONS=("3.16.1.0" "3.16.1.0" "3.16.1.0" "3.16.1.0" "3.16.1.0") # We want to use docker buildkit so that our layers are built in parallel. This # is ignored completely on versions of docker which don't support buildkit. diff --git a/.ci/gitlab/benchmark.yml b/.ci/gitlab/benchmark.yml index ee201684f1..11f2b3b866 100644 --- a/.ci/gitlab/benchmark.yml +++ b/.ci/gitlab/benchmark.yml @@ -1,5 +1,5 @@ .benchmark: - image: ghcr.io/clash-lang/clash-ci:$GHC_VERSION-20260417 + image: ghcr.io/clash-lang/clash-ci:$GHC_VERSION-20260515 stage: test timeout: 2 hours variables: diff --git a/.ci/gitlab/common.yml b/.ci/gitlab/common.yml index f6fda93da7..34e1487d78 100644 --- a/.ci/gitlab/common.yml +++ b/.ci/gitlab/common.yml @@ -12,7 +12,7 @@ default: timeout: 2 hours stage: build variables: - CLASH_DOCKER_TAG: 20260417 + CLASH_DOCKER_TAG: 20260515 CACHE_BUST_TOKEN: 3 # Note that the fallback key has two cache bust tokens. `$CACHE_BUST_TOKEN` # is our own, defined right above, and the `-3` at the end in the fallback diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 200b059fa4..8ea9006555 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -21,7 +21,7 @@ jobs: fail-fast: false matrix: os: ["macos-26", "windows-latest"] - ghc: ["9.6", "9.8", "9.10", "9.12"] + ghc: ["9.6", "9.8", "9.10", "9.12", "9.14"] exclude: # GHC/Clash starts extremely slowly, see # https://github.com/clash-lang/clash-compiler/issues/2684 @@ -43,6 +43,9 @@ jobs: - os: "windows-latest" ghc: "9.12" + - os: "windows-latest" + ghc: "9.14" + steps: - uses: actions/checkout@v5 - uses: haskell-actions/setup@v2 @@ -152,7 +155,7 @@ jobs: # Run steps inside the clash CI docker image container: - image: ghcr.io/clash-lang/clash-ci:${{ matrix.ghc }}-20260417 + image: ghcr.io/clash-lang/clash-ci:${{ matrix.ghc }}-20260515 env: THREADS: 2 diff --git a/.github/workflows/nix.yml b/.github/workflows/nix.yml index 04d060ecfe..d6864d1ccf 100644 --- a/.github/workflows/nix.yml +++ b/.github/workflows/nix.yml @@ -79,7 +79,6 @@ jobs: "clash-prelude-hedgehog", "clash-profiling", "clash-profiling-prepare", - "clash-term", "clash-testsuite" ] exclude: diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 22a6bb9db0..0edd0021b9 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -34,6 +34,9 @@ tests: CI_PARENT_PIPELINE_SOURCE: $CI_PIPELINE_SOURCE parallel: matrix: + - GHC_VERSION: 9.14.1 + RUN_TESTS: "always" + - GHC_VERSION: 9.12.4 RUN_TESTS: "always" diff --git a/cabal.project b/cabal.project index 8b38d391ed..d9e6388bd2 100644 --- a/cabal.project +++ b/cabal.project @@ -15,7 +15,7 @@ write-ghc-environment-files: always -- index state, to go along with the cabal.project.freeze file. update the index -- state by running `cabal update` twice and looking at the index state it -- displays to you (as the second update will be a no-op) -index-state: 2026-05-09T11:46:50Z +index-state: 2026-05-15T04:09:15Z -- For some reason the `clash-testsuite` executable fails to run without -- this, as it cannot find the related library... @@ -54,23 +54,14 @@ optional-packages: ./benchmark/profiling/prepare ./benchmark/profiling/run ./clash-cosim - ./clash-term allow-newer: - brick:base, - brick:deepseq, - hashable, - hedgehog-fakedata:hedgehog, - rewrite-inspector:binary, - rewrite-inspector:containers, - vty:deepseq, derive-storable-plugin:ghc, derive-storable-plugin:ghci, string-random:text, string-random:containers, - string-interpolate:template-haskell, - string-interpolate:text, - hint:ghc + ordered-containers:containers, + boring:base, -- Works around: https://github.com/recursion-schemes/recursion-schemes/issues/128. This -- shouldn't harm (runtime) performance of Clash, as we only use recursion-schemes with @@ -80,7 +71,3 @@ package recursion-schemes package regex-tdfa optimization: 2 - - --- rewrite-inspector-0.1.0.11 uses brick-0.50 which doesn't compile with vty-6.0 -constraints: vty < 6.0 diff --git a/changelog/2026-05-15T07_25_33+02_00_add_ghc914 b/changelog/2026-05-15T07_25_33+02_00_add_ghc914 new file mode 100644 index 0000000000..c565b8f55a --- /dev/null +++ b/changelog/2026-05-15T07_25_33+02_00_add_ghc914 @@ -0,0 +1 @@ +ADDED: Added support for GHC 9.14 diff --git a/clash-ffi/clash-ffi.cabal b/clash-ffi/clash-ffi.cabal index ec1c84af49..8c7a0cec8b 100644 --- a/clash-ffi/clash-ffi.cabal +++ b/clash-ffi/clash-ffi.cabal @@ -20,7 +20,7 @@ common common-options ghc-options: -Wall -Wcompat build-depends: - base >= 4.11 && < 4.22, + base >= 4.11 && < 4.23, bytestring >= 0.10 && < 0.13, clash-prelude >= 1.2 && < 1.12, deepseq >= 1.4 && < 1.6, diff --git a/clash-ffi/example/cabal.project b/clash-ffi/example/cabal.project index 41a89c8e1c..7b3eec625d 100644 --- a/clash-ffi/example/cabal.project +++ b/clash-ffi/example/cabal.project @@ -3,9 +3,5 @@ packages: . .. ../../clash-ghc ../../clash-lib ../../clash-prelude write-ghc-environment-files: always allow-newer: - hashable, derive-storable-plugin:ghc, derive-storable-plugin:ghci, - string-interpolate:template-haskell, - string-interpolate:text, - hint:ghc diff --git a/clash-ffi/example/clash-ffi-example.cabal b/clash-ffi/example/clash-ffi-example.cabal index d5679e70d5..3f4fbc7644 100644 --- a/clash-ffi/example/clash-ffi-example.cabal +++ b/clash-ffi/example/clash-ffi-example.cabal @@ -14,9 +14,9 @@ category: Hardware custom-setup setup-depends: base >= 4.11 && < 5, - Cabal >= 2.4 && < 3.14, + Cabal >= 2.4 && < 3.17, directory >= 1.3.6 && < 1.4, - filepath >= 1.4.2 && < 1.5, + filepath >= 1.4.2 && < 1.6, foreign-library clash-ffi-example default-language: Haskell2010 diff --git a/clash-ghc/clash-ghc.cabal b/clash-ghc/clash-ghc.cabal index 77367d0a8c..5589464af8 100644 --- a/clash-ghc/clash-ghc.cabal +++ b/clash-ghc/clash-ghc.cabal @@ -81,7 +81,7 @@ executable clash GHC-Options: -- -T: Workaround for GHC #8754: if the GC stats aren't enabled because -- the -- compiler couldn't use -Bsymbolic to link the default hooks, then - -- initialize them sensibly. + -- initialize them sensibly. -- -- -I5: See GHC #3408: the default idle GC time of 0.3s is too short on -- Windows where we receive console events once per second or so. @@ -137,7 +137,9 @@ common common-options library import: common-options HS-Source-Dirs: src-ghc, src-bin-common - if impl(ghc >= 9.12.0) + if impl(ghc >= 9.14.0) + HS-Source-Dirs: src-bin-9.14 + elif impl(ghc >= 9.12.0) HS-Source-Dirs: src-bin-9.12 elif impl(ghc >= 9.10.2) HS-Source-Dirs: src-bin-9.10.2 @@ -179,17 +181,17 @@ library ghc-typelits-knownnat, ghc-typelits-natnormalise, deepseq >= 1.3.0.2 && < 1.6, - time >= 1.4.0.1 && < 1.15, - ghc >= 9.6.0 && < 9.13, - ghc-bignum >= 1.0 && < 1.4, - ghc-boot >= 9.6.0 && < 9.13, + time >= 1.4.0.1 && < 1.17, + ghc >= 9.6.0 && < 9.15, + ghc-bignum >= 1.0 && < 1.5, + ghc-boot >= 9.6.0 && < 9.15, ghc-prim >= 0.10 && < 0.14, - ghci >= 9.6.0 && < 9.13, + ghci >= 9.6.0 && < 9.15, uniplate >= 1.6.12 && < 1.8, reflection >= 2.1.2 && < 3.0, primitive >= 0.5.0.1 && < 1.0, string-interpolate ^>= 0.3, - template-haskell >= 2.8.0.0 && < 2.24, + template-haskell >= 2.8.0.0 && < 2.25, utf8-string >= 1.0.0.0 && < 1.1.0.0, vector >= 0.11 && < 1.0, exceptions >= 0.10.4 && < 0.11, @@ -238,3 +240,8 @@ library Other-Modules: Clash.GHCi.UI.Exception else Other-Modules: Clash.GHCi.UI.Tags + + if impl(ghc >= 9.14.0) + Other-Modules: Clash.GHCi.UI.Print + Clash.GHC.Driver.Session.Lint + Clash.GHC.Driver.Session.Mode diff --git a/clash-ghc/src-bin-9.14/Clash/GHC/Driver/Session/Lint.hs b/clash-ghc/src-bin-9.14/Clash/GHC/Driver/Session/Lint.hs new file mode 100644 index 0000000000..e75850e9db --- /dev/null +++ b/clash-ghc/src-bin-9.14/Clash/GHC/Driver/Session/Lint.hs @@ -0,0 +1,124 @@ +{-# LANGUAGE CPP #-} +{-# LANGUAGE LambdaCase #-} +{-# LANGUAGE NondecreasingIndentation #-} +{-# LANGUAGE TupleSections #-} +module Clash.GHC.Driver.Session.Lint (checkOptions) where + +import GHC.Driver.Backend +import GHC.Driver.Phases +import GHC.Driver.Session +import GHC.Platform.Ways + +import GHC.Utils.Misc +import GHC.Utils.Panic + +import GHC.Data.Maybe + +import System.IO +import Control.Monad +import qualified Data.Set as Set +import Prelude + +import Clash.GHC.Driver.Session.Mode + +-- ----------------------------------------------------------------------------- +-- Option sanity checks + +-- | Ensure sanity of options. +-- +-- Throws 'UsageError' or 'CmdLineError' if not. +checkOptions :: PostLoadMode -> DynFlags -> [(String,Maybe Phase)] -> [String] -> [String] -> IO () + -- Final sanity checking before kicking off a compilation (pipeline). +checkOptions mode dflags srcs objs units = do + -- Complain about any unknown flags + let unknown_opts = [ f | (f@('-':_), _) <- srcs ] + when (notNull unknown_opts) (unknownFlagsErr unknown_opts) + + when (not (Set.null (rtsWays (ways dflags))) + && isInterpretiveMode mode) $ + hPutStrLn stderr ("Warning: -debug, -threaded and -ticky are ignored by GHCi") + + -- -prof and --interactive are not a good combination + when ((fullWays (ways dflags) /= hostFullWays) + && LinkInMemory == ghcLink dflags + && not (gopt Opt_ExternalInterpreter dflags)) $ + do throwGhcException (UsageError + "-fexternal-interpreter is required when using --interactive with a non-standard way (-prof, -static, or -dynamic).") + -- -ohi sanity check + if (isJust (outputHi dflags) && + (isCompManagerMode mode || srcs `lengthExceeds` 1)) + then throwGhcException (UsageError "-ohi can only be used when compiling a single source file") + else do + + if (isJust (dynOutputHi dflags) && + (isCompManagerMode mode || srcs `lengthExceeds` 1)) + then throwGhcException (UsageError "-dynohi can only be used when compiling a single source file") + else do + + -- -o sanity checking + if (srcs `lengthExceeds` 1 && isJust (outputFile dflags) + && not (isLinkMode mode)) + then throwGhcException (UsageError "can't apply -o to multiple source files") + else do + + let not_linking = not (isLinkMode mode) || isNoLink (ghcLink dflags) + + when (not_linking && not (null objs)) $ + hPutStrLn stderr ("Warning: the following files would be used as linker inputs, but linking is not being done: " ++ unwords objs) + + -- Check that there are some input files + -- (except in the interactive case) + if null srcs && (null objs || not_linking) && needsInputsMode mode && null units + then throwGhcException (UsageError "no input files" ) + else do + + case mode of + StopBefore StopC | not (backendGeneratesHc (backend dflags)) + -> throwGhcException $ UsageError $ + "the option -C is only available with an unregisterised GHC" + StopBefore StopAs | ghcLink dflags == NoLink + -> throwGhcException $ UsageError $ + "the options -S and -fno-code are incompatible. Please omit -S" + + _ -> return () + + -- Verify that output files point somewhere sensible. + verifyOutputFiles dflags + +-- Compiler output options + +-- Called to verify that the output files point somewhere valid. +-- +-- The assumption is that the directory portion of these output +-- options will have to exist by the time 'verifyOutputFiles' +-- is invoked. +-- +-- We create the directories for -odir, -hidir, -outputdir etc. ourselves if +-- they don't exist, so don't check for those here (#2278). +verifyOutputFiles :: DynFlags -> IO () +verifyOutputFiles dflags = do + let ofile = outputFile dflags + when (isJust ofile) $ do + let fn = fromJust ofile + flg <- doesDirNameExist fn + when (not flg) (nonExistentDir "-o" fn) + let ohi = outputHi dflags + when (isJust ohi) $ do + let hi = fromJust ohi + flg <- doesDirNameExist hi + when (not flg) (nonExistentDir "-ohi" hi) + where + nonExistentDir flg dir = + throwGhcException (CmdLineError ("error: directory portion of " ++ + show dir ++ " does not exist (used with " ++ + show flg ++ " option.)")) + +-- | Utility for reporting unknown flag error +unknownFlagsErr :: [String] -> a +unknownFlagsErr fs = throwGhcException $ UsageError $ concatMap oneError fs + where + oneError f = + "unrecognised flag: " ++ f ++ "\n" ++ + (case flagSuggestions (nubSort allNonDeprecatedFlags) f of + [] -> "" + suggs -> "did you mean one of:\n" ++ unlines (map (" " ++) suggs)) diff --git a/clash-ghc/src-bin-9.14/Clash/GHC/Driver/Session/Mode.hs b/clash-ghc/src-bin-9.14/Clash/GHC/Driver/Session/Mode.hs new file mode 100644 index 0000000000..1a6b581ea6 --- /dev/null +++ b/clash-ghc/src-bin-9.14/Clash/GHC/Driver/Session/Mode.hs @@ -0,0 +1,343 @@ +{-# LANGUAGE CPP #-} +{-# LANGUAGE LambdaCase #-} +{-# LANGUAGE NondecreasingIndentation #-} +{-# LANGUAGE TupleSections #-} +module Clash.GHC.Driver.Session.Mode where + +import GHC.Driver.CmdLine +import GHC.Driver.Phases +import GHC.Driver.Session +import GHC.Unit.Module ( ModuleName, mkModuleName ) + +import GHC.Types.SrcLoc + +import GHC.Utils.Panic + +import GHC.Data.Maybe + +-- Standard Haskell libraries +import System.IO +import Control.Monad +import Data.Char +import Prelude + +----------------------------------------------------------------------------- +-- GHC modes of operation + +type Mode = Either PreStartupMode PostStartupMode +type PostStartupMode = Either PreLoadMode PostLoadMode + +data PreStartupMode + = ShowVersion -- ghc -V/--version + | ShowNumVersion -- ghc --numeric-version + | ShowSupportedExtensions -- ghc --supported-extensions + | ShowOptions Bool {- isInteractive -} -- ghc --show-options + +showVersionMode, showNumVersionMode, showSupportedExtensionsMode, showOptionsMode :: Mode +showVersionMode = mkPreStartupMode ShowVersion +showNumVersionMode = mkPreStartupMode ShowNumVersion +showSupportedExtensionsMode = mkPreStartupMode ShowSupportedExtensions +showOptionsMode = mkPreStartupMode (ShowOptions False) + +mkPreStartupMode :: PreStartupMode -> Mode +mkPreStartupMode = Left + +isShowVersionMode :: Mode -> Bool +isShowVersionMode (Left ShowVersion) = True +isShowVersionMode _ = False + +isShowNumVersionMode :: Mode -> Bool +isShowNumVersionMode (Left ShowNumVersion) = True +isShowNumVersionMode _ = False + +data PreLoadMode + = ShowGhcUsage -- ghc -? + | ShowGhciUsage -- ghci -? + | ShowInfo -- ghc --info + | PrintWithDynFlags (DynFlags -> String) -- ghc --print-foo + +showGhcUsageMode, showGhciUsageMode, showInfoMode :: Mode +showGhcUsageMode = mkPreLoadMode ShowGhcUsage +showGhciUsageMode = mkPreLoadMode ShowGhciUsage +showInfoMode = mkPreLoadMode ShowInfo + +printSetting :: String -> Mode +printSetting k = mkPreLoadMode (PrintWithDynFlags f) + where f dflags = fromMaybe (panic ("Setting not found: " ++ show k)) + $ lookup k (compilerInfo dflags) + +mkPreLoadMode :: PreLoadMode -> Mode +mkPreLoadMode = Right . Left + +isShowGhcUsageMode :: Mode -> Bool +isShowGhcUsageMode (Right (Left ShowGhcUsage)) = True +isShowGhcUsageMode _ = False + +isShowGhciUsageMode :: Mode -> Bool +isShowGhciUsageMode (Right (Left ShowGhciUsage)) = True +isShowGhciUsageMode _ = False + +data PostLoadMode + = ShowInterface FilePath -- ghc --show-iface + | DoMkDependHS -- ghc -M + | StopBefore StopPhase -- ghc -E | -C | -S + -- StopBefore StopLn is the default + | DoMake -- ghc --make + | DoBackpack -- ghc --backpack foo.bkp + | DoInteractive -- ghc --interactive + | DoEval [String] -- ghc -e foo -e bar => DoEval ["bar", "foo"] + | DoRun -- ghc --run + | DoAbiHash -- ghc --abi-hash + | ShowPackages -- ghc --show-packages + | DoFrontend ModuleName -- ghc --frontend Plugin.Module + | DoVHDL -- ghc --vhdl + | DoVerilog -- ghc --verilog + | DoSystemVerilog -- ghc --systemverilog + +doMkDependHSMode, doMakeMode, doInteractiveMode, doRunMode, + doAbiHashMode, showUnitsMode, doVHDLMode, doVerilogMode, + doSystemVerilogMode :: Mode +doMkDependHSMode = mkPostLoadMode DoMkDependHS +doMakeMode = mkPostLoadMode DoMake +doInteractiveMode = mkPostLoadMode DoInteractive +doRunMode = mkPostLoadMode DoRun +doAbiHashMode = mkPostLoadMode DoAbiHash +showUnitsMode = mkPostLoadMode ShowPackages +doVHDLMode = mkPostLoadMode DoVHDL +doVerilogMode = mkPostLoadMode DoVerilog +doSystemVerilogMode = mkPostLoadMode DoSystemVerilog + +showInterfaceMode :: FilePath -> Mode +showInterfaceMode fp = mkPostLoadMode (ShowInterface fp) + +stopBeforeMode :: StopPhase -> Mode +stopBeforeMode phase = mkPostLoadMode (StopBefore phase) + +doEvalMode :: String -> Mode +doEvalMode str = mkPostLoadMode (DoEval [str]) + +doFrontendMode :: String -> Mode +doFrontendMode str = mkPostLoadMode (DoFrontend (mkModuleName str)) + +doBackpackMode :: Mode +doBackpackMode = mkPostLoadMode DoBackpack + +mkPostLoadMode :: PostLoadMode -> Mode +mkPostLoadMode = Right . Right + +isDoInteractiveMode :: Mode -> Bool +isDoInteractiveMode (Right (Right DoInteractive)) = True +isDoInteractiveMode _ = False + +isStopLnMode :: Mode -> Bool +isStopLnMode (Right (Right (StopBefore NoStop))) = True +isStopLnMode _ = False + +isDoMakeMode :: Mode -> Bool +isDoMakeMode (Right (Right DoMake)) = True +isDoMakeMode _ = False + +isDoEvalMode :: Mode -> Bool +isDoEvalMode (Right (Right (DoEval _))) = True +isDoEvalMode _ = False + +#if defined(HAVE_INTERNAL_INTERPRETER) +isInteractiveMode :: PostLoadMode -> Bool +isInteractiveMode DoInteractive = True +isInteractiveMode _ = False +#endif + +-- isInterpretiveMode: byte-code compiler involved +isInterpretiveMode :: PostLoadMode -> Bool +isInterpretiveMode DoInteractive = True +isInterpretiveMode (DoEval _) = True +isInterpretiveMode _ = False + +needsInputsMode :: PostLoadMode -> Bool +needsInputsMode DoMkDependHS = True +needsInputsMode (StopBefore _) = True +needsInputsMode DoMake = True +needsInputsMode DoVHDL = True +needsInputsMode DoVerilog = True +needsInputsMode DoSystemVerilog = True +needsInputsMode _ = False + +-- True if we are going to attempt to link in this mode. +-- (we might not actually link, depending on the GhcLink flag) +isLinkMode :: PostLoadMode -> Bool +isLinkMode (StopBefore NoStop) = True +isLinkMode DoMake = True +isLinkMode DoRun = True +isLinkMode DoInteractive = True +isLinkMode (DoEval _) = True +isLinkMode _ = False + +isCompManagerMode :: PostLoadMode -> Bool +isCompManagerMode DoRun = True +isCompManagerMode DoMake = True +isCompManagerMode DoInteractive = True +isCompManagerMode (DoEval _) = True +isCompManagerMode DoVHDL = True +isCompManagerMode DoVerilog = True +isCompManagerMode DoSystemVerilog = True +isCompManagerMode _ = False + +-- ----------------------------------------------------------------------------- +-- Parsing the mode flag + +parseModeFlags :: [Located String] + -> IO (Mode, [String], + [Located String], + [Warn]) +parseModeFlags args = do + ((leftover, errs1, warns), (mModeFlag, units, errs2, flags')) <- + processCmdLineP mode_flags (Nothing, [], [], []) args + let mode = case mModeFlag of + Nothing -> doMakeMode + Just (m, _) -> m + + -- See Note [Handling errors when parsing command-line flags] + unless (null errs1 && null errs2) $ throwGhcException $ errorsToGhcException $ + map (("on the commandline", )) $ map (unLoc . errMsg) errs1 ++ errs2 + + return (mode, units, flags' ++ leftover, warns) + +type ModeM = CmdLineP (Maybe (Mode, String), [String], [String], [Located String]) + -- mode flags sometimes give rise to new DynFlags (eg. -C, see below) + -- so we collect the new ones and return them. + +mode_flags :: [Flag ModeM] +mode_flags = + [ ------- help / version ---------------------------------------------- + defFlag "?" (PassFlag (setMode showGhcUsageMode)) + , defFlag "-help" (PassFlag (setMode showGhcUsageMode)) + , defFlag "V" (PassFlag (setMode showVersionMode)) + , defFlag "-version" (PassFlag (setMode showVersionMode)) + , defFlag "-numeric-version" (PassFlag (setMode showNumVersionMode)) + , defFlag "-info" (PassFlag (setMode showInfoMode)) + , defFlag "-show-options" (PassFlag (setMode showOptionsMode)) + , defFlag "-supported-languages" (PassFlag (setMode showSupportedExtensionsMode)) + , defFlag "-supported-extensions" (PassFlag (setMode showSupportedExtensionsMode)) + , defFlag "-show-packages" (PassFlag (setMode showUnitsMode)) + ] ++ + [ defFlag k' (PassFlag (setMode (printSetting k))) + | k <- ["Project version", + "Project Git commit id", + "Booter version", + "Stage", + "Build platform", + "Host platform", + "Target platform", + "Have interpreter", + "Object splitting supported", + "Have native code generator", + "Support SMP", + "Unregisterised", + "Tables next to code", + "RTS ways", + "Leading underscore", + "Debug on", + "LibDir", + "Global Package DB", + "C compiler flags", + "C compiler link flags" + ], + let k' = "-print-" ++ map (replaceSpace . toLower) k + replaceSpace ' ' = '-' + replaceSpace c = c + ] ++ + ------- interfaces ---------------------------------------------------- + [ defFlag "-show-iface" (HasArg (\f -> setMode (showInterfaceMode f) + "--show-iface")) + + ------- primary modes ------------------------------------------------ + , defFlag "c" (PassFlag (\f -> do setMode (stopBeforeMode NoStop) f + addFlag "-no-link" f)) + , defFlag "M" (PassFlag (setMode doMkDependHSMode)) + , defFlag "E" (PassFlag (setMode (stopBeforeMode StopPreprocess ))) + , defFlag "C" (PassFlag (setMode (stopBeforeMode StopC))) + , defFlag "S" (PassFlag (setMode (stopBeforeMode StopAs))) + , defFlag "-run" (PassFlag (setMode doRunMode)) + , defFlag "-make" (PassFlag (setMode doMakeMode)) + , defFlag "unit" (SepArg (\s -> addUnit s "-unit")) + , defFlag "-backpack" (PassFlag (setMode doBackpackMode)) + , defFlag "-interactive" (PassFlag (setMode doInteractiveMode)) + , defFlag "-abi-hash" (PassFlag (setMode doAbiHashMode)) + , defFlag "e" (SepArg (\s -> setMode (doEvalMode s) "-e")) + , defFlag "-frontend" (SepArg (\s -> setMode (doFrontendMode s) "-frontend")) + , defFlag "-vhdl" (PassFlag (setMode doVHDLMode)) + , defFlag "-verilog" (PassFlag (setMode doVerilogMode)) + , defFlag "-systemverilog" (PassFlag (setMode doSystemVerilogMode)) + ] + +addUnit :: String -> String -> EwM ModeM () +addUnit unit_str _arg = liftEwM $ do + (mModeFlag, units, errs, flags') <- getCmdLineState + putCmdLineState (mModeFlag, unit_str:units, errs, flags') + +setMode :: Mode -> String -> EwM ModeM () +setMode newMode newFlag = liftEwM $ do + (mModeFlag, units, errs, flags') <- getCmdLineState + let (modeFlag', errs') = + case mModeFlag of + Nothing -> ((newMode, newFlag), errs) + Just (oldMode, oldFlag) -> + case (oldMode, newMode) of + -- -c/--make are allowed together, and mean --make -no-link + _ | isStopLnMode oldMode && isDoMakeMode newMode + || isStopLnMode newMode && isDoMakeMode oldMode -> + ((doMakeMode, "--make"), []) + + -- If we have both --help and --interactive then we + -- want showGhciUsage + _ | isShowGhcUsageMode oldMode && + isDoInteractiveMode newMode -> + ((showGhciUsageMode, oldFlag), []) + | isShowGhcUsageMode newMode && + isDoInteractiveMode oldMode -> + ((showGhciUsageMode, newFlag), []) + + -- If we have both -e and --interactive then -e always wins + _ | isDoEvalMode oldMode && + isDoInteractiveMode newMode -> + ((oldMode, oldFlag), []) + | isDoEvalMode newMode && + isDoInteractiveMode oldMode -> + ((newMode, newFlag), []) + + -- Otherwise, --help/--version/--numeric-version always win + | isDominantFlag oldMode -> ((oldMode, oldFlag), []) + | isDominantFlag newMode -> ((newMode, newFlag), []) + -- We need to accumulate eval flags like "-e foo -e bar" + (Right (Right (DoEval esOld)), + Right (Right (DoEval [eNew]))) -> + ((Right (Right (DoEval (eNew : esOld))), oldFlag), + errs) + -- Saying e.g. --interactive --interactive is OK + _ | oldFlag == newFlag -> ((oldMode, oldFlag), errs) + + -- --interactive and --show-options are used together + (Right (Right DoInteractive), Left (ShowOptions _)) -> + ((Left (ShowOptions True), + "--interactive --show-options"), errs) + (Left (ShowOptions _), (Right (Right DoInteractive))) -> + ((Left (ShowOptions True), + "--show-options --interactive"), errs) + -- Otherwise, complain + _ -> let err = flagMismatchErr oldFlag newFlag + in ((oldMode, oldFlag), err : errs) + putCmdLineState (Just modeFlag', units, errs', flags') + where isDominantFlag f = isShowGhcUsageMode f || + isShowGhciUsageMode f || + isShowVersionMode f || + isShowNumVersionMode f + +flagMismatchErr :: String -> String -> String +flagMismatchErr oldFlag newFlag + = "cannot use `" ++ oldFlag ++ "' with `" ++ newFlag ++ "'" + +addFlag :: String -> String -> EwM ModeM () +addFlag s flag = liftEwM $ do + (m, units, e, flags') <- getCmdLineState + putCmdLineState (m, units, e, mkGeneralLocated loc s : flags') + where loc = "addFlag by " ++ flag ++ " on the commandline" diff --git a/clash-ghc/src-bin-9.14/Clash/GHCi/Leak.hs b/clash-ghc/src-bin-9.14/Clash/GHCi/Leak.hs new file mode 100644 index 0000000000..f049c86cc7 --- /dev/null +++ b/clash-ghc/src-bin-9.14/Clash/GHCi/Leak.hs @@ -0,0 +1,88 @@ +{-# LANGUAGE RecordWildCards, LambdaCase #-} +module Clash.GHCi.Leak + ( LeakIndicators + , getLeakIndicators + , checkLeakIndicators + ) where + +import Clash.GHCi.Util +import Control.Monad +import Data.Bits +import Data.IORef +import Foreign.Ptr (ptrToIntPtr, intPtrToPtr) +import GHC +import GHC.Ptr (Ptr (..)) +import GHC.Driver.Env +import GHC.Driver.Ppr +import GHC.Utils.Outputable +import GHC.Unit.Module.ModDetails +import GHC.Unit.Home.ModInfo +import GHC.Unit.Home.PackageTable +import GHC.Platform (target32Bit) +import GHC.Linker.Types +import Prelude +import System.Mem +import System.Mem.Weak +import GHC.Types.Unique.DFM +import Control.Exception + +-- Checking for space leaks in GHCi. See #15111, and the +-- -fghci-leak-check flag. + +data LeakIndicators = LeakIndicators [LeakModIndicators] + +data LeakModIndicators = LeakModIndicators + { leakMod :: Weak HomeModInfo + , leakIface :: Weak ModIface + , leakDetails :: Weak ModDetails + , leakLinkable :: [Maybe (Weak Linkable)] + } + +-- | Grab weak references to some of the data structures representing +-- the currently loaded modules. +getLeakIndicators :: HscEnv -> IO LeakIndicators +getLeakIndicators hsc_env = + fmap LeakIndicators $ do + hpt <- readIORef $ hptInternalTableRef $ hsc_HPT hsc_env + forM (eltsUDFM hpt) $ \hmi@HomeModInfo{..} -> do + leakMod <- mkWeakPtr hmi Nothing + leakIface <- mkWeakPtr hm_iface Nothing + leakDetails <- mkWeakPtr hm_details Nothing + leakLinkable <- mkWeakLinkables hm_linkable + return $ LeakModIndicators{..} + where + mkWeakLinkables :: HomeModLinkable -> IO [Maybe (Weak Linkable)] + mkWeakLinkables (HomeModLinkable mbc mo) = + mapM (\ln -> traverse (flip mkWeakPtr Nothing <=< evaluate) ln) [mbc, mo] + +-- | Look at the LeakIndicators collected by an earlier call to +-- `getLeakIndicators`, and print messasges if any of them are still +-- alive. +checkLeakIndicators :: DynFlags -> LeakIndicators -> IO () +checkLeakIndicators dflags (LeakIndicators leakmods) = do + performGC + forM_ leakmods $ \LeakModIndicators{..} -> do + deRefWeak leakMod >>= \case + Nothing -> return () + Just hmi -> + report ("HomeModInfo for " ++ + showSDoc dflags (ppr (mi_module (hm_iface hmi)))) (Just hmi) + deRefWeak leakIface >>= \case + Nothing -> return () + Just miface -> report ("ModIface:" ++ moduleNameString (moduleName (mi_module miface))) (Just miface) + deRefWeak leakDetails >>= report "ModDetails" + forM_ leakLinkable $ \l -> forM_ l $ \l' -> deRefWeak l' >>= report "Linkable" + where + report :: String -> Maybe a -> IO () + report _ Nothing = return () + report msg (Just a) = do + addr <- anyToPtr a + putStrLn ("-fghci-leak-check: " ++ msg ++ " is still alive at " ++ + show (maskTagBits addr)) + + tagBits + | target32Bit (targetPlatform dflags) = 2 + | otherwise = 3 + + maskTagBits :: Ptr a -> Ptr a + maskTagBits p = intPtrToPtr (ptrToIntPtr p .&. complement (shiftL 1 tagBits - 1)) diff --git a/clash-ghc/src-bin-9.14/Clash/GHCi/UI.hs b/clash-ghc/src-bin-9.14/Clash/GHCi/UI.hs new file mode 100644 index 0000000000..d6ffe77cd8 --- /dev/null +++ b/clash-ghc/src-bin-9.14/Clash/GHCi/UI.hs @@ -0,0 +1,5118 @@ +{-# LANGUAGE CPP #-} +{-# LANGUAGE BangPatterns #-} +{-# LANGUAGE LambdaCase #-} +{-# LANGUAGE MagicHash #-} +{-# LANGUAGE MultiWayIf #-} +{-# LANGUAGE NondecreasingIndentation #-} +{-# LANGUAGE OverloadedStrings #-} +{-# LANGUAGE RecordWildCards #-} +{-# LANGUAGE ScopedTypeVariables #-} +{-# LANGUAGE TupleSections #-} +{-# LANGUAGE ViewPatterns #-} +{-# LANGUAGE TypeFamilies #-} +{-# LANGUAGE DataKinds #-} + +{-# OPTIONS -fno-warn-name-shadowing #-} +-- This module does a lot of it + +----------------------------------------------------------------------------- +-- +-- GHC Interactive User Interface +-- +-- (c) The GHC Team 2005-2006 +-- +----------------------------------------------------------------------------- + +module Clash.GHCi.UI ( + interactiveUI, + GhciSettings(..), + defaultGhciSettings, + ghciCommands, + ghciWelcomeMsg, + makeHDL + ) where + +-- GHCi +import qualified Clash.GHCi.UI.Monad as GhciMonad ( args, runStmt, runDecls' ) +import Clash.GHCi.UI.Monad hiding ( args, runStmt ) +import Clash.GHCi.UI.Info +import Clash.GHCi.UI.Exception hiding (GHCi) + +import GHC.Runtime.Debugger +import GHC.Runtime.Debugger.Breakpoints +import GHC.Runtime.Eval (mkTopLevEnv) +import GHC.Runtime.Eval.Utils + +-- The GHC interface +import GHC.ByteCode.Breakpoints (imodBreaks_modBreaks, InternalBreakpointId(..), getBreakSourceId, getBreakSourceMod) +import GHC.Runtime.Interpreter +import GHCi.RemoteTypes +import GHCi.BreakArray( breakOn, breakOff ) +import GHC.Core.DataCon +import GHC.Core.ConLike +import GHC.Core.PatSyn +import GHC.Driver.Flags +import GHC.Driver.Errors +import GHC.Driver.Errors.Types +import GHC.Driver.Phases +import GHC.Driver.Session as DynFlags +import GHC.Driver.Ppr hiding (printForUser) +import GHC.Utils.Error hiding (traceCmd) +import GHC.Driver.Monad ( modifySession, modifySessionM ) +import GHC.Driver.Make ( newIfaceCache, ModIfaceCache(..) ) +import GHC.Driver.Config.Parser +import GHC.Driver.Config.Diagnostic +import qualified GHC +import GHC ( LoadHowMuch(..), Target(..), TargetId(..), + Resume, SingleStep, Ghc, + GetDocsFailure(..), pushLogHookM, + getModuleGraph, handleSourceError, + BreakpointId(..) ) +import GHC.Driver.Main (hscParseModuleWithLocation, hscParseStmtWithLocation) +import GHC.Hs.ImpExp +import GHC.Hs +import GHC.Driver.Env +import GHC.Runtime.Context +import GHC.Types.TyThing +import GHC.Types.TyThing.Ppr +import GHC.Core.TyCo.Ppr +import GHC.Types.SafeHaskell ( getSafeMode ) +import GHC.Types.SourceError ( SourceError ) +import GHC.Types.Name +import GHC.Types.Var ( varType ) +import GHC.Iface.Syntax ( showToHeader ) +import GHC.Builtin.Names +import GHC.Builtin.Types( stringTyCon_RDR ) +import GHC.Types.Name.Reader as RdrName ( getGRE_NameQualifier_maybes, getRdrName, greName, globalRdrEnvElts) +import GHC.Types.SrcLoc as SrcLoc +import qualified GHC.Parser.Lexer as Lexer +import GHC.Parser.Header ( toArgs ) +import qualified GHC.Parser.Header as Header +import GHC.Types.PkgQual + +import GHC.Unit +import GHC.Unit.Finder as Finder +import GHC.Unit.Module.Graph (filterToposortToModules) +import GHC.Unit.Module.ModSummary + +import GHC.Data.StringBuffer +import GHC.Utils.Outputable +import GHC.Utils.Logger + +-- Other random utilities +import GHC.Types.Basic hiding ( isTopLevel ) +import GHC.Data.Graph.Directed +import GHC.Utils.Encoding +import GHC.Data.FastString +import qualified GHC.Linker.Loader as Loader +import GHC.Data.Maybe ( expectJust ) +import GHC.Types.Name.Set +import GHC.Utils.Panic hiding ( showException, try ) +import GHC.Utils.Misc +import qualified GHC.LanguageExtensions as LangExt +import qualified GHC.Data.Strict as Strict +import GHC.Types.Error +import qualified GHC.Unit.Home.Graph as HUG + +-- Haskell Libraries +import System.Console.Haskeline as Haskeline + +import Control.Applicative hiding (empty) +import Control.DeepSeq (deepseq) +import Control.Monad as Monad +import Control.Monad.Catch as MC +import Control.Monad.IO.Class +import Control.Monad.Trans.Class +import Control.Monad.Trans.Except + +import Data.Array +import qualified Data.ByteString.Char8 as BS +import Data.Char +import Data.Function +import qualified Data.Foldable as Foldable +import Data.IORef ( IORef, modifyIORef, newIORef, readIORef, writeIORef ) +import Data.List ( find, intercalate, intersperse, + isPrefixOf, isSuffixOf, nub, partition, sort, sortBy, (\\) ) +import qualified Data.List.NonEmpty as NE +import qualified Data.Set as S +import Data.Maybe +import qualified Data.Map as M +import Data.IntMap.Strict (IntMap) +import qualified Data.IntMap.Strict as IntMap +import Data.Time.LocalTime ( getZonedTime ) +import Data.Time.Format ( formatTime, defaultTimeLocale ) +import Data.Version ( showVersion ) +import qualified Data.Semigroup as S +import Prelude hiding ((<>)) + +import GHC.Utils.Exception as Exception hiding (catch, mask, handle) +import Foreign hiding (void) +import GHC.Stack hiding (SrcLoc(..)) +import GHC.Unit.Env +import GHC.Unit.Home.PackageTable + +import System.Directory +import System.Environment +import System.Exit ( exitWith, ExitCode(..) ) +import System.FilePath +import System.Info +import System.IO +import System.IO.Error +import System.IO.Unsafe ( unsafePerformIO ) +import System.Process +import Text.Printf +import Text.Read ( readMaybe ) +import Text.Read.Lex (isSymbolChar) + +import Unsafe.Coerce + +#if !defined(mingw32_HOST_OS) +import System.Posix hiding ( getEnv ) +#else +import qualified System.Win32 +#endif + +import GHC.IO.Exception ( IOErrorType(InvalidArgument) ) +import GHC.IO.Handle ( hFlushAll ) +import GHC.TopHandler ( topHandler ) + +import qualified GHC.Unit.Module.Graph as GHC + + +-- clash additions +import Clash.Backend (Backend(initBackend, hdlKind, primDirs)) +import Clash.Backend.SystemVerilog (SystemVerilogState) +import Clash.Backend.VHDL (VHDLState) +import Clash.Backend.Verilog (VerilogState) +import qualified Clash.Driver +import Clash.Driver.Bool (fromGhcOverridingBool) +import Clash.Driver.Types (ClashOpts(..), ClashEnv(..), ClashDesign(..)) +import Clash.GHC.Evaluator +import Clash.GHC.GenerateBindings +import Clash.GHC.NetlistTypes +import Clash.GHC.PartialEval +import Clash.GHCi.Common +import Clash.GHCi.Leak +import Clash.GHCi.UI.Print +import Clash.Util (clashLibVersion, reportTimeDiff) +import Data.Proxy +import qualified Data.Time.Clock as Clock +import qualified Paths_clash_ghc + +----------------------------------------------------------------------------- + +data GhciSettings = GhciSettings { + availableCommands :: [Command], + fullHelpText :: String, + defPrompt :: PromptFunction, + defPromptCont :: PromptFunction + } + +defaultGhciSettings :: IORef ClashOpts -> GhciSettings +defaultGhciSettings opts = + GhciSettings { + availableCommands = ghciCommands opts, + defPrompt = default_prompt, + defPromptCont = default_prompt_cont, + fullHelpText = defFullHelpText + } + +ghciWelcomeMsg :: String +ghciWelcomeMsg = + "Clashi, version " ++ Data.Version.showVersion Paths_clash_ghc.version ++ + " (using clash-lib, version " ++ Data.Version.showVersion clashLibVersion ++ + "):\nhttps://clash-lang.org/ :? for help" + +ghciCommands :: IORef ClashOpts -> [Command] +ghciCommands opts = map mkCmd [ + -- Hugs users are accustomed to :e, so make sure it doesn't overlap + ("?", keepGoing help, noCompletion), + ("add", keepGoingPaths addModule, completeFilename), + ("abandon", keepGoing abandonCmd, noCompletion), + ("break", keepGoing breakCmd, completeBreakpoint), + ("back", keepGoing backCmd, noCompletion), + ("browse", keepGoing' (browseCmd False), completeModule), + ("browse!", keepGoing' (browseCmd True), completeModule), + ("cd", keepGoing' changeDirectory, completeFilename), + ("continue", keepGoing' continueCmd, noCompletion), + ("cmd", keepGoing cmdCmd, completeExpression), + ("def", keepGoing (defineMacro False), completeExpression), + ("def!", keepGoing (defineMacro True), completeExpression), + ("delete", keepGoing deleteCmd, noCompletion), + ("disable", keepGoing disableCmd, noCompletion), + ("doc", keepGoing' docCmd, completeIdentifier), + ("edit", keepGoing' editFile, completeFilename), + ("enable", keepGoing enableCmd, noCompletion), + ("force", keepGoing forceCmd, completeExpression), + ("forward", keepGoing forwardCmd, noCompletion), + ("help", keepGoing help, noCompletion), + ("history", keepGoing historyCmd, noCompletion), + ("info", keepGoing' (info False), completeIdentifier), + ("info!", keepGoing' (info True), completeIdentifier), + ("issafe", keepGoing' isSafeCmd, completeModule), + ("ignore", keepGoing ignoreCmd, noCompletion), + ("kind", keepGoing' (kindOfType False), completeIdentifier), + ("kind!", keepGoing' (kindOfType True), completeIdentifier), + ("load", keepGoingPaths loadModule_, completeHomeModuleOrFile), + ("load!", keepGoingPaths loadModuleDefer, completeHomeModuleOrFile), + ("list", keepGoing' listCmd, noCompletion), + ("module", keepGoing moduleCmd, completeSetModule), + ("main", keepGoing runMain, completeFilename), + ("print", keepGoing printCmd, completeExpression), + ("quit", quit, noCompletion), + ("reload", keepGoing' reloadModule, noCompletion), + ("reload!", keepGoing' reloadModuleDefer, noCompletion), + ("run", keepGoing' runRun, completeFilename), + ("script", keepGoing' scriptCmd, completeFilename), + ("set", keepGoing setCmd, completeSetOptions), + ("seti", keepGoing setiCmd, completeSeti), + ("show", keepGoing' showCmd, completeShowOptions), + ("showi", keepGoing showiCmd, completeShowiOptions), + ("sprint", keepGoing sprintCmd, completeExpression), + ("step", keepGoing stepCmd, completeIdentifier), + ("steplocal", keepGoing stepLocalCmd, completeIdentifier), + ("stepout", keepGoing stepOutCmd, noCompletion), + ("stepmodule",keepGoing stepModuleCmd, completeIdentifier), + ("type", keepGoing' typeOfExpr, completeExpression), + ("trace", keepGoing traceCmd, completeExpression), + ("unadd", keepGoingPaths unAddModule, completeFilename), + ("undef", keepGoing undefineMacro, completeMacro), + ("unset", keepGoing unsetOptions, completeSetOptions), + ("where", keepGoing whereCmd, noCompletion), + ("vhdl", keepGoingPaths (makeVHDL opts), completeHomeModuleOrFile), + ("verilog", keepGoingPaths (makeVerilog opts), completeHomeModuleOrFile), + ("systemverilog", keepGoingPaths (makeSystemVerilog opts), completeHomeModuleOrFile), + ("instances", keepGoing' instancesCmd, completeExpression) + ] ++ map mkCmdHidden [ -- hidden commands + ("all-types", keepGoing' allTypesCmd), + ("complete", keepGoing completeCmd), + ("loc-at", keepGoing' locAtCmd), + ("type-at", keepGoing' typeAtCmd), + ("uses", keepGoing' usesCmd) + ] + where + mkCmd (n,a,c) = Command { cmdName = n + , cmdAction = a + , cmdHidden = False + , cmdCompletionFunc = c + } + + mkCmdHidden (n,a) = Command { cmdName = n + , cmdAction = a + , cmdHidden = True + , cmdCompletionFunc = noCompletion + } + +-- We initialize readline (in the interactiveUI function) to use +-- word_break_chars as the default set of completion word break characters. +-- This can be overridden for a particular command (for example, filename +-- expansion shouldn't consider '/' to be a word break) by setting the third +-- entry in the Command tuple above. +-- +-- NOTE: in order for us to override the default correctly, any custom entry +-- must be a SUBSET of word_break_chars. +word_break_chars :: String +word_break_chars = spaces ++ specials ++ symbols + +word_break_chars_pred :: Char -> Bool +word_break_chars_pred '.' = False +word_break_chars_pred c = c `elem` (spaces ++ specials) || isSymbolChar c + +symbols, specials, spaces :: String +symbols = "!#$%&*+/<=>?@\\^|-~" +specials = "(),;[]`{}" +spaces = " \t\n" + +flagWordBreakChars :: String +flagWordBreakChars = " \t\n" + + +showSDocForUser' :: GHC.GhcMonad m => SDoc -> m String +showSDocForUser' doc = do + dflags <- getDynFlags + unit_state <- hsc_units <$> GHC.getSession + name_ppr_ctx <- GHC.getNamePprCtx + pure $ showSDocForUser dflags unit_state name_ppr_ctx doc + +showSDocForUserQualify :: GHC.GhcMonad m => SDoc -> m String +showSDocForUserQualify doc = do + dflags <- getDynFlags + unit_state <- hsc_units <$> GHC.getSession + pure $ showSDocForUser dflags unit_state alwaysQualify doc + + +keepGoing :: (String -> GHCi ()) -> (String -> InputT GHCi CmdExecOutcome) +keepGoing a str = keepGoing' (lift . a) str + +keepGoing' :: GhciMonad m => (a -> m ()) -> a -> m CmdExecOutcome +keepGoing' a str = do + a str + return CmdSuccess + +keepGoingPaths :: ([FilePath] -> InputT GHCi ()) -> (String -> InputT GHCi CmdExecOutcome) +keepGoingPaths a str + = do case toArgsNoLoc str of + Left err -> reportError (GhciInvalidArgumentString err) >> return CmdSuccess + Right args -> keepGoing' a args + +defFullHelpText :: String +defFullHelpText = + " Commands available from the prompt:\n" ++ + "\n" ++ + " evaluate/run \n" ++ + " : repeat last command\n" ++ + " :{\\n ..lines.. \\n:}\\n multiline command\n" ++ + " :add [*] ... add module(s) to the current target set\n" ++ + " :browse[!] [[*]] display the names defined by module \n" ++ + " (!: more details; *: all top-level names)\n" ++ + " :cd change directory to \n" ++ + " :cmd run the commands returned by ::IO String\n" ++ + " :complete [] list completions for partial input string\n" ++ + " :def[!] define command : (later defined command has\n" ++ + " precedence, :: is always a builtin command)\n" ++ + " (!: redefine an existing command name)\n" ++ + " :doc display docs for the given name (experimental)\n" ++ + " :edit edit file\n" ++ + " :edit edit last module\n" ++ + " :help, :? display this list of commands\n" ++ + " :info[!] [ ...] display information about the given names\n" ++ + " (!: do not filter instances)\n" ++ + " :instances display the class instances available for \n" ++ + " :issafe [] display safe haskell information of module \n" ++ + " :kind[!] show the kind of \n" ++ + " (!: also print the normalised type)\n" ++ + " :load[!] [*] ... load module(s) and their dependents\n" ++ + " (!: defer type errors)\n" ++ + " :main [ ...] run the main function with the given arguments\n" ++ + " :module [+/-] [*] ... set the context for expression evaluation\n" ++ + " :quit exit GHCi\n" ++ + " :reload[!] reload the current module set\n" ++ + " (!: defer type errors)\n" ++ + " :run function [ ...] run the function with the given arguments\n" ++ + " :script run the script \n" ++ + " :type show the type of \n" ++ + " :type +d show the type of , defaulting type variables\n" ++ + " :unadd ... remove module(s) from the current target set\n" ++ + " :undef undefine user-defined command :\n" ++ + " :: run the builtin command\n" ++ + " :! run the shell command \n" ++ + " :vhdl synthesize currently loaded module to vhdl\n" ++ + " :vhdl [] synthesize specified modules/files to vhdl\n" ++ + " :verilog synthesize currently loaded module to verilog\n" ++ + " :verilog [] synthesize specified modules/files to verilog\n" ++ + " :systemverilog synthesize currently loaded module to systemverilog\n" ++ + " :systemverilog [] synthesize specified modules/files to systemverilog\n" ++ + "\n" ++ + " -- Commands for debugging:\n" ++ + "\n" ++ + " :abandon at a breakpoint, abandon current computation\n" ++ + " :back [] go back in the history N steps (after :trace)\n" ++ + " :break [] [] set a breakpoint at the specified location\n" ++ + " :break set a breakpoint on the specified function\n" ++ + " :continue [] resume after a breakpoint [and set break ignore count]\n" ++ + " :delete ... delete the specified breakpoints\n" ++ + " :delete * delete all breakpoints\n" ++ + " :disable ... disable the specified breakpoints\n" ++ + " :disable * disable all breakpoints\n" ++ + " :enable ... enable the specified breakpoints\n" ++ + " :enable * enable all breakpoints\n" ++ + " :force print , forcing unevaluated parts\n" ++ + " :forward [] go forward in the history N step s(after :back)\n" ++ + " :history [] after :trace, show the execution history\n" ++ + " :ignore for break set break ignore \n" ++ + " :list show the source code around current breakpoint\n" ++ + " :list show the source code for \n" ++ + " :list [] show the source code around line number \n" ++ + " :print [ ...] show a value without forcing its computation\n" ++ + " :sprint [ ...] simplified version of :print\n" ++ + " :step single-step after stopping at a breakpoint\n"++ + " :step single-step into \n"++ + " :steplocal single-step within the current top-level binding\n"++ + " :stepout stop at the first breakpoint after returning from the current scope\n"++ + " :stepmodule single-step restricted to the current module\n"++ + " :trace trace after stopping at a breakpoint\n"++ + " :trace evaluate with tracing on (see :history)\n"++ + + "\n" ++ + " -- Commands for changing settings:\n" ++ + "\n" ++ + " :set