Skip to content

Add hexadecimal integer literals (e.g. 0xFF) - #132

Open
gdisirio wants to merge 1 commit into
apache:2.3-gaefrom
gdisirio:feature/hex-integer-literals
Open

Add hexadecimal integer literals (e.g. 0xFF)#132
gdisirio wants to merge 1 commit into
apache:2.3-gaefrom
gdisirio:feature/hex-integer-literals

Conversation

@gdisirio

Copy link
Copy Markdown

Whole numbers can now be written in hexadecimal notation, using an 0x (or 0X) prefix followed by hex digits — 0xFF is 255, 0x100 is 256.

This has come up on the mailing list several times over the years; the usual workaround has been exposing Integer.decode as a shared variable. It's most useful when templates deal with values that are conventionally written in hex — bitmasks, hardware register values, colour constants, binary protocol fields — where decimal spellings obscure the intent.

Backward compatibility

Purely additive. In an expression, a sequence like 0xFF was previously a parse error (a number immediately followed by an identifier), so no currently-valid template can change meaning. The new HEX_INTEGER token is only active in the expression lexer states, never in plain template text.

Range and representation

Hex literals specify whole numbers only — no fractional part, no exponent, no sign. A sign can still be applied as a separate operator, as in -0x10.

Values are narrowed to the smallest of Integer / Long that fits, and beyond Long range they become BigInteger, so there is no arbitrary limit on the number of digits and no overflow error.

One consequence worth flagging explicitly: this means hex literals do not go through ArithmeticEngine.toNumber, so under the default BIGDECIMAL_ENGINE the literal 255 yields a BigDecimal while 0xFF yields an Integer. The two compare and arithmetically behave identically, but they are different Java types, which is observable if the value is passed to an overloaded Java method. I went this way because hex notation is inherently integral and Integer/Long is what callers doing mask arithmetic expect — but if you'd rather hex respect the configured arithmetic engine for consistency, that's a small change and I'm happy to make it.

Testing & docs

  • JUnit coverage in HexLiteralTest: basic values, both prefix cases, use in expressions, assignment, comparison, and the Integer/Long/BigInteger boundaries.
  • Manual entry in the "Direct specification of values" section, marked @since 2.3.35.
  • ./gradlew check and ./gradlew manualOffline both pass.

Relationship to #130

Independent of #130 — the two share no code. This changes only the lexer/parser (FTL.jj); #130 changes only the string built-ins (BuiltIn.java, BuiltInsForStringsBasic.java). The one file both touch is book.xml, and the hunks are about 10,000 lines apart (the expressions chapter vs. the built-ins reference). They merge cleanly in either order, so no coordination is needed.

Whole numbers can now be written in hexadecimal notation, using the
0x (or 0X) prefix followed by hex digits, e.g. 0xFF for 255. This has
been requested on the mailing list several times over the years (the
previous workaround being to expose Integer.decode as a shared
variable).

The change is purely additive and backward compatible: in an
expression, a sequence like "0xFF" was previously a parse error (a
number immediately followed by an identifier), so no currently-valid
template can be affected. The new HEX_INTEGER token is only active in
the expression lexer states, never in plain template text.

Hex literals specify whole numbers only; the sign can be applied as a
separate operator (e.g. -0x10). There's no limit on the number of
digits: the value is narrowed to an Integer if it fits into a 32-bit
signed integer, to a Long if it fits into a 64-bit signed integer, and
is kept as a BigInteger otherwise.

Added JUnit coverage and a note in the Manual's "Direct specification
of values" section (with @SInCE 2.3.35).
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.

1 participant