From 9de4a8aecd8450922033d8d69195aed3d2050064 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=83=AA=E3=82=AD=E8=90=8C?= Date: Mon, 30 Jun 2025 23:54:50 +0200 Subject: [PATCH] replace `def = value` with `def: value`, and `let a = b` with `a = b` in the name of terseness i'm also slipping in a new brush preset that i made closes #125 --- crates/haku/src/compiler.rs | 4 +- crates/haku/src/lexer.rs | 2 +- crates/haku/src/parser.rs | 33 +++++++++++++-- crates/haku/src/parser/tests.rs | 71 ++++++++++++++++----------------- crates/haku/src/token.rs | 2 +- 5 files changed, 67 insertions(+), 45 deletions(-) diff --git a/crates/haku/src/compiler.rs b/crates/haku/src/compiler.rs index a095dcb..a458c5e 100644 --- a/crates/haku/src/compiler.rs +++ b/crates/haku/src/compiler.rs @@ -635,7 +635,7 @@ fn def_prepass<'a>(c: &mut Compiler<'a>, src: &Source<'a>, toplevel: NodeId) -> while let Some(binary) = walk.node_of(NodeKind::Binary) { let mut binary_walk = src.ast.walk(binary); if let (Some(ident), Some(op)) = (binary_walk.node(), binary_walk.get(NodeKind::Op)) { - if src.ast.span(op).slice(src.code) == "=" { + if src.ast.span(op).slice(src.code) == ":" { let name = src.ast.span(ident).slice(src.code); match c.defs.add_def(name) { Ok(_) => (), @@ -667,7 +667,7 @@ fn compile_toplevel_expr<'a>( ) -> CompileResult { if src.ast.kind(node_id) == NodeKind::Binary { if let Some(op) = src.ast.walk(node_id).get(NodeKind::Op) { - if src.ast.span(op).slice(src.code) == "=" { + if src.ast.span(op).slice(src.code) == ":" { compile_def(c, src, node_id)?; return Ok(ToplevelExpr::Def); } diff --git a/crates/haku/src/lexer.rs b/crates/haku/src/lexer.rs index fe8f879..64683a9 100644 --- a/crates/haku/src/lexer.rs +++ b/crates/haku/src/lexer.rs @@ -73,7 +73,6 @@ fn ident(l: &mut Lexer<'_>) -> TokenKind { "or" => TokenKind::Or, "if" => TokenKind::If, "else" => TokenKind::Else, - "let" => TokenKind::Let, _ => TokenKind::Ident, } } @@ -210,6 +209,7 @@ fn token(l: &mut Lexer<'_>) -> (TokenKind, Span) { '[' => one(l, TokenKind::LBrack), ']' => one(l, TokenKind::RBrack), ',' => one(l, TokenKind::Comma), + ':' => one(l, TokenKind::Colon), '\\' => one(l, TokenKind::Backslash), _ => { diff --git a/crates/haku/src/parser.rs b/crates/haku/src/parser.rs index 2c6a80f..a64aad8 100644 --- a/crates/haku/src/parser.rs +++ b/crates/haku/src/parser.rs @@ -306,7 +306,7 @@ enum Tighter { fn tighter(left: TokenKind, right: TokenKind) -> Tighter { fn tightness(kind: TokenKind) -> Option { match kind { - TokenKind::Equal => Some(0), + TokenKind::Equal | TokenKind::Colon => Some(0), TokenKind::EqualEqual | TokenKind::NotEqual | TokenKind::Less @@ -590,7 +590,6 @@ const PREFIX_TOKENS: TokenKindSet = TokenKindSet::new(&[ TokenKind::LParen, TokenKind::Backslash, TokenKind::If, - TokenKind::Let, TokenKind::LBrack, ]); @@ -606,7 +605,6 @@ fn prefix(p: &mut Parser) -> Closed { TokenKind::LParen => paren(p), TokenKind::Backslash => lambda(p), TokenKind::If => if_expr(p), - TokenKind::Let => let_expr(p), _ => { assert!( @@ -637,7 +635,9 @@ fn infix(p: &mut Parser, op: TokenKind) -> NodeKind { | TokenKind::LessEqual | TokenKind::Greater | TokenKind::GreaterEqual - | TokenKind::Equal => infix_binary(p, op), + | TokenKind::Colon => infix_binary(p, op), + + TokenKind::Equal => infix_let(p, op), _ if PREFIX_TOKENS.contains(op) => infix_call(p), @@ -666,6 +666,31 @@ fn infix_call(p: &mut Parser) -> NodeKind { NodeKind::Call } +fn infix_let(p: &mut Parser, op: TokenKind) -> NodeKind { + p.advance(); + + if p.peek() == TokenKind::Newline { + p.advance(); + } + + precedence_parse(p, op); + + if p.peek() == TokenKind::Newline { + p.advance(); + } else { + let span = p.span(); + p.emit(Diagnostic::error( + span, + "new line expected after variable definition `a = b`", + )); + p.advance_with_error(); + } + + expr(p); + + NodeKind::Let +} + pub fn expr(p: &mut Parser) { precedence_parse(p, TokenKind::Eof) } diff --git a/crates/haku/src/parser/tests.rs b/crates/haku/src/parser/tests.rs index c5711ed..c06d32d 100644 --- a/crates/haku/src/parser/tests.rs +++ b/crates/haku/src/parser/tests.rs @@ -316,7 +316,7 @@ Binary @ 0..6 ); assert_ast_eq( - "1 = 1", + "1 : 1", expr, " Binary @ 0..5 @@ -864,52 +864,49 @@ Toplevel @ 1..63 #[test] fn let_expr() { assert_ast_eq( - r#" let x = 1 + r#" x = 1 x "#, toplevel, " -Toplevel @ 1..24 - Let @ 1..24 - Token @ 1..4 - Ident @ 5..6 +Toplevel @ 1..20 + Let @ 1..20 + Ident @ 1..2 + Token @ 1..2 + Token @ 3..4 + Number @ 5..6 Token @ 5..6 - Token @ 7..8 - Number @ 9..10 - Token @ 9..10 - Token @ 10..11 - Ident @ 23..24 - Token @ 23..24", + Token @ 6..7 + Ident @ 19..20 + Token @ 19..20", ); assert_ast_eq( - r#" let x = 1 - let y = 2 + r#" x = 1 + y = 2 x + y "#, toplevel, " -Toplevel @ 1..50 - Let @ 1..50 - Token @ 1..4 - Ident @ 5..6 +Toplevel @ 1..42 + Let @ 1..42 + Ident @ 1..2 + Token @ 1..2 + Token @ 3..4 + Number @ 5..6 Token @ 5..6 - Token @ 7..8 - Number @ 9..10 - Token @ 9..10 - Token @ 10..11 - Let @ 23..50 - Token @ 23..26 - Ident @ 27..28 - Token @ 27..28 - Token @ 29..30 - Number @ 31..32 - Token @ 31..32 - Token @ 32..33 - Binary @ 45..50 - Ident @ 45..46 - Token @ 45..46 - Op @ 47..48 - Token @ 47..48 - Ident @ 49..50 - Token @ 49..50", + Token @ 6..7 + Let @ 19..42 + Ident @ 19..20 + Token @ 19..20 + Token @ 21..22 + Number @ 23..24 + Token @ 23..24 + Token @ 24..25 + Binary @ 37..42 + Ident @ 37..38 + Token @ 37..38 + Op @ 39..40 + Token @ 39..40 + Ident @ 41..42 + Token @ 41..42", ) } diff --git a/crates/haku/src/token.rs b/crates/haku/src/token.rs index ed36150..5a0ba1f 100644 --- a/crates/haku/src/token.rs +++ b/crates/haku/src/token.rs @@ -34,6 +34,7 @@ pub enum TokenKind { RBrack, Comma, Equal, + Colon, Backslash, RArrow, @@ -43,7 +44,6 @@ pub enum TokenKind { Or, If, Else, - Let, // NOTE: This must be kept last for TokenSet to work correctly. Error,