diff --git a/crates/saft-ir/src/lowerer.rs b/crates/saft-ir/src/lowerer.rs index b747dfb..a10add2 100644 --- a/crates/saft-ir/src/lowerer.rs +++ b/crates/saft-ir/src/lowerer.rs @@ -120,7 +120,7 @@ impl Lowerer { self.scoped_based(|l| { let params = params .iter() - .map(|ident| l.declare(ident)) + .map(|ident| l.declare(&ident.v.name)) .try_collect::>()?; let body = l.lower_block(body)?; diff --git a/crates/saft-syntax/src/ast.rs b/crates/saft-syntax/src/ast.rs index 9e92ba0..8cb6a2e 100644 --- a/crates/saft-syntax/src/ast.rs +++ b/crates/saft-syntax/src/ast.rs @@ -127,13 +127,21 @@ pub enum Item { Function(Function), } +#[derive(Debug, Clone, PartialEq)] +pub struct Parameter { + pub name: Spanned, + pub ty: Spanned, +} + #[derive(Debug, Clone, PartialEq)] pub struct Function { pub ident: Spanned, - pub params: Vec>, + pub params: Vec>, pub body: Spanned, + pub ret_ty: Option>, } +#[derive(Debug, Clone, PartialEq, Eq)] pub enum Type { Ident(Ident), } diff --git a/crates/saft-syntax/src/lex.rs b/crates/saft-syntax/src/lex.rs index b9a8e1e..4c9456a 100644 --- a/crates/saft-syntax/src/lex.rs +++ b/crates/saft-syntax/src/lex.rs @@ -80,6 +80,7 @@ impl<'a> Lexer<'a> { '!' if Self::eat_chars(&mut cur, "!=") => mktoken!(cur, T::BangEqual), '!' => eat_token!(cur, T::Bang), '+' => eat_token!(cur, T::Plus), + '-' if Self::eat_chars(&mut cur, "->") => mktoken!(cur, T::Arrow), '-' => eat_token!(cur, T::Minus), '*' => eat_token!(cur, T::Star), '/' if Self::eat_chars(&mut cur, "//") => mktoken!(cur, T::SlashSlash), diff --git a/crates/saft-syntax/src/parser.rs b/crates/saft-syntax/src/parser.rs index cb33603..be9294c 100644 --- a/crates/saft-syntax/src/parser.rs +++ b/crates/saft-syntax/src/parser.rs @@ -493,11 +493,17 @@ impl<'a> Parser<'a> { let start = self.eat(Token::Fn)?; let ident = self.eat_ident()?; - let mut params = Vec::new(); + let mut params = Vec::>::new(); self.eat(Token::LParen)?; while self.peek().v != Token::RParen { - let param = self.eat_ident()?; + let name = self.eat_ident()?; + self.eat(Token::Colon)?; + let ty = self.parse_ty()?; + let s = name.s.join(&ty.s); + + let param = s.spanned(ast::Parameter { name, ty }); + params.push(param); if self.try_eat(Token::Comma).is_none() { @@ -507,6 +513,12 @@ impl<'a> Parser<'a> { self.eat(Token::RParen)?; + let ret_ty = if self.try_eat(Token::Arrow).is_some() { + Some(self.parse_ty()?) + } else { + None + }; + let body = self.parse_block(None)?; let s = start.join(&body.s); @@ -515,6 +527,7 @@ impl<'a> Parser<'a> { ident, params, body, + ret_ty, })), s, )) diff --git a/crates/saft-syntax/src/token.rs b/crates/saft-syntax/src/token.rs index 39d56a4..6ed8b4a 100644 --- a/crates/saft-syntax/src/token.rs +++ b/crates/saft-syntax/src/token.rs @@ -23,6 +23,7 @@ pub enum Token { Comma, Semicolon, Colon, + Arrow, Identifier(String), Float(f64), @@ -98,6 +99,7 @@ impl Token { Comment(s) => format!("comment '{s}'"), Colon => "':'".into(), Let => "'let'".into(), + Arrow => "'->'".into(), } } } diff --git a/tests/res/tests/items/functions/assignment.saf b/tests/res/tests/items/functions/assignment.saf index af6be29..35ff66c 100644 --- a/tests/res/tests/items/functions/assignment.saf +++ b/tests/res/tests/items/functions/assignment.saf @@ -1,4 +1,4 @@ -fn f(x) { +fn f(x: int) { print("Okay boomer " + x) } diff --git a/tests/res/tests/items/functions/order.saf b/tests/res/tests/items/functions/order.saf index f257a5a..8361939 100644 --- a/tests/res/tests/items/functions/order.saf +++ b/tests/res/tests/items/functions/order.saf @@ -1,6 +1,6 @@ printadd(1, 2); -fn printadd(a, b) { +fn printadd(a: int, b: int) { print(a + b); } diff --git a/tests/res/tests/misc/fib.saf b/tests/res/tests/misc/fib.saf index 8914960..5a7ccc4 100644 --- a/tests/res/tests/misc/fib.saf +++ b/tests/res/tests/misc/fib.saf @@ -1,4 +1,4 @@ -fn fib(i) { +fn fib(i: int) -> int { if i < 2 { i } else { diff --git a/tests/res/tests/misc/fib_loop.saf b/tests/res/tests/misc/fib_loop.saf index c31ca43..fe3a956 100644 --- a/tests/res/tests/misc/fib_loop.saf +++ b/tests/res/tests/misc/fib_loop.saf @@ -1,4 +1,4 @@ -fn fib(n) { +fn fib(n: int) -> int { if n == 0 { return 0; }; let a = 0;