Skip to content

Commit

Permalink
SIP 42 Binary literals finds acceptance (#10656)
Browse files Browse the repository at this point in the history
undefined
  • Loading branch information
som-snytt committed Jan 11, 2024
1 parent 1498a12 commit e59b420
Show file tree
Hide file tree
Showing 5 changed files with 83 additions and 6 deletions.
3 changes: 2 additions & 1 deletion spec/01-lexical-syntax.md
Expand Up @@ -344,10 +344,11 @@ Literal ::= [‘-’] integerLiteral
### Integer Literals

```ebnf
integerLiteral ::= (decimalNumeral | hexNumeral)
integerLiteral ::= (decimalNumeral | hexNumeral | binaryNumeral)
[‘L’ | ‘l’]
decimalNumeral ::= digit {digit}
hexNumeral ::= ‘0’ (‘x’ | ‘X’) hexDigit {hexDigit}
binaryNumeral ::= ‘0’ (‘b’ | ‘B’) binaryDigit {binaryDigit}
```

Values of type `Int` are all integer
Expand Down
2 changes: 2 additions & 0 deletions spec/13-syntax-summary.md
Expand Up @@ -35,6 +35,7 @@ opchar ::= ‘!’ | ‘#’ | ‘%’ | ‘&’ | ‘*’ | ‘+’
printableChar ::= all characters in [\u0020, \u007E] inclusive
UnicodeEscape ::= ‘\’ ‘u’ {‘u’} hexDigit hexDigit hexDigit hexDigit
hexDigit ::= ‘0’ | … | ‘9’ | ‘A’ | … | ‘F’ | ‘a’ | … | ‘f’
binaryDigit ::= ‘0’ | ‘1’
charEscapeSeq ::= ‘\’ (‘b’ | ‘t’ | ‘n’ | ‘f’ | ‘r’ | ‘"’ | ‘'’ | ‘\’)
escapeSeq ::= UnicodeEscape | charEscapeSeq
op ::= opchar {opchar}
Expand All @@ -51,6 +52,7 @@ idrest ::= {letter | digit} [‘_’ op]
integerLiteral ::= (decimalNumeral | hexNumeral) [‘L’ | ‘l’]
decimalNumeral ::= digit {digit}
hexNumeral ::= ‘0’ (‘x’ | ‘X’) hexDigit {hexDigit}
binaryNumeral ::= ‘0’ (‘b’ | ‘B’) binaryDigit {binaryDigit}
floatingPointLiteral
::= digit {digit} ‘.’ digit {digit} [exponentPart] [floatType]
Expand Down
2 changes: 1 addition & 1 deletion src/compiler/scala/tools/nsc/ast/parser/Scanners.scala
Expand Up @@ -660,7 +660,7 @@ trait Scanners extends ScannersCommon {
nextChar()
ch match {
case 'x' | 'X' => base = 16 ; nextChar()
//case 'b' | 'B' => base = 2 ; nextChar()
case 'b' | 'B' => base = 2 ; nextChar()
case _ => base = 10 ; putChar('0')
}
if (base != 10 && !isNumberSeparator(ch) && digit2int(ch, base) < 0)
Expand Down
8 changes: 4 additions & 4 deletions test/files/run/literals.check
@@ -1,12 +1,12 @@
literals.scala:63: warning: Lowercase el for long is not recommended because it is easy to confuse with numeral 1; use uppercase L instead [quickfixable]
literals.scala:137: warning: Lowercase el for long is not recommended because it is easy to confuse with numeral 1; use uppercase L instead [quickfixable]
check_success("1l == 1L", 1l, 1L)
^
literals.scala:64: warning: Lowercase el for long is not recommended because it is easy to confuse with numeral 1; use uppercase L instead [quickfixable]
literals.scala:138: warning: Lowercase el for long is not recommended because it is easy to confuse with numeral 1; use uppercase L instead [quickfixable]
check_success("1L == 1l", 1L, 1l)
^
literals.scala:65: warning: Lowercase el for long is not recommended because it is easy to confuse with numeral 1; use uppercase L instead [quickfixable]
literals.scala:139: warning: Lowercase el for long is not recommended because it is easy to confuse with numeral 1; use uppercase L instead [quickfixable]
check_success("1.asInstanceOf[Long] == 1l", 1.asInstanceOf[Long], 1l)
^
literals.scala:112: warning: Lowercase el for long is not recommended because it is easy to confuse with numeral 1; use uppercase L instead [quickfixable]
literals.scala:186: warning: Lowercase el for long is not recommended because it is easy to confuse with numeral 1; use uppercase L instead [quickfixable]
check_success("1l.asInstanceOf[Double] == 1.0", 1l.asInstanceOf[Double], 1.0)
^
74 changes: 74 additions & 0 deletions test/files/run/literals.scala
Expand Up @@ -59,6 +59,80 @@ object Test {
check_success("0x80000000 == -2147483648", 0x80000000, -2147483648)
check_success("0xffffffff == -1", 0xffffffff, -1)

check_success("0b_0000 == 0x0", 0b_0000, 0x0)
check_success("0b_0001 == 0x1", 0b_0001, 0x1)
check_success("0b_0010 == 0x2", 0b_0010, 0x2)
check_success("0b_0011 == 0x3", 0b_0011, 0x3)
check_success("0b_0100 == 0x4", 0b_0100, 0x4)
check_success("0b_0101 == 0x5", 0b_0101, 0x5)
check_success("0b_0110 == 0x6", 0b_0110, 0x6)
check_success("0b_0111 == 0x7", 0b_0111, 0x7)
check_success("0b_1000 == 0x8", 0b_1000, 0x8)
check_success("0b_1001 == 0x9", 0b_1001, 0x9)
check_success("0b_1010 == 0xa", 0b_1010, 0xa)
check_success("0b_1011 == 0xb", 0b_1011, 0xb)
check_success("0b_1100 == 0xc", 0b_1100, 0xc)
check_success("0b_1101 == 0xd", 0b_1101, 0xd)
check_success("0b_1110 == 0xe", 0b_1110, 0xe)
check_success("0b_1111 == 0xf", 0b_1111, 0xf)

check_success("0B_1000 == 0x8", 0B_1000, 0x8)

assert(0b0001_0000 == 16)
assert(0b0010_0000 == 32)
assert(0b0100_0000 == 64)
assert(0b1000_0000 == 128)

assert(0b0001_0000_0000 == 256)
assert(0b0010_0000_0000 == 512)
assert(0b0100_0000_0000 == 1024)
assert(0b1000_0000_0000 == 2048)

assert(0b0001_0000_0000_0000 == 4096)
assert(0b0010_0000_0000_0000 == 8192)
assert(0b0100_0000_0000_0000 == 16384)
assert(0b1000_0000_0000_0000 == 32768)

assert(0b0001__0000_0000_0000_0000 == 65536)
assert(0b0010__0000_0000_0000_0000 == 131072)
assert(0b0100__0000_0000_0000_0000 == 262144)
assert(0b1000__0000_0000_0000_0000 == 524288)

assert(0b0001_0000__0000_0000_0000_0000 == 1048576)
assert(0b0010_0000__0000_0000_0000_0000 == 2097152)
assert(0b0100_0000__0000_0000_0000_0000 == 4194304)
assert(0b1000_0000__0000_0000_0000_0000 == 8388608)

assert(0b0001_0000_0000__0000_0000_0000_0000 == 16777216)
assert(0b0010_0000_0000__0000_0000_0000_0000 == 33554432)
assert(0b0100_0000_0000__0000_0000_0000_0000 == 67108864)
assert(0b1000_0000_0000__0000_0000_0000_0000 == 134217728)

assert(0b0001_0000_0000_0000__0000_0000_0000_0000 == 268435456)
assert(0b0010_0000_0000_0000__0000_0000_0000_0000 == 536870912)
assert(0b0100_0000_0000_0000__0000_0000_0000_0000 == 1073741824)
assert(0b1000_0000_0000_0000__0000_0000_0000_0000L == 2147483648L)

assert(0b1000_0000_0000_0000__0000_0000_0000_0000 == -2147483648) // Signed !
assert(0b1111_1111_1111_1111__1111_1111_1111_1111 == -1)

// Randomly generated using https://numbergenerator.org/random-32-bit-binary-number#!numbers=10&length=32&addfilters=
// Converted to signed decimal using https://onlinetoolz.net/unsigned-signed#base=2&bits=32
assert(0b0110_1000_1100_0101_0010_1100_0100_0011 == 1757752387)
assert(0b1111_0101_0100_1011_0101_1000_0011_0110 == -179611594)
assert(0b0000_0011_0000_1010_1010_0011_0000_0000 == 51028736)
assert(0b0101_0010_1111_1001_0100_0101_1101_1011 == 1392068059)
assert(0b1001_0000_1111_1001_1011_1101_1100_1111 == -1862681137)

assert(0B0000_0111_1110_1100_0111_1100_1000_0010 == 132938882)
assert(0B0000_1011_0111_1011_0001_1010_1010_1000 == 192617128)
assert(0B1100_1100_1000_1010_1111_0111_0100_1101 == -863307955)
assert(0B1000_0000_0001_0010_0001_1001_0101_1110 == -2146297506)
assert(0B1110_0000_0110_1100_0111_0110_1100_1111 == -529762609)

assert(0b0010_1001_0101_1001__1010_0100_1000_1010__1001_1000_0011_0111__1100_1011_0111_0101L == 2979593543648529269L)
assert(0b1101_1110_0100_1000__0010_1101_1010_0010__0111_1000_1111_1001__1010_1001_0101_1000L == -2429641823128802984L)

// long
check_success("1l == 1L", 1l, 1L)
check_success("1L == 1l", 1L, 1l)
Expand Down

0 comments on commit e59b420

Please sign in to comment.