diff --git a/src/lexer.rs b/src/lexer.rs index 8c07890..e246b40 100644 --- a/src/lexer.rs +++ b/src/lexer.rs @@ -15,7 +15,7 @@ pub enum Token { #[token("else")] Else, #[token("in")] In, #[token("let")] Let, - #[token("var")] Var, + #[token("mut")] Mut, #[token("interface")] Interface, #[token("impl")] Impl, diff --git a/src/lib.rs b/src/lib.rs index d88a362..49b111f 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -30,7 +30,7 @@ impl ColorTheme { pub fn token_style(&self, token: &Token) -> &Style { use Token::*; match token { - Struct | Function | For | If | Else | In | Let | Var => &self.keyword, + Struct | Function | For | If | Else | In | Let | Mut => &self.keyword, BinaryInteger | OctalInteger | DecimalInteger => &self.literal, SingleLineComment => &self.comment, Error => &self.error, diff --git a/src/parse.rs b/src/parse.rs index 7275110..61f62b4 100644 --- a/src/parse.rs +++ b/src/parse.rs @@ -13,12 +13,20 @@ impl<'a> ParseTree<'a> { let mut declarations = Vec::new(); let mut associated_struct = None; while let Some(tok) = lexer.next() { - if let Some(_) = associated_struct { - if tok != Token::Function { - lexer.panic_message("Expected fn"); + if let Some(struct_name) = associated_struct { + let mut mutable = false; + if tok == Token::Mut { + mutable = true; + lexer.eat_expect(Token::Function); + } else if tok != Token::Function { + lexer.panic_message("Expected fn or mut"); } - declarations.push(Definition::build_function(associated_struct, lexer)); + declarations.push(Definition::build_function( + Some((struct_name, mutable)), + lexer, + )); + associated_struct = None; } else { match tok { @@ -26,7 +34,7 @@ impl<'a> ParseTree<'a> { Token::Function => declarations.push(Definition::build_function(None, lexer)), Token::Interface => declarations.push(Definition::build_interface(lexer)), Token::Identifier => associated_struct = Some(lexer.slice()), - _ => lexer.panic_message("Expected associated struct identifier, fn or struct"), + _ => lexer.panic_message("Expected function, struct, or interface"), } } } @@ -42,7 +50,7 @@ pub enum Definition<'a> { members: Vec>, }, Function { - associated_struct: Option<&'a str>, + associated_struct: Option<(&'a str, bool)>, name: &'a str, signature: FnSig<'a>, body: FnBody<'a>, @@ -78,7 +86,10 @@ impl<'a> Definition<'a> { Self::Struct { name, members } } - pub fn build_function(associated_struct: Option<&'a str>, lexer: &mut Lexer<'a>) -> Self { + pub fn build_function( + associated_struct: Option<(&'a str, bool)>, + lexer: &mut Lexer<'a>, + ) -> Self { let name = lexer.eat_expect_id(); let (signature, tok) = FnSig::build(lexer); @@ -204,15 +215,6 @@ impl<'a> FnBody<'a> { _ => lexer.panic_message("Unexpected token"), } } - Token::Var => { - let (statement, next) = Statement::build_var(lexer); - statements.push(statement); - match next { - Token::Semicolon => {} - Token::BraceClose => break, - _ => lexer.panic_message("Unexpected token"), - } - } Token::Identifier => match Expr::build_start(tok, lexer) { (None, Token::Semicolon | Token::BraceClose) => {} (Some(expr), Token::Semicolon) => statements.push(Statement::Expr(expr)), @@ -223,7 +225,7 @@ impl<'a> FnBody<'a> { _ => lexer.panic_message("Unexpected token"), }, Token::BraceClose => break, - _ => lexer.panic_message("Expected var, let, or assign"), + _ => lexer.panic_message("Expected let or expression"), } } @@ -294,6 +296,7 @@ pub enum BinaryOp { Sub, Mul, Div, + Assign, Less, LessEq, Greater, @@ -311,6 +314,7 @@ impl BinaryOp { OpSub => Some(Sub), OpMul => Some(Mul), OpDiv => Some(Div), + OpAssign => Some(Assign), OpLess => Some(Less), OpLessEq => Some(LessEq), OpGreater => Some(Greater), @@ -335,10 +339,7 @@ pub enum Statement<'a> { Expr(Expr<'a>), Let { var: &'a str, - expr: Expr<'a>, - }, - Var { - var: &'a str, + mutable: bool, expr: Expr<'a>, }, If { @@ -356,15 +357,18 @@ impl<'a> Statement<'a> { } pub fn build_let(lexer: &mut Lexer<'a>) -> (Self, Token) { - let var = lexer.eat_expect_id(); - let (expr, tail) = Self::eat_assign(lexer); - (Self::Let { var, expr }, tail) - } + let mut mutable = false; + let var = match lexer.next().unwrap() { + Token::Identifier => lexer.slice(), + Token::Mut => { + mutable = true; + lexer.eat_expect_id() + } + _ => lexer.panic_message("Unexpected token"), + }; - pub fn build_var(lexer: &mut Lexer<'a>) -> (Self, Token) { - let var = lexer.eat_expect_id(); let (expr, tail) = Self::eat_assign(lexer); - (Self::Var { var, expr }, tail) + (Self::Let { var, mutable, expr }, tail) } } diff --git a/src/test/example.fae b/src/test/example.fae index a0e3f80..ed41b46 100644 --- a/src/test/example.fae +++ b/src/test/example.fae @@ -37,9 +37,9 @@ fn count_neighbors(BitArray array, i32 i, i32 j) i32 { } // associated function for the World struct -World fn set_next(i32 i, i32 j) { +World mut fn set_next(i32 i, i32 j) { // members on this World struct can be accessed with `.` - var numdots = .numdots; // mutable variables are defined with `var` + let mut numdots = .numdots; // mutable variables are defined with `let mut` let neighbors = count_neighbors(.current, i, j); // `if` statements are expressions @@ -61,7 +61,6 @@ World fn set_next(i32 i, i32 j) { }; if next != 0 { - // TODO: mutability rules for arguments? if i < .xmin { .xmin = i; } if i > .xmax { .xmax = i; } if j < .ymin { .ymin = j; } @@ -85,7 +84,6 @@ World fn next_cycle() { // TODO: figure out better range definitions, or ditch them altogether for y in 0..(.ysize) { for x in 0..(.xsize) { - // TODO: mutability rules .current.set_bit(x, y, .next.get_bit(x, y)); } } diff --git a/src/test/function.fae b/src/test/function.fae index 5b939e1..673e652 100644 --- a/src/test/function.fae +++ b/src/test/function.fae @@ -3,9 +3,9 @@ fn free_floating(i32 arg1, i32 arg2) ReturnType { } // associated function for the World struct -World fn set_next(i32 i, i32 j) { +World mut fn set_next(i32 i, i32 j) { // members on this World struct can be accessed with `.` - var numdots = .numdots; // mutable variables are defined with `var` + let mut numdots = .numdots; // mutable variables are defined with `let mut` let neighbors = count_neighbors(.current, i, j); // `if` statements are expressions @@ -27,7 +27,6 @@ World fn set_next(i32 i, i32 j) { }; if next != 0 { - // TODO: mutability rules for arguments? if i < .xmin { .xmin = i; } if i > .xmax { .xmax = i; } if j < .ymin { .ymin = j; }