Support Hex, Binary, and Octal number literals #20
|
@ -543,3 +543,18 @@ sqrt := fn(x: int): int {
|
||||||
return g
|
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
|
||||||
|
}
|
||||||
|
```
|
|
@ -3340,5 +3340,6 @@ mod tests {
|
||||||
struct_return_from_module_function => README;
|
struct_return_from_module_function => README;
|
||||||
comptime_pointers => README;
|
comptime_pointers => README;
|
||||||
sort_something_viredly => README;
|
sort_something_viredly => README;
|
||||||
|
hex_octal_binary_literals => README;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -293,19 +293,19 @@ impl<'a> Lexer<'a> {
|
||||||
let kind = match c {
|
let kind = match c {
|
||||||
..=b' ' => continue,
|
..=b' ' => continue,
|
||||||
b'0' if self.advance_if(b'x') => {
|
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();
|
self.advance();
|
||||||
}
|
}
|
||||||
T::Number
|
T::Number
|
||||||
}
|
}
|
||||||
b'0' if self.advance_if(b'b') => {
|
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();
|
self.advance();
|
||||||
}
|
}
|
||||||
T::Number
|
T::Number
|
||||||
}
|
}
|
||||||
b'0' if self.advance_if(b'o') => {
|
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();
|
self.advance();
|
||||||
}
|
}
|
||||||
T::Number
|
T::Number
|
||||||
|
|
|
@ -389,22 +389,23 @@ impl<'a, 'b> Parser<'a, 'b> {
|
||||||
pos: token.start,
|
pos: token.start,
|
||||||
stmts: self.collect_list(T::Semi, T::RBrace, Self::expr),
|
stmts: self.collect_list(T::Semi, T::RBrace, Self::expr),
|
||||||
},
|
},
|
||||||
T::Number => E::Number {
|
T::Number => {
|
||||||
pos: token.start,
|
|
||||||
value: {
|
|
||||||
let slice = self.lexer.slice(token.range());
|
let slice = self.lexer.slice(token.range());
|
||||||
let (slice, radix) = match &slice.get(0..2) {
|
let (slice, radix) = match &slice.get(0..2) {
|
||||||
Some("0x") => (slice.trim_start_matches("0x"), 16),
|
Some("0x") => (slice.trim_start_matches("0x"), Radix::Hex),
|
||||||
Some("0b") => (slice.trim_start_matches("0b"), 16),
|
Some("0b") => (slice.trim_start_matches("0b"), Radix::Binary),
|
||||||
Some("0o") => (slice.trim_start_matches("0o"), 16),
|
Some("0o") => (slice.trim_start_matches("0o"), Radix::Octal),
|
||||||
_ => (slice, 10),
|
_ => (slice, Radix::Decimal),
|
||||||
};
|
};
|
||||||
match u64::from_str_radix(slice, radix) {
|
E::Number {
|
||||||
|
pos: token.start,
|
||||||
|
value: match u64::from_str_radix(slice, radix as u32) {
|
||||||
Ok(value) => value,
|
Ok(value) => value,
|
||||||
Err(e) => self.report(format_args!("invalid number: {e}")),
|
Err(e) => self.report(format_args!("invalid number: {e}")),
|
||||||
|
},
|
||||||
|
radix,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
|
||||||
},
|
|
||||||
T::LParen => {
|
T::LParen => {
|
||||||
let expr = self.expr();
|
let expr = self.expr();
|
||||||
self.expect_advance(T::RParen);
|
self.expect_advance(T::RParen);
|
||||||
|
@ -629,6 +630,15 @@ macro_rules! generate_expr {
|
||||||
(@last ($($last:tt)*),) => { $($last)* };
|
(@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
|
// it would be real nice if we could use relative pointers and still pattern match easily
|
||||||
generate_expr! {
|
generate_expr! {
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||||
|
@ -680,6 +690,7 @@ generate_expr! {
|
||||||
Number {
|
Number {
|
||||||
pos: Pos,
|
pos: Pos,
|
||||||
value: u64,
|
value: u64,
|
||||||
|
radix: Radix,
|
||||||
},
|
},
|
||||||
BinOp {
|
BinOp {
|
||||||
left: &'a Self,
|
left: &'a Self,
|
||||||
|
@ -1001,7 +1012,12 @@ impl<'a> std::fmt::Display for Expr<'a> {
|
||||||
write!(f, "}}")?;
|
write!(f, "}}")?;
|
||||||
res
|
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::Bool { value, .. } => write!(f, "{value}"),
|
||||||
Self::BinOp {
|
Self::BinOp {
|
||||||
left,
|
left,
|
||||||
|
|
3
hblang/tests/codegen_tests_hex_octal_binary_literals.txt
Normal file
3
hblang/tests/codegen_tests_hex_octal_binary_literals.txt
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
code size: 210
|
||||||
|
ret: 0
|
||||||
|
status: Ok(())
|
Loading…
Reference in a new issue