From cb07385b3052b6307991f38013362bb7387a05f4 Mon Sep 17 00:00:00 2001 From: Wolfgang Jeltsch Date: Mon, 14 Apr 2025 20:03:33 +0300 Subject: [PATCH 01/12] Add script for finding missing `IO` specializations --- scripts/find-missing-io-specialisations.sh | 91 +++++++++++++++++++ .../Animals.Sheep.hs | 44 +++++++++ .../Misc.hs | 26 ++++++ .../output | 6 ++ 4 files changed, 167 insertions(+) create mode 100755 scripts/find-missing-io-specialisations.sh create mode 100644 scripts/find-missing-io-specialisations.tests/Animals.Sheep.hs create mode 100644 scripts/find-missing-io-specialisations.tests/Misc.hs create mode 100644 scripts/find-missing-io-specialisations.tests/output diff --git a/scripts/find-missing-io-specialisations.sh b/scripts/find-missing-io-specialisations.sh new file mode 100755 index 000000000..cd94c9d82 --- /dev/null +++ b/scripts/find-missing-io-specialisations.sh @@ -0,0 +1,91 @@ +#! /usr/bin/env sh + +# Usage notes: +# +# * The arguments to this utility specify the files to check. If no +# arguments are given, standard input is checked. A typical usage of +# this utility is with the `**` glob wildcard, supported in +# particular by the Z Shell and by Bash with the `extglob` option +# set. For example, the following command will check all Haskell +# source files of the main library: +# +# scripts/find-missing-io-specialisations.sh src/**/*.hs +# +# * The results of this utility are not reliable, but should generally +# be correct for “reasonably styled” code. One important restriction +# is that, in order to be considered in need of having an `IO` +# specialisation, an operation must have an application of a type +# variable named `m` as its result type. +# +# Implementation notes: +# +# * The `sed` script that essentially performs all the work uses the +# hold space to hold the name of the current module and the name of +# the operation to which the most recently found `IO` specialisation +# refers. These two names are stored with a space between them. The +# strings before and after the space can also be empty: +# +# - The string before the space is empty when the module name is +# not given on the same line as the `module` keyword. This +# causes the module name to not appear in the output but +# otherwise does not have any drawback. +# +# - The string after the space is empty when no `IO` +# specialisation has been found yet in the current module or the +# most recently found `IO` specialisation is considered to not +# be relevant for the remainder of the module. + +hic='[[:alnum:]_#]' # Haskell identifier character + +LC_COLLATE=C LC_CTYPE=C sed -En ' + :start + /^module / { + s/module +([^ ]*).*/\1 / + h + } + /^\{-# *SPECIALI[SZ]E( |$)/ { + x + s/ .*// + x + :spec-add + H + /#-\}/ !{ + n + b spec-add + } + g + s/.*(::|=>|->)( |\n)*// + /^IO / !{ + g + s/\n.*/ / + h + d + } + g + s/\{-# *SPECIALI[SZ]E( |\n)+// + s/\n('"$hic"'*).*/ \1/ + h + } + /^[[:lower:]_]/ { + :tsig-add + s/ -- .*// + H + n + /^ / b tsig-add + x + /^[^ ]* '"$hic"'*\n'"$hic"'+( |\n)*::/ { + s/([^ ]* '"$hic"'*\n'"$hic"'+).*(::|=>|->)( |\n)*/\1 / + /^[^ ]* '"$hic"'*\n[^ ]+ m / { + /^[^ ]* ('"$hic"'*)\n\1 / !{ + s/([^ ]*) '"$hic"'*\n([^ ]+).*/\1.\2/p + s/\.[^.]+$/ / + b tsig-fin + } + } + } + s/ .*/ / + :tsig-fin + x + b start + } +' "$@" diff --git a/scripts/find-missing-io-specialisations.tests/Animals.Sheep.hs b/scripts/find-missing-io-specialisations.tests/Animals.Sheep.hs new file mode 100644 index 000000000..94da5f81d --- /dev/null +++ b/scripts/find-missing-io-specialisations.tests/Animals.Sheep.hs @@ -0,0 +1,44 @@ +{- + Pronunciation note: + + The identifiers in this module are somehow considered to be German. They + used to contain the German ä and ö, but since the script only treats English + letters as letters eligible to be part of identifiers, ä and ö were replaced + by their standard alternatives ae and oe. This all should give some + indication regarding how to pronounce the identifiers. The author of this + module thought this note to be necessary, not least to justify the choice of + module name. 😉 +-} +module Animals.Sheep where + +{-# SPECIALISE + boerk + :: + Show a => a -> m () + #-} +boerk :: + (Monad m, Show a) -- ^ The general way of constraining + => a -- ^ A value + -> m a -- ^ An effectful computation +{-# SPECIALISE + schnoerk + :: + Show a => m a + #-} +schnoerk + :: (Monad, m, Show a) -- ^ The general way of constraining + => m a -- ^ An effectful computation + +{-# SPECIALISE + bloek + :: + IO a + #-} +bloek :: + IO a + +maeh :: a -> (b -> IO (a, b)) +maeh = curry return + +moeh :: Monad m => a -> (b -> m (a, b)) +moeh = curry return diff --git a/scripts/find-missing-io-specialisations.tests/Misc.hs b/scripts/find-missing-io-specialisations.tests/Misc.hs new file mode 100644 index 000000000..f44f75077 --- /dev/null +++ b/scripts/find-missing-io-specialisations.tests/Misc.hs @@ -0,0 +1,26 @@ +module Misc +( + conv, + first +) +where + +yield :: Monad m => a -> m a +yield = return + +{-# SPECIALISE first :: [a] -> IO (WeakPtr a) #-} +-- | Get a weak pointer to the first element of a list. +first :: MonadWeak m => [a] -> m (WeakPtr a) +first = _ + +{-# SPECIALISE last :: [a] -> IO (WeakPtr a) #-} +last :: [a] -> IO (WeakPtr a) +last _ = _ + +{-# SPECIALISE conv :: MonadIO m => [a] -> m a #-} +conv :: (Functor f, Monad m) => f a -> m a +conv = id + +{-# SPECIALISE mis :: MonadIO m => [a] -> IO a #-} +match :: (Functor f, Monad m) => f a -> m a +match = id diff --git a/scripts/find-missing-io-specialisations.tests/output b/scripts/find-missing-io-specialisations.tests/output new file mode 100644 index 000000000..2066e283f --- /dev/null +++ b/scripts/find-missing-io-specialisations.tests/output @@ -0,0 +1,6 @@ +Animals.Sheep.boerk +Animals.Sheep.schnoerk +Animals.Sheep.moeh +Misc.yield +Misc.conv +Misc.match From 14ed874c67b04267c53b236cfd2472e227cdd8d2 Mon Sep 17 00:00:00 2001 From: Wolfgang Jeltsch Date: Wed, 16 Apr 2025 17:31:39 +0300 Subject: [PATCH 02/12] Disable reporting of operations with inline directives --- scripts/find-missing-io-specialisations.sh | 35 +++++++++++-------- .../Animals.Sheep.hs | 10 ++++++ 2 files changed, 30 insertions(+), 15 deletions(-) diff --git a/scripts/find-missing-io-specialisations.sh b/scripts/find-missing-io-specialisations.sh index cd94c9d82..a31674ffe 100755 --- a/scripts/find-missing-io-specialisations.sh +++ b/scripts/find-missing-io-specialisations.sh @@ -22,8 +22,9 @@ # * The `sed` script that essentially performs all the work uses the # hold space to hold the name of the current module and the name of # the operation to which the most recently found `IO` specialisation -# refers. These two names are stored with a space between them. The -# strings before and after the space can also be empty: +# or inlining directive refers. These two names are stored with a +# space between them. The strings before and after the space can +# also be empty: # # - The string before the space is empty when the module name is # not given on the same line as the `module` keyword. This @@ -31,10 +32,12 @@ # otherwise does not have any drawback. # # - The string after the space is empty when no `IO` -# specialisation has been found yet in the current module or the -# most recently found `IO` specialisation is considered to not -# be relevant for the remainder of the module. +# specialisation or inlining directive has been found yet in the +# current module or the most recently found such directive is +# considered to not be relevant for the remainder of the module. +specialise='SPECIALI[SZ]E' +pragma_types="($specialise|INLINE)" hic='[[:alnum:]_#]' # Haskell identifier character LC_COLLATE=C LC_CTYPE=C sed -En ' @@ -43,26 +46,28 @@ LC_COLLATE=C LC_CTYPE=C sed -En ' s/module +([^ ]*).*/\1 / h } - /^\{-# *SPECIALI[SZ]E( |$)/ { + /^\{-# *'"$pragma_types"'( |$)/ { x s/ .*// x - :spec-add + :prag-add H /#-\}/ !{ n - b spec-add + b prag-add } g - s/.*(::|=>|->)( |\n)*// - /^IO / !{ + /\{-# *'"$specialise"'( |\n)/ { + s/.*(::|=>|->)( |\n)*// + /^IO / !{ + g + s/\n.*/ / + h + d + } g - s/\n.*/ / - h - d } - g - s/\{-# *SPECIALI[SZ]E( |\n)+// + s/\{-# *'"$pragma_types"'( |\n)+// s/\n('"$hic"'*).*/ \1/ h } diff --git a/scripts/find-missing-io-specialisations.tests/Animals.Sheep.hs b/scripts/find-missing-io-specialisations.tests/Animals.Sheep.hs index 94da5f81d..aa5c4a09b 100644 --- a/scripts/find-missing-io-specialisations.tests/Animals.Sheep.hs +++ b/scripts/find-missing-io-specialisations.tests/Animals.Sheep.hs @@ -37,6 +37,16 @@ schnoerk bloek :: IO a +{-# INLINE baeh +#-} +baeh :: m a -> m a +baeh = id + +{-# INLINE + boo #-} -- maybe too large for inlining +boo :: MonadSheep m => Scissors -> m Wool +boo scissors = withScissors scissors $ \ capability -> cut capability (fur Boo) + maeh :: a -> (b -> IO (a, b)) maeh = curry return From 5ef603e886c2e986f96728e6c95561d0959db2eb Mon Sep 17 00:00:00 2001 From: Wolfgang Jeltsch Date: Wed, 16 Apr 2025 22:39:11 +0300 Subject: [PATCH 03/12] Add comments to the `sed` script --- scripts/find-missing-io-specialisations.sh | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/scripts/find-missing-io-specialisations.sh b/scripts/find-missing-io-specialisations.sh index a31674ffe..e54a845d5 100755 --- a/scripts/find-missing-io-specialisations.sh +++ b/scripts/find-missing-io-specialisations.sh @@ -42,21 +42,27 @@ hic='[[:alnum:]_#]' # Haskell identifier character LC_COLLATE=C LC_CTYPE=C sed -En ' :start + # Process the first line of a module header /^module / { s/module +([^ ]*).*/\1 / h } + # Process a `SPECIALISE` or `INLINE` pragma /^\{-# *'"$pragma_types"'( |$)/ { + # Remove any pragma operation name from the hold space x s/ .*// x + # Add the pragma to the hold space :prag-add H /#-\}/ !{ n b prag-add } + # Get the contents of the hold space g + # Skip a `SPECIALISE` pragma with a non-`IO` result type /\{-# *'"$specialise"'( |\n)/ { s/.*(::|=>|->)( |\n)*// /^IO / !{ @@ -67,20 +73,28 @@ LC_COLLATE=C LC_CTYPE=C sed -En ' } g } + # Store the operation name along with the module name s/\{-# *'"$pragma_types"'( |\n)+// s/\n('"$hic"'*).*/ \1/ h } + # Process a potential type signature /^[[:lower:]_]/ { + # Add the potential type signature to the hold space :tsig-add s/ -- .*// H n /^ / b tsig-add + # Get the persistent data and save the next line x + # Process a type signature /^[^ ]* '"$hic"'*\n'"$hic"'+( |\n)*::/ { + # Place the result type next to the operation name s/([^ ]* '"$hic"'*\n'"$hic"'+).*(::|=>|->)( |\n)*/\1 / + # Handle the case of a monadic result type /^[^ ]* '"$hic"'*\n[^ ]+ m / { + # Handle the case of a missing pragma /^[^ ]* ('"$hic"'*)\n\1 / !{ s/([^ ]*) '"$hic"'*\n([^ ]+).*/\1.\2/p s/\.[^.]+$/ / @@ -88,9 +102,12 @@ LC_COLLATE=C LC_CTYPE=C sed -En ' } } } + # Clean up and forget about the pragma operation name if any s/ .*/ / + # Get the saved next line and store the persistent data :tsig-fin x + # Continue b start } ' "$@" From 829176321a3078215485f3dcb01f5c458df0f9f0 Mon Sep 17 00:00:00 2001 From: Wolfgang Jeltsch Date: Thu, 17 Apr 2025 00:36:50 +0300 Subject: [PATCH 04/12] Disable reporting of operations with unconstrained types --- scripts/find-missing-io-specialisations.sh | 6 +++--- .../find-missing-io-specialisations.tests/Animals.Sheep.hs | 5 ++++- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/scripts/find-missing-io-specialisations.sh b/scripts/find-missing-io-specialisations.sh index e54a845d5..80e0175ab 100755 --- a/scripts/find-missing-io-specialisations.sh +++ b/scripts/find-missing-io-specialisations.sh @@ -88,10 +88,10 @@ LC_COLLATE=C LC_CTYPE=C sed -En ' /^ / b tsig-add # Get the persistent data and save the next line x - # Process a type signature - /^[^ ]* '"$hic"'*\n'"$hic"'+( |\n)*::/ { + # Process a type signature with a context + /^[^ ]* '"$hic"'*\n'"$hic"'+( |\n)*::.+=>/ { # Place the result type next to the operation name - s/([^ ]* '"$hic"'*\n'"$hic"'+).*(::|=>|->)( |\n)*/\1 / + s/([^ ]* '"$hic"'*\n'"$hic"'+).*(=>|->)( |\n)*/\1 / # Handle the case of a monadic result type /^[^ ]* '"$hic"'*\n[^ ]+ m / { # Handle the case of a missing pragma diff --git a/scripts/find-missing-io-specialisations.tests/Animals.Sheep.hs b/scripts/find-missing-io-specialisations.tests/Animals.Sheep.hs index aa5c4a09b..423ccb707 100644 --- a/scripts/find-missing-io-specialisations.tests/Animals.Sheep.hs +++ b/scripts/find-missing-io-specialisations.tests/Animals.Sheep.hs @@ -37,9 +37,12 @@ schnoerk bloek :: IO a +lamb :: m a -> m a +lamb = id + {-# INLINE baeh #-} -baeh :: m a -> m a +baeh :: Monad m => m a -> m a baeh = id {-# INLINE From 279bae772601b840632a3d1ff40309a32e9b72f2 Mon Sep 17 00:00:00 2001 From: Wolfgang Jeltsch Date: Sun, 20 Apr 2025 15:19:35 +0300 Subject: [PATCH 05/12] Add `IO` specialisation linting script --- scripts/io-specialisations/absence-allowed | 0 .../find-absent.sh} | 6 +-- .../find-absent.tests}/Animals.Sheep.hs | 0 .../find-absent.tests}/Misc.hs | 0 .../find-absent.tests}/output | 0 scripts/lint-io-specialisations.sh | 44 +++++++++++++++++++ 6 files changed, 47 insertions(+), 3 deletions(-) create mode 100644 scripts/io-specialisations/absence-allowed rename scripts/{find-missing-io-specialisations.sh => io-specialisations/find-absent.sh} (96%) rename scripts/{find-missing-io-specialisations.tests => io-specialisations/find-absent.tests}/Animals.Sheep.hs (100%) rename scripts/{find-missing-io-specialisations.tests => io-specialisations/find-absent.tests}/Misc.hs (100%) rename scripts/{find-missing-io-specialisations.tests => io-specialisations/find-absent.tests}/output (100%) create mode 100755 scripts/lint-io-specialisations.sh diff --git a/scripts/io-specialisations/absence-allowed b/scripts/io-specialisations/absence-allowed new file mode 100644 index 000000000..e69de29bb diff --git a/scripts/find-missing-io-specialisations.sh b/scripts/io-specialisations/find-absent.sh similarity index 96% rename from scripts/find-missing-io-specialisations.sh rename to scripts/io-specialisations/find-absent.sh index 80e0175ab..6b6fa6f69 100755 --- a/scripts/find-missing-io-specialisations.sh +++ b/scripts/io-specialisations/find-absent.sh @@ -9,7 +9,7 @@ # set. For example, the following command will check all Haskell # source files of the main library: # -# scripts/find-missing-io-specialisations.sh src/**/*.hs +# scripts/io-specialisations/find-absent.sh src/**/*.hs # # * The results of this utility are not reliable, but should generally # be correct for “reasonably styled” code. One important restriction @@ -40,7 +40,7 @@ specialise='SPECIALI[SZ]E' pragma_types="($specialise|INLINE)" hic='[[:alnum:]_#]' # Haskell identifier character -LC_COLLATE=C LC_CTYPE=C sed -En ' +LC_COLLATE=C LC_CTYPE=C sed -En -e ' :start # Process the first line of a module header /^module / { @@ -94,7 +94,7 @@ LC_COLLATE=C LC_CTYPE=C sed -En ' s/([^ ]* '"$hic"'*\n'"$hic"'+).*(=>|->)( |\n)*/\1 / # Handle the case of a monadic result type /^[^ ]* '"$hic"'*\n[^ ]+ m / { - # Handle the case of a missing pragma + # Handle the case of pragma absence /^[^ ]* ('"$hic"'*)\n\1 / !{ s/([^ ]*) '"$hic"'*\n([^ ]+).*/\1.\2/p s/\.[^.]+$/ / diff --git a/scripts/find-missing-io-specialisations.tests/Animals.Sheep.hs b/scripts/io-specialisations/find-absent.tests/Animals.Sheep.hs similarity index 100% rename from scripts/find-missing-io-specialisations.tests/Animals.Sheep.hs rename to scripts/io-specialisations/find-absent.tests/Animals.Sheep.hs diff --git a/scripts/find-missing-io-specialisations.tests/Misc.hs b/scripts/io-specialisations/find-absent.tests/Misc.hs similarity index 100% rename from scripts/find-missing-io-specialisations.tests/Misc.hs rename to scripts/io-specialisations/find-absent.tests/Misc.hs diff --git a/scripts/find-missing-io-specialisations.tests/output b/scripts/io-specialisations/find-absent.tests/output similarity index 100% rename from scripts/find-missing-io-specialisations.tests/output rename to scripts/io-specialisations/find-absent.tests/output diff --git a/scripts/lint-io-specialisations.sh b/scripts/lint-io-specialisations.sh new file mode 100755 index 000000000..4dcbbccdb --- /dev/null +++ b/scripts/lint-io-specialisations.sh @@ -0,0 +1,44 @@ +#! /usr/bin/env sh + +set -e + +IFS=' +' + +absence_allowed_file=scripts/io-specialisations/absence-allowed +absence_finder=scripts/io-specialisations/find-absent.sh + +export LC_COLLATE=C LC_TYPE=C + +printf 'Linting the main library regarding `IO` specialisations\n' + +if ! [ -f "$absence_allowed_file" ] +then + printf 'There is no regular file `%s`.\n' "$absence_allowed_file" + exit 2 +fi >&2 +if ! sort -C "$absence_allowed_file" +then + printf 'The entries in `%s` are not sorted.\n' "$absence_allowed_file" + exit 2 +fi >&2 + +hs_files=$( + git ls-files \ + --exclude-standard --no-deleted --deduplicate \ + 'src/**/*.hs' +) +absent=$( + "$absence_finder" $hs_files +) +missing=$( + printf '%s\n' "$absent" | sort | comm -23 - "$absence_allowed_file" +) +if [ -n "$missing" ] +then + printf '`IO` specialisations for the following operations are ' + printf 'missing:\n' + printf '%s\n' "$missing" | sed -e 's/.*/ * `&`/' + exit 1 +fi +printf 'All required `IO` specialisations are present.\n' From 63d2e4f6404bc945274e6a0d8965ae508ad96a1d Mon Sep 17 00:00:00 2001 From: Wolfgang Jeltsch Date: Sun, 20 Apr 2025 15:30:17 +0300 Subject: [PATCH 06/12] Make linters not consider the `IO` specialisation tests --- .../find-absent.tests/{Animals.Sheep.hs => Animals.Sheep.fake-hs} | 0 .../find-absent.tests/{Misc.hs => Misc.fake-hs} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename scripts/io-specialisations/find-absent.tests/{Animals.Sheep.hs => Animals.Sheep.fake-hs} (100%) rename scripts/io-specialisations/find-absent.tests/{Misc.hs => Misc.fake-hs} (100%) diff --git a/scripts/io-specialisations/find-absent.tests/Animals.Sheep.hs b/scripts/io-specialisations/find-absent.tests/Animals.Sheep.fake-hs similarity index 100% rename from scripts/io-specialisations/find-absent.tests/Animals.Sheep.hs rename to scripts/io-specialisations/find-absent.tests/Animals.Sheep.fake-hs diff --git a/scripts/io-specialisations/find-absent.tests/Misc.hs b/scripts/io-specialisations/find-absent.tests/Misc.fake-hs similarity index 100% rename from scripts/io-specialisations/find-absent.tests/Misc.hs rename to scripts/io-specialisations/find-absent.tests/Misc.fake-hs From 91663ef56060efdc7489b947a7c552b79b797454 Mon Sep 17 00:00:00 2001 From: Wolfgang Jeltsch Date: Sun, 20 Apr 2025 15:36:27 +0300 Subject: [PATCH 07/12] Move the definition of static variables to the top --- scripts/lint-io-specialisations.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/lint-io-specialisations.sh b/scripts/lint-io-specialisations.sh index 4dcbbccdb..186c12be4 100755 --- a/scripts/lint-io-specialisations.sh +++ b/scripts/lint-io-specialisations.sh @@ -1,13 +1,13 @@ #! /usr/bin/env sh +absence_allowed_file=scripts/io-specialisations/absence-allowed +absence_finder=scripts/io-specialisations/find-absent.sh + set -e IFS=' ' -absence_allowed_file=scripts/io-specialisations/absence-allowed -absence_finder=scripts/io-specialisations/find-absent.sh - export LC_COLLATE=C LC_TYPE=C printf 'Linting the main library regarding `IO` specialisations\n' From 099e887e99ad671ed18bbdca535777390d37e5f6 Mon Sep 17 00:00:00 2001 From: Wolfgang Jeltsch Date: Sun, 20 Apr 2025 19:38:30 +0300 Subject: [PATCH 08/12] Add workflow job for `IO` specialisation linting --- .github/workflows/ci.yml | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 77b88aca9..23c0aef5a 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -268,6 +268,19 @@ jobs: - name: 🎗️ Lint with stylish-haskell run: ./scripts/format-stylish-haskell.sh && git diff --exit-code + ################################################################################ + # Lint regarding IO specialisations + ################################################################################ + lint-io-specialisations: + name: Lint regarding IO specialisations + runs-on: ubuntu-latest + steps: + - name: 📥 Checkout repository + uses: actions/checkout@v4 + + - name: 🎗️ Lint regarding IO specialisations + run: ./scripts/lint-io-specialisations.sh + ################################################################################ # Lint with generate-readme ################################################################################ From 7a76e4f418ace0b1674fe8a320660ca152d7592e Mon Sep 17 00:00:00 2001 From: Wolfgang Jeltsch Date: Sun, 20 Apr 2025 20:26:03 +0300 Subject: [PATCH 09/12] Make sure that top-level modules are checked --- scripts/lint-io-specialisations.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/lint-io-specialisations.sh b/scripts/lint-io-specialisations.sh index 186c12be4..c3e2cb70e 100755 --- a/scripts/lint-io-specialisations.sh +++ b/scripts/lint-io-specialisations.sh @@ -26,7 +26,7 @@ fi >&2 hs_files=$( git ls-files \ --exclude-standard --no-deleted --deduplicate \ - 'src/**/*.hs' + 'src/*.hs' 'src/**/*.hs' ) absent=$( "$absence_finder" $hs_files From 72093a1d7cca7e5492c43579d1ef68dfb0671a93 Mon Sep 17 00:00:00 2001 From: Wen Kokke Date: Wed, 30 Apr 2025 11:29:44 +0100 Subject: [PATCH 10/12] fix(lint-io-specialisations): rename folder for better grouping --- scripts/lint-io-specialisations.sh | 4 ++-- .../absence-allowed | 0 .../find-absent.sh | 0 .../find-absent.tests/Animals.Sheep.fake-hs | 0 .../find-absent.tests/Misc.fake-hs | 0 .../find-absent.tests/output | 0 6 files changed, 2 insertions(+), 2 deletions(-) rename scripts/{io-specialisations => lint-io-specialisations}/absence-allowed (100%) rename scripts/{io-specialisations => lint-io-specialisations}/find-absent.sh (100%) rename scripts/{io-specialisations => lint-io-specialisations}/find-absent.tests/Animals.Sheep.fake-hs (100%) rename scripts/{io-specialisations => lint-io-specialisations}/find-absent.tests/Misc.fake-hs (100%) rename scripts/{io-specialisations => lint-io-specialisations}/find-absent.tests/output (100%) diff --git a/scripts/lint-io-specialisations.sh b/scripts/lint-io-specialisations.sh index c3e2cb70e..7a87ba2b0 100755 --- a/scripts/lint-io-specialisations.sh +++ b/scripts/lint-io-specialisations.sh @@ -1,7 +1,7 @@ #! /usr/bin/env sh -absence_allowed_file=scripts/io-specialisations/absence-allowed -absence_finder=scripts/io-specialisations/find-absent.sh +absence_allowed_file=scripts/lint-io-specialisations/absence-allowed +absence_finder=scripts/lint-io-specialisations/find-absent.sh set -e diff --git a/scripts/io-specialisations/absence-allowed b/scripts/lint-io-specialisations/absence-allowed similarity index 100% rename from scripts/io-specialisations/absence-allowed rename to scripts/lint-io-specialisations/absence-allowed diff --git a/scripts/io-specialisations/find-absent.sh b/scripts/lint-io-specialisations/find-absent.sh similarity index 100% rename from scripts/io-specialisations/find-absent.sh rename to scripts/lint-io-specialisations/find-absent.sh diff --git a/scripts/io-specialisations/find-absent.tests/Animals.Sheep.fake-hs b/scripts/lint-io-specialisations/find-absent.tests/Animals.Sheep.fake-hs similarity index 100% rename from scripts/io-specialisations/find-absent.tests/Animals.Sheep.fake-hs rename to scripts/lint-io-specialisations/find-absent.tests/Animals.Sheep.fake-hs diff --git a/scripts/io-specialisations/find-absent.tests/Misc.fake-hs b/scripts/lint-io-specialisations/find-absent.tests/Misc.fake-hs similarity index 100% rename from scripts/io-specialisations/find-absent.tests/Misc.fake-hs rename to scripts/lint-io-specialisations/find-absent.tests/Misc.fake-hs diff --git a/scripts/io-specialisations/find-absent.tests/output b/scripts/lint-io-specialisations/find-absent.tests/output similarity index 100% rename from scripts/io-specialisations/find-absent.tests/output rename to scripts/lint-io-specialisations/find-absent.tests/output From 5d6c2cebbf4bfa1fbd545907d1ab43197d97997e Mon Sep 17 00:00:00 2001 From: Wen Kokke Date: Wed, 30 Apr 2025 11:57:18 +0100 Subject: [PATCH 11/12] fix(lint-io-specialisations): use gsed on macOS and more thoroughly propagate exit failure --- scripts/lint-io-specialisations.sh | 20 +++++++--------- .../lint-io-specialisations/find-absent.sh | 24 +++++++++++++++++-- 2 files changed, 31 insertions(+), 13 deletions(-) diff --git a/scripts/lint-io-specialisations.sh b/scripts/lint-io-specialisations.sh index 7a87ba2b0..74d9d4226 100755 --- a/scripts/lint-io-specialisations.sh +++ b/scripts/lint-io-specialisations.sh @@ -1,16 +1,15 @@ -#! /usr/bin/env sh +#!/bin/sh -absence_allowed_file=scripts/lint-io-specialisations/absence-allowed -absence_finder=scripts/lint-io-specialisations/find-absent.sh - -set -e +SCRIPTS_DIR="$(CDPATH= cd -- "$(dirname -- "$0")" && pwd -P)" +absence_allowed_file="${SCRIPTS_DIR}/lint-io-specialisations/absence-allowed" +absence_finder="${SCRIPTS_DIR}/lint-io-specialisations/find-absent.sh" IFS=' ' export LC_COLLATE=C LC_TYPE=C -printf 'Linting the main library regarding `IO` specialisations\n' +printf 'Linting the main library for missing `IO` specialisations\n' if ! [ -f "$absence_allowed_file" ] then @@ -27,17 +26,16 @@ hs_files=$( git ls-files \ --exclude-standard --no-deleted --deduplicate \ 'src/*.hs' 'src/**/*.hs' -) +) || exit 3 absent=$( "$absence_finder" $hs_files -) +) || exit 3 missing=$( printf '%s\n' "$absent" | sort | comm -23 - "$absence_allowed_file" -) +) || exit 3 if [ -n "$missing" ] then - printf '`IO` specialisations for the following operations are ' - printf 'missing:\n' + printf '`IO` specialisations for the following operations are missing:\n' printf '%s\n' "$missing" | sed -e 's/.*/ * `&`/' exit 1 fi diff --git a/scripts/lint-io-specialisations/find-absent.sh b/scripts/lint-io-specialisations/find-absent.sh index 6b6fa6f69..0df6b2f82 100755 --- a/scripts/lint-io-specialisations/find-absent.sh +++ b/scripts/lint-io-specialisations/find-absent.sh @@ -1,4 +1,4 @@ -#! /usr/bin/env sh +#!/bin/sh # Usage notes: # @@ -36,11 +36,31 @@ # current module or the most recently found such directive is # considered to not be relevant for the remainder of the module. +# Find sed: +case "$(uname)" in + Darwin) + sed="$(which gsed)" + if [ "${sed}" = "" ]; then + printf 'This script requires GNU sed, which can be installed with Homebrew:\n\n' >&2 + printf ' brew install gsed\n\n' >&2 + exit 1 + fi + ;; + *) + sed="$(which sed)" + ;; +esac + +sed=$(which gsed) +if [ "${sed}" = "" ]; then + sed=$(which sed) +fi + specialise='SPECIALI[SZ]E' pragma_types="($specialise|INLINE)" hic='[[:alnum:]_#]' # Haskell identifier character -LC_COLLATE=C LC_CTYPE=C sed -En -e ' +LC_COLLATE=C LC_CTYPE=C $sed -En -e ' :start # Process the first line of a module header /^module / { From eaf6c20a7c632483cda12e001c93e0e064556e0f Mon Sep 17 00:00:00 2001 From: Wen Kokke Date: Wed, 30 Apr 2025 12:00:45 +0100 Subject: [PATCH 12/12] fix(lint-io-specialisations): more specific job names --- .github/workflows/ci.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 23c0aef5a..3cc22a78b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -269,16 +269,16 @@ jobs: run: ./scripts/format-stylish-haskell.sh && git diff --exit-code ################################################################################ - # Lint regarding IO specialisations + # Lint for missing IO specialisations ################################################################################ lint-io-specialisations: - name: Lint regarding IO specialisations + name: Lint for missing IO specialisations runs-on: ubuntu-latest steps: - name: 📥 Checkout repository uses: actions/checkout@v4 - - name: 🎗️ Lint regarding IO specialisations + - name: 🎗️ Lint for missing IO specialisations run: ./scripts/lint-io-specialisations.sh ################################################################################