Skip to content

Conversation

vdukhovni
Copy link
Contributor

thLiteral    :: Quote m => String -> Code m ByteString
thHexLiteral :: Quote m => String -> Code m ByteString

The former rejects inputs with non-octet code points above 0xFF. The latter rejects odd-length inputs or inputs with characters other than non-hexadecimal digits.

@vdukhovni vdukhovni force-pushed the th-splices branch 2 times, most recently from 70f1a6a to b53c921 Compare August 16, 2025 08:26
@vdukhovni
Copy link
Contributor Author

@Bodigrim I don't understand what's going on with CI. Any help appreciated.

@Bodigrim
Copy link
Contributor

@vdukhovni no idea tbh. Maybe something changed under the hood, either in runner images or in the haskell action.

@vdukhovni
Copy link
Contributor Author

I have very little experience tuning GitHub CI. Any chance someone can help?

@Bodigrim
Copy link
Contributor

It seems it was an intermittent failure with https://github.com/haskell-actions/setup. I don't think you need to touch CI setup in this PR.

@vdukhovni
Copy link
Contributor Author

Thanks, indeed most of the problems appear to have been transient. I reverted the CI changes, and the only failure so far is with OpenBSD, which reports:
⚠️ Not enough compute credits to prioritize tasks!

Otherwise, no issues. So I think I'm done, unless you'd prefer to name the two functions differently. The names thLiteral and thHexLiteral were a best effort choice at the time, but one can probably make a case for other choices if these don't appeal.

@vdukhovni
Copy link
Contributor Author

Review request: @hsyl20 @Bodigrim @clyring

Copy link
Contributor

@hsyl20 hsyl20 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

I would prefer more explicit names: something like literalFromAscii (or literalFromChar8) and literalFromHex

@vdukhovni
Copy link
Contributor Author

LGTM

I would prefer more explicit names: something like literalFromAscii (or literalFromChar8) and literalFromHex

Many thanks for the prompt review! I'm about to push a fixup for all the nits, and what remains then is to reach consensus on the splice names. Of the above I prefer literalFromChar8 over literalFromAscii and have no objections to literalFromHex. I take it you don't see any benefit from including a th prefix to make it clear these are splices rather than directly usable functions?

@hsyl20
Copy link
Contributor

hsyl20 commented Aug 21, 2025

I take it you don't see any benefit from including a th prefix to make it clear these are splices rather than directly usable functions?

Yes the type and literal already convey that imo.

@vdukhovni vdukhovni force-pushed the th-splices branch 2 times, most recently from c5906d9 to 28a0cb6 Compare August 21, 2025 14:09
@vdukhovni vdukhovni force-pushed the th-splices branch 2 times, most recently from 83cf073 to 2f5671a Compare August 23, 2025 03:11
@Bodigrim Bodigrim requested a review from clyring August 24, 2025 10:28
@vdukhovni
Copy link
Contributor Author

@hsyl20, @Bodigrim Many thanks for the reviews, much appreciated. If at some point you find some more review cycles, I've revived, rebased and improved #569, so reviews there would also be great.

@vdukhovni
Copy link
Contributor Author

@hsyl20 @clyring @Bodigrim I believe this is done. Please let me know if anything is missing.

import Data.Bits ((.&.))
import Data.Bits ((.|.), (.&.), complement, shiftL)
import Data.Char (ord)
import Data.Foldable (foldr')
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The unqualified foldr' briefly confused me. (Actually, why are these quote-generators defined in D.B.Internal.Type instead of the exposed Data.ByteString?)

-- > ehloCmd :: ByteString
-- > ehloCmd = $$(literalFromChar8 "EHLO")
--
literalFromChar8 :: String -> THLift ByteString
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I respect the idea of using a type synonym here, but (with recent GHCs) it expands to a higher-rank type, which is different from the type we would otherwise have given it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The alternative to just repeat the whole function with a different type signature, or use CPP.
Is that necessary? I've not run into any issues with using the splice in GHC 9.12. Is there a problem with 9.14?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Take a look at how template-haskell-lift shims around this: https://gitlab.haskell.org/ghc/template-haskell-lift/-/blob/main/src/Language/Haskell/TH/Lift.hs?ref_type=heads#L40

It's currently unreleased, but I'll try to publish this library in the next few weeks.

It means we can just write Qoute m => ... -> Code m a and it will turn into the correct thing for all versions of GHC without higher-rank types, etc.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've adopted that approach.

literalFromChar8 "" = [||empty||]
literalFromChar8 s = case foldr' op (Octets 0 []) s of
Octets n ws -> liftTyped (unsafePackLenBytes n ws)
Hichar i w -> liftCode $ fail $ "non-octet character '\\" ++
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@TeofilC Would this liftCode $ fail $ ... stuff require any adjustments to your template-haskell-lift plans?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the headsup. This should be fine.

op :: Char -> S2W -> S2W
op (fromIntegral . fromEnum -> !(w :: Word)) acc
| w <= 0xff = case acc of
Octets i ws -> Octets (i + 1) (fromIntegral w : ws)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(i+1) can overflow.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That would require that the input string length be greater than maxBound @Int, and the consequence is just an incorrect report of the problem offset. I suspect this does not warrant work-arounds.

    thLiteral    :: Quote m => String -> Code m ByteString
    thHexLiteral :: Quote m => String -> Code m ByteString

The former rejects inputs with non-octet code points above 0xFF.
The latter rejects odd-length inputs or inputs with characters
other than non-hexadecimal digits.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants