Skip to content

Commit

Permalink
binary literals
Browse files Browse the repository at this point in the history
  • Loading branch information
NotAFlyingGoose committed Jun 4, 2024
1 parent 780153d commit 057a149
Show file tree
Hide file tree
Showing 8 changed files with 165 additions and 3 deletions.
24 changes: 24 additions & 0 deletions crates/ast/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -738,6 +738,7 @@ def_multi_token! {
IntValue:
Dec -> Int
Hex -> Hex
Bin -> Bin
}

def_ast_node!(FloatLiteral);
Expand Down Expand Up @@ -854,6 +855,7 @@ def_ast_token!(DoublePipe);
def_ast_token!(Ident);
def_ast_token!(Int);
def_ast_token!(Hex);
def_ast_token!(Bin);
def_ast_token!(Float);
def_ast_token!(Bool);

Expand Down Expand Up @@ -1483,6 +1485,28 @@ mod tests {
assert_eq!(hex.text(&tree), "0xFeab1");
}

#[test]
fn get_value_of_bin_literal() {
let (tree, root) = parse("0b111000111;");
let statement = root.stmts(&tree).next().unwrap();
let expr = match statement {
Stmt::Expr(expr_stmt) => expr_stmt.expr(&tree),
_ => unreachable!(),
};

let int_literal = match expr {
Some(Expr::IntLiteral(int_literal)) => int_literal,
_ => unreachable!(),
};

let bin = match int_literal.value(&tree).unwrap() {
IntValue::Bin(bin) => bin,
_ => unreachable!(),
};

assert_eq!(bin.text(&tree), "0b111000111");
}

#[test]
fn get_value_of_float_literal() {
let (tree, root) = parse("4.5;");
Expand Down
35 changes: 35 additions & 0 deletions crates/codegen/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1899,5 +1899,40 @@ mod tests {
)
}

#[test]
fn hex_and_bin() {
check_raw(
r#"
main :: () {
iprint(0x1FeeeF001239 + 0b111101010101010);
}
iprint :: (n: i64) {
n := n;
if n < 0 {
n = -n;
putchar('-');
}
if n > 9 {
a := n / 10;
n = n - 10 * a;
iprint(a);
}
putchar({'0' as u8 + n} as char);
}
putchar :: (ch: char) extern;
"#,
"main",
expect![[r#"
35111072468195
"#]],
0,
)
}

// the "ptrs_to_ptrs.capy" and "comptime_types.capy" tests are not reproducible
}
1 change: 1 addition & 0 deletions crates/diagnostics/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -705,6 +705,7 @@ fn format_kind(kind: TokenKind) -> &'static str {
TokenKind::Bool => "boolean",
TokenKind::Int => "integer",
TokenKind::Hex => "hex literal",
TokenKind::Bin => "binary literal",
TokenKind::Float => "float",
TokenKind::SingleQuote => "`'`",
TokenKind::DoubleQuote => "`\"`",
Expand Down
85 changes: 84 additions & 1 deletion crates/hir/src/body.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1342,7 +1342,22 @@ impl<'a> Ctx<'a> {

match u64::from_str_radix(value, 16) {
Ok(value) => Expr::IntLiteral(value),
Err(why) => {
Err(_) => {
self.diagnostics.push(LoweringDiagnostic {
kind: LoweringDiagnosticKind::OutOfRangeIntLiteral,
range: int_literal.range(self.tree),
});

Expr::Missing
}
}
}
ast::IntValue::Bin(bin) => {
let value = bin.text(self.tree).strip_prefix("0b").unwrap();

match u64::from_str_radix(value, 2) {
Ok(value) => Expr::IntLiteral(value),
Err(_) => {
self.diagnostics.push(LoweringDiagnostic {
kind: LoweringDiagnosticKind::OutOfRangeIntLiteral,
range: int_literal.range(self.tree),
Expand Down Expand Up @@ -2822,6 +2837,74 @@ mod tests {
)
}

#[test]
fn hex_literal() {
check(
r#"
foo :: () {
num := 0x21eFAB;
}
"#,
expect![[r#"
main::foo :: () {
l0 := 2224043;
};
"#]],
|_| [],
)
}

#[test]
fn out_of_range_hex_literal() {
check(
r#"
foo :: () {
num := 0x10000000000000000;
}
"#,
expect![[r#"
main::foo :: () {
l0 := <missing>;
};
"#]],
|_| [(LoweringDiagnosticKind::OutOfRangeIntLiteral, 56..75)],
)
}

#[test]
fn bin_literal() {
check(
r#"
foo :: () {
num := 0b001100101010101;
}
"#,
expect![[r#"
main::foo :: () {
l0 := 6485;
};
"#]],
|_| [],
)
}

#[test]
fn out_of_range_bin_literal() {
check(
r#"
foo :: () {
num := 0b10000000000000000000000000000000000000000000000000000000000000000;
}
"#,
expect![[r#"
main::foo :: () {
l0 := <missing>;
};
"#]],
|_| [(LoweringDiagnosticKind::OutOfRangeIntLiteral, 56..123)],
)
}

#[test]
fn float_literal() {
check(
Expand Down
4 changes: 2 additions & 2 deletions crates/parser/src/grammar/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ fn parse_lhs(
TokenKind::Tilde,
]);

let cm = if p.at(TokenKind::Int) || p.at(TokenKind::Hex) {
let cm = if p.at(TokenKind::Int) || p.at(TokenKind::Hex) || p.at(TokenKind::Bin) {
parse_int_literal(p)
} else if p.at(TokenKind::Float) {
parse_float_literal(p)
Expand Down Expand Up @@ -286,7 +286,7 @@ fn parse_post_operators(
}

fn parse_int_literal(p: &mut Parser) -> CompletedMarker {
assert!(p.at(TokenKind::Int) || p.at(TokenKind::Hex));
assert!(p.at(TokenKind::Int) || p.at(TokenKind::Hex) || p.at(TokenKind::Bin));
let m = p.start();
p.bump();
m.complete(p, NodeKind::IntLiteral)
Expand Down
6 changes: 6 additions & 0 deletions crates/parser/src/tests/repl_line/bin_literal.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
0b10100010011111111
===
[email protected]
[email protected]
[email protected]
[email protected] "0b10100010011111111"
12 changes: 12 additions & 0 deletions crates/parser/src/tests/repl_line/bin_literal_multiplication.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
0b101010101 * 0b010101010
===
[email protected]
[email protected]
[email protected]
[email protected]
[email protected] "0b101010101"
[email protected] " "
[email protected] "*"
[email protected] " "
[email protected]
[email protected] "0b010101010"
1 change: 1 addition & 0 deletions tokenizer.txt
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ Ident = /[A-Za-z_][A-Za-z0-9_]*/
Float = /(\d[\d_]*)?\.(\d[\d_]*)+([eE][-+]?(\d[\d_]*)+)?/
Int = /(\d[\d_]*)+([eE](\d[\d_]*)+)?/
Hex = /0x[0-9a-fA-F]+/
Bin = /0b[01]+/
Bool = /true|false/
_SingleQuote
_DoubleQuote
Expand Down

0 comments on commit 057a149

Please sign in to comment.