Skip to content

Comments

Add hexadecimal literals for 'Byte'#1170

Merged
phischu merged 18 commits intomainfrom
feat-byte-hex-notation
Feb 3, 2026
Merged

Add hexadecimal literals for 'Byte'#1170
phischu merged 18 commits intomainfrom
feat-byte-hex-notation

Conversation

@jiribenes
Copy link
Contributor

@jiribenes jiribenes commented Oct 30, 2025

Originally by @PhictionalOne, started in #1148 (was on a repo fork).

Resolves #814 by adding hexadecimal literals for bytes: 0xAA, 0x00, 0xFF, 0xA0, etc, exclusively of type Byte.

Comment on lines 137 to 140
val unsigned: Int = b.toInt.bitwiseAnd(0xFF.toInt)

val high = unsigned.bitwiseShr(4).bitwiseAnd(0xFF.toInt)
val low = unsigned.bitwiseAnd(0x0F.toInt)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

It would be nice to have bitwise operators on Bytes

Copy link
Contributor Author

Choose a reason for hiding this comment

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

... and equality and stuff :)

@jiribenes jiribenes force-pushed the feat-byte-hex-notation branch from b959d97 to 5f45e95 Compare November 14, 2025 20:17
@jiribenes jiribenes force-pushed the feat-byte-hex-notation branch from 3cf2587 to 29e26d6 Compare December 17, 2025 13:41
case Literal((), _) => "()"
case Literal(n, Type.TInt) => n.toString
case Literal(n, Type.TChar) => s"'\\${n.toString}'"
case Literal(b: Byte, Type.TByte) => UByte.unsafeFromByte(b).toHexString
Copy link
Contributor Author

@jiribenes jiribenes Dec 17, 2025

Choose a reason for hiding this comment

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

This might be a bit confusing, but we can't match on a UByte as it's opaque, so we have to match on a Byte, just to zero-cost convert it to a Byte, just to print the hexString consistently.
... I really don't know how to do this better without either wrapping it in a custom type and dealing with the overhead, or pulling a newtype library :/

Copy link
Collaborator

Choose a reason for hiding this comment

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

It's ok. You could have toHexString operate directly on Byte and use toUnsignedInt everywhere.

@jiribenes jiribenes requested a review from phischu December 18, 2025 15:18
case Literal((), _) => "()"
case Literal(n, Type.TInt) => n.toString
case Literal(n, Type.TChar) => s"'\\${n.toString}'"
case Literal(b: Byte, Type.TByte) => UByte.unsafeFromByte(b).toHexString
Copy link
Collaborator

Choose a reason for hiding this comment

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

It's ok. You could have toHexString operate directly on Byte and use toUnsignedInt everywhere.

Comment on lines +484 to +486
val b = UByte.unsafeFromByte(value)
// TODO: Literal bytes could now also be just byte-sized in Machine (= use 'UByte'; they are byte-sized in LLVM anyway).
LiteralByte(unboxed, b.toInt, Coerce(variable, unboxed, k(variable)))
Copy link
Collaborator

Choose a reason for hiding this comment

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

I would prefer toUnsignedInt here instead of the newtype wrapping, but ok.

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 biggest issue I have with toUnsignedInt is that you need to remember to use that whenever you see a Byte, which felt like a footgun (that I stumbled into like three times when making this PR in the first place).
The alternative is weird since we can't match on UByte as a type, so it's all quite unsatisfactory :/

Comment on lines +15 to +21
do emit(0x28)
repeat(n) {
do emit(40.toByte)
do emit(41.toByte)
do emit(0x28)
do emit(0x29)
}
emitTree(n - 1)
do emit(41.toByte)
do emit(0x29)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Beautiful!

@jiribenes
Copy link
Contributor Author

One more thing that would sometimes be useful is byte character literals (without the need to convert them).
But we could also just build that into the normaliser as when c is charLiteral, rewrite c.toByte to <lowest byte of c>.

@phischu phischu merged commit 06d6dee into main Feb 3, 2026
8 checks passed
@phischu phischu deleted the feat-byte-hex-notation branch February 3, 2026 15:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add hexadecimal literals for Byte

4 participants