fix obvious bugs, add unit test, hopefully preserve radix when formatting

This commit is contained in:
koniifer 2024-09-01 20:07:19 +01:00
parent 27462d9a33
commit 581c4d531c
5 changed files with 53 additions and 18 deletions

View file

@ -543,3 +543,18 @@ sqrt := fn(x: int): int {
return g
}
```
#### hex_octal_binary_literals
```hb
main := fn(): int {
hex := 0xFF
decimal := 255
octal := 0o377
binary := 0b11111111
if hex == decimal & octal == decimal & binary == decimal {
return 0
}
return 1
}
```

View file

@ -3340,5 +3340,6 @@ mod tests {
struct_return_from_module_function => README;
comptime_pointers => README;
sort_something_viredly => README;
hex_octal_binary_literals => README;
}
}

View file

@ -293,19 +293,19 @@ impl<'a> Lexer<'a> {
let kind = match c {
..=b' ' => continue,
b'0' if self.advance_if(b'x') => {
while let Some(b'0'..=b'9') = self.peek() {
while let Some(b'0'..=b'9' | b'A'..=b'F' | b'a'..=b'f') = self.peek() {
self.advance();
}
T::Number
}
b'0' if self.advance_if(b'b') => {
while let Some(b'0'..=b'9') = self.peek() {
while let Some(b'0' | b'1') = self.peek() {
self.advance();
}
T::Number
}
b'0' if self.advance_if(b'o') => {
while let Some(b'0'..=b'9') = self.peek() {
while let Some(b'0'..=b'7') = self.peek() {
self.advance();
}
T::Number

View file

@ -389,22 +389,23 @@ impl<'a, 'b> Parser<'a, 'b> {
pos: token.start,
stmts: self.collect_list(T::Semi, T::RBrace, Self::expr),
},
T::Number => E::Number {
pos: token.start,
value: {
let slice = self.lexer.slice(token.range());
let (slice, radix) = match &slice.get(0..2) {
Some("0x") => (slice.trim_start_matches("0x"), 16),
Some("0b") => (slice.trim_start_matches("0b"), 16),
Some("0o") => (slice.trim_start_matches("0o"), 16),
_ => (slice, 10),
};
match u64::from_str_radix(slice, radix) {
T::Number => {
let slice = self.lexer.slice(token.range());
let (slice, radix) = match &slice.get(0..2) {
Some("0x") => (slice.trim_start_matches("0x"), Radix::Hex),
Some("0b") => (slice.trim_start_matches("0b"), Radix::Binary),
Some("0o") => (slice.trim_start_matches("0o"), Radix::Octal),
_ => (slice, Radix::Decimal),
};
E::Number {
pos: token.start,
value: match u64::from_str_radix(slice, radix as u32) {
Ok(value) => value,
Err(e) => self.report(format_args!("invalid number: {e}")),
}
},
},
},
radix,
}
}
T::LParen => {
let expr = self.expr();
self.expect_advance(T::RParen);
@ -629,6 +630,15 @@ macro_rules! generate_expr {
(@last ($($last:tt)*),) => { $($last)* };
}
#[repr(u32)]
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum Radix {
Hex = 16,
Octal = 8,
Binary = 2,
Decimal = 10,
}
// it would be real nice if we could use relative pointers and still pattern match easily
generate_expr! {
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
@ -680,6 +690,7 @@ generate_expr! {
Number {
pos: Pos,
value: u64,
radix: Radix,
},
BinOp {
left: &'a Self,
@ -1001,7 +1012,12 @@ impl<'a> std::fmt::Display for Expr<'a> {
write!(f, "}}")?;
res
}
Self::Number { value, .. } => write!(f, "{value}"),
Self::Number { value, radix, .. } => match radix {
Radix::Decimal => write!(f, "{value}"),
Radix::Hex => write!(f, "{value:#X}"),
Radix::Octal => write!(f, "{value:#o}"),
Radix::Binary => write!(f, "{value:#b}"),
},
Self::Bool { value, .. } => write!(f, "{value}"),
Self::BinOp {
left,

View file

@ -0,0 +1,3 @@
code size: 210
ret: 0
status: Ok(())