From 1770af43dcf834f4aa739df9c8b2702a29b176c5 Mon Sep 17 00:00:00 2001 From: Wolfgang Jeltsch Date: Mon, 14 Apr 2025 20:03:33 +0300 Subject: [PATCH 01/14] 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 897232f02ce61ee2f66b45232daa8d83d5092175 Mon Sep 17 00:00:00 2001 From: Wolfgang Jeltsch Date: Wed, 16 Apr 2025 17:31:39 +0300 Subject: [PATCH 02/14] 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 700173d26b2c9319cebb437471a07a468ed18fb5 Mon Sep 17 00:00:00 2001 From: Wolfgang Jeltsch Date: Wed, 16 Apr 2025 22:39:11 +0300 Subject: [PATCH 03/14] 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 f37213fd128162ea3a732eccc511afaa3534130f Mon Sep 17 00:00:00 2001 From: Wolfgang Jeltsch Date: Thu, 17 Apr 2025 00:36:50 +0300 Subject: [PATCH 04/14] 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 e65b58173642c2e6a7eaa8392842af5f7d33ae56 Mon Sep 17 00:00:00 2001 From: Wolfgang Jeltsch Date: Sun, 20 Apr 2025 15:19:35 +0300 Subject: [PATCH 05/14] 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 4e022e5120c078e0c4ec1e1fd1435975ee3b1aba Mon Sep 17 00:00:00 2001 From: Wolfgang Jeltsch Date: Sun, 20 Apr 2025 15:30:17 +0300 Subject: [PATCH 06/14] 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 02acfcf229107c1e2c9e30dfaa5d68c2ac4e0bd7 Mon Sep 17 00:00:00 2001 From: Wolfgang Jeltsch Date: Sun, 20 Apr 2025 15:36:27 +0300 Subject: [PATCH 07/14] 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 1649bedea888e85735b37ef8c2312e071eeacbc9 Mon Sep 17 00:00:00 2001 From: Wolfgang Jeltsch Date: Sun, 20 Apr 2025 19:38:30 +0300 Subject: [PATCH 08/14] 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 470f1bea0..15583f226 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 174e47ec1b02f6c53ea4219f5874eea8d6296783 Mon Sep 17 00:00:00 2001 From: Wolfgang Jeltsch Date: Sun, 20 Apr 2025 20:26:03 +0300 Subject: [PATCH 09/14] 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 7a77b4a548e91af627ecce7be9e8261f069aa6e1 Mon Sep 17 00:00:00 2001 From: Wolfgang Jeltsch Date: Mon, 12 May 2025 21:05:18 +0300 Subject: [PATCH 10/14] Clarify the description of the linting task --- .github/workflows/ci.yml | 6 +++--- scripts/lint-io-specialisations.sh | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 15583f226..99c42eda4 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 ################################################################################ diff --git a/scripts/lint-io-specialisations.sh b/scripts/lint-io-specialisations.sh index c3e2cb70e..d7bdc9f86 100755 --- a/scripts/lint-io-specialisations.sh +++ b/scripts/lint-io-specialisations.sh @@ -10,7 +10,7 @@ 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 From dc68c59ef45b4fed60074a13071c2a448c47ef45 Mon Sep 17 00:00:00 2001 From: Wolfgang Jeltsch Date: Mon, 12 May 2025 22:05:02 +0300 Subject: [PATCH 11/14] Make `find-absent.sh` insist on using GNU sed --- scripts/io-specialisations/find-absent.sh | 27 ++++++++++++++++++++++- 1 file changed, 26 insertions(+), 1 deletion(-) diff --git a/scripts/io-specialisations/find-absent.sh b/scripts/io-specialisations/find-absent.sh index 6b6fa6f69..50d12b725 100755 --- a/scripts/io-specialisations/find-absent.sh +++ b/scripts/io-specialisations/find-absent.sh @@ -17,6 +17,12 @@ # specialisation, an operation must have an application of a type # variable named `m` as its result type. # +# * This utility requires GNU sed. If there is a command `gsed` +# available, then this utility will consider it to be GNU sed and +# use it. If there is no command `gsed` available but the operating +# system is Linux, then this utility will assume that `sed` is GNU +# sed and use it. In all other cases, this utility will fail. +# # Implementation notes: # # * The `sed` script that essentially performs all the work uses the @@ -35,12 +41,31 @@ # 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. +# +# * This utility requires GNU sed because it uses a backreference in a +# regular expression, something that the POSIX standard does not +# guarantee to work. + +set -e + +export LC_COLLATE=C LC_CTYPE=C + +if command -v gsed >/dev/null +then + gnu_sed=gsed +elif [ $(uname) = Linux ] +then + gnu_sed=sed +else + printf 'GNU sed not found\n' >&2 + exit 1 +fi specialise='SPECIALI[SZ]E' pragma_types="($specialise|INLINE)" hic='[[:alnum:]_#]' # Haskell identifier character -LC_COLLATE=C LC_CTYPE=C sed -En -e ' +$gnu_sed -En -e ' :start # Process the first line of a module header /^module / { From eaa1c9429664af663fdb25d59f12682464b6fb85 Mon Sep 17 00:00:00 2001 From: Wolfgang Jeltsch Date: Wed, 14 May 2025 18:30:24 +0300 Subject: [PATCH 12/14] Rename `io-specialisations` to `lint-io-specialisations` --- 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 d7bdc9f86..e158299c6 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 cecde9498e32618855c748a4d16c3726d45f7763 Mon Sep 17 00:00:00 2001 From: Wolfgang Jeltsch Date: Tue, 20 May 2025 16:56:55 +0300 Subject: [PATCH 13/14] Add missing `IO` specialization for `hGetByteArrayExactly` --- src/Database/LSMTree/Internal/BloomFilter.hs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/Database/LSMTree/Internal/BloomFilter.hs b/src/Database/LSMTree/Internal/BloomFilter.hs index bdad12d4d..8721a8228 100644 --- a/src/Database/LSMTree/Internal/BloomFilter.hs +++ b/src/Database/LSMTree/Internal/BloomFilter.hs @@ -296,6 +296,11 @@ bloomFilterFromFile hfs h = do ErrFileFormatInvalid (fsErrorPath e) FormatBloomFilterFile msg) +{-# SPECIALISE hGetByteArrayExactly :: + HasFS IO h + -> Handle h + -> Int + -> IO P.ByteArray #-} hGetByteArrayExactly :: (PrimMonad m, MonadThrow m) => HasFS m h From a5f12f91bca754f2400fb5f9e58db1290290decb Mon Sep 17 00:00:00 2001 From: Wolfgang Jeltsch Date: Tue, 27 May 2025 15:59:09 +0300 Subject: [PATCH 14/14] Correct the stated reason for the use of GNU sed --- scripts/lint-io-specialisations/find-absent.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/lint-io-specialisations/find-absent.sh b/scripts/lint-io-specialisations/find-absent.sh index 50d12b725..4d45c2139 100755 --- a/scripts/lint-io-specialisations/find-absent.sh +++ b/scripts/lint-io-specialisations/find-absent.sh @@ -42,9 +42,9 @@ # current module or the most recently found such directive is # considered to not be relevant for the remainder of the module. # -# * This utility requires GNU sed because it uses a backreference in a -# regular expression, something that the POSIX standard does not -# guarantee to work. +# * This utility requires GNU sed because it uses a backreference in +# an extended regular expression, something that the POSIX standard +# does not guarantee to work. set -e