···555555 when finding the Gleam files of a package.
556556 ([Giacomo Cavalieri](https://github.com/giacomocavalieri))
557557558558+- Fixed a bug where the compiler would not be able to correctly parse negative
559559+ numbers written in binary, octal, or hexadecimal base.
560560+ ([Giacomo Cavalieri](https://github.com/giacomocavalieri))
561561+558562- The formatter now properly formats binary operations in bit array size
559563 segments.
560564 ([Andrey Kozhev](https://github.com/ankddev))
+61-30
compiler-core/src/parse/lexer.rs
···88use crate::parse::error::{LexicalError, LexicalErrorType};
99use crate::parse::token::Token;
1010use std::char;
1111+use std::ops::Neg;
11121213use super::error::InvalidUnicodeEscapeError;
1314···879880880881 fn lex_number(&mut self) -> LexResult {
881882 let start_pos = self.get_pos();
883883+884884+ // We call this function after making sure that what comes next starts
885885+ // with what seems to be a valid number. If we see that it starts with
886886+ // `-` we consume the token and record that the number is negative.
887887+ let is_negative = if self.chr0 == Some('-') {
888888+ let _ = self.next_char();
889889+ true
890890+ } else {
891891+ false
892892+ };
893893+882894 let num = if self.chr0 == Some('0') {
883883- if self.chr1 == Some('x') || self.chr1 == Some('X') {
884884- // Hex!
885885- let _ = self.next_char();
886886- let _ = self.next_char();
887887- self.lex_number_radix(start_pos, 16, "0x")?
888888- } else if self.chr1 == Some('o') || self.chr1 == Some('O') {
889889- // Octal!
890890- let _ = self.next_char();
891891- let _ = self.next_char();
892892- self.lex_number_radix(start_pos, 8, "0o")?
893893- } else if self.chr1 == Some('b') || self.chr1 == Some('B') {
894894- // Binary!
895895- let _ = self.next_char();
896896- let _ = self.next_char();
897897- self.lex_number_radix(start_pos, 2, "0b")?
898898- } else {
899899- self.lex_decimal_number()?
895895+ match self.chr1 {
896896+ Some('x' | 'X') => {
897897+ // Hex!
898898+ let _ = self.next_char();
899899+ let _ = self.next_char();
900900+ self.lex_number_radix(start_pos, 16, is_negative, "0x")?
901901+ }
902902+ Some('o' | 'O') => {
903903+ // Octal!
904904+ let _ = self.next_char();
905905+ let _ = self.next_char();
906906+ self.lex_number_radix(start_pos, 8, is_negative, "0o")?
907907+ }
908908+ Some('b' | 'B') => {
909909+ // Binary!
910910+ let _ = self.next_char();
911911+ let _ = self.next_char();
912912+ self.lex_number_radix(start_pos, 2, is_negative, "0b")?
913913+ }
914914+ _ => self.lex_decimal_number(start_pos, is_negative)?,
900915 }
901916 } else {
902902- self.lex_decimal_number()?
917917+ self.lex_decimal_number(start_pos, is_negative)?
903918 };
904919905920 if Some('_') == self.chr0 {
···917932 }
918933919934 // Lex a hex/octal/decimal/binary number without a decimal point.
920920- fn lex_number_radix(&mut self, start_pos: u32, radix: u32, prefix: &str) -> LexResult {
935935+ fn lex_number_radix(
936936+ &mut self,
937937+ start_pos: u32,
938938+ radix: u32,
939939+ is_negative: bool,
940940+ prefix: &str,
941941+ ) -> LexResult {
921942 let num = self.radix_run(radix);
922943 if num.is_empty() {
923944 let location = self.get_pos() - 1;
···941962 let value = format!("{prefix}{num}");
942963 let int_value = super::parse_int_value(&value).expect("int value to parse as bigint");
943964 let end_pos = self.get_pos();
965965+966966+ let (value, int_value) = if is_negative {
967967+ (format!("-{value}"), int_value.neg())
968968+ } else {
969969+ (value, int_value)
970970+ };
971971+944972 Ok((
945973 start_pos,
946974 Token::Int {
···954982955983 // Lex a normal number, that is, no octal, hex or binary number.
956984 // This function cannot be reached without the head of the stream being either 0-9 or '-', 0-9
957957- fn lex_decimal_number(&mut self) -> LexResult {
958958- self.lex_decimal_or_int_number(true)
985985+ fn lex_decimal_number(&mut self, start_pos: u32, is_negative: bool) -> LexResult {
986986+ self.lex_decimal_or_int_number(start_pos, is_negative, true)
959987 }
960988961961- fn lex_int_number(&mut self) -> LexResult {
962962- self.lex_decimal_or_int_number(false)
989989+ fn lex_int_number(&mut self, start_pos: u32, is_negative: bool) -> LexResult {
990990+ self.lex_decimal_or_int_number(start_pos, is_negative, false)
963991 }
964992965965- fn lex_decimal_or_int_number(&mut self, can_lex_decimal: bool) -> LexResult {
966966- let start_pos = self.get_pos();
993993+ fn lex_decimal_or_int_number(
994994+ &mut self,
995995+ start_pos: u32,
996996+ is_negative: bool,
997997+ can_lex_decimal: bool,
998998+ ) -> LexResult {
967999 let mut value = String::new();
968968- // consume negative sign
969969- if self.chr0 == Some('-') {
970970- value.push(self.next_char().expect("lex_normal_number negative"));
971971- }
10001000+ if is_negative {
10011001+ value.push('-')
10021002+ };
9721003 // consume first run of digits
9731004 value.push_str(&self.radix_run(10));
9741005···10251056 // It can be nested like: `tuple.1.2.3.4`
10261057 loop {
10271058 if matches!(self.chr0, Some('0'..='9')) {
10281028- let number = self.lex_int_number()?;
10591059+ let number = self.lex_int_number(self.get_pos(), false)?;
10291060 self.emit(number);
10301061 } else {
10311062 break;