Skip to content

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 163
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.

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!

char str[4]; // Byte values range from 0 to 255, 3 characters + null terminator
snprintf(str, sizeof(str), "%" PRIu8, n);
char str[5]; // |"0x" ++ <2 hex digits> ++ '\0'| = 5
snprintf(str, sizeof str, "0x%02" PRIX8, (uint8_t)n);
Copy link
Collaborator

Choose a reason for hiding this comment

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

Shouldn't n already be of type uint8_t? We have typedef uint8_t Byte;. Or is this best practice in C?

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