From 85b2ebf04ae7afa842e9ab330c67580df1ed556e Mon Sep 17 00:00:00 2001 From: sofia Date: Fri, 11 Jul 2025 21:32:20 +0300 Subject: [PATCH] Add mutability parsing --- reid/examples/{arithmetic.rs => mutable.rs} | 4 +-- reid/examples/reid/arithmetic.reid | 13 ------- reid/examples/reid/mutable.reid | 15 ++++++++ reid/src/ast/mod.rs | 15 ++++++-- reid/src/ast/parse.rs | 38 ++++++++++++++++----- reid/src/ast/process.rs | 7 ++-- reid/src/lexer.rs | 3 ++ 7 files changed, 67 insertions(+), 28 deletions(-) rename reid/examples/{arithmetic.rs => mutable.rs} (52%) delete mode 100644 reid/examples/reid/arithmetic.reid create mode 100644 reid/examples/reid/mutable.reid diff --git a/reid/examples/arithmetic.rs b/reid/examples/mutable.rs similarity index 52% rename from reid/examples/arithmetic.rs rename to reid/examples/mutable.rs index 5f9ecd6..ec6a04c 100644 --- a/reid/examples/arithmetic.rs +++ b/reid/examples/mutable.rs @@ -1,9 +1,9 @@ use reid::compile; -pub static ARITHMETIC: &str = include_str!("./reid/arithmetic.reid"); +pub static MUTABLE: &str = include_str!("./reid/mutable.reid"); fn main() { - let text = match compile(ARITHMETIC) { + let text = match compile(MUTABLE) { Ok(t) => t, Err(e) => panic!("{}", e), }; diff --git a/reid/examples/reid/arithmetic.reid b/reid/examples/reid/arithmetic.reid deleted file mode 100644 index d80436b..0000000 --- a/reid/examples/reid/arithmetic.reid +++ /dev/null @@ -1,13 +0,0 @@ -// Arithmetic, function calls and imports! - -fn main() { - let test = 9; - let simpleAdd = 2 + 2; - let simpleSub = 7 - 2; // 14 - - if simpleAdd < test { - return 3; - } - - return arithmetic + simpleSub + boop; -} \ No newline at end of file diff --git a/reid/examples/reid/mutable.reid b/reid/examples/reid/mutable.reid new file mode 100644 index 0000000..4d75cd4 --- /dev/null +++ b/reid/examples/reid/mutable.reid @@ -0,0 +1,15 @@ +// Arithmetic, function calls and imports! + +fn indirection() -> bool { + return true; +} + +fn main() -> u16 { + let mut test = 5; + + if indirection() { + test = 11; + } + + return test; +} diff --git a/reid/src/ast/mod.rs b/reid/src/ast/mod.rs index 57772e7..b806347 100644 --- a/reid/src/ast/mod.rs +++ b/reid/src/ast/mod.rs @@ -92,7 +92,14 @@ pub struct IfExpression( ); #[derive(Debug, Clone)] -pub struct LetStatement(pub String, pub Option, pub Expression, pub TokenRange); +pub struct LetStatement( + pub String, + pub Option, + /// Mutability + pub bool, + pub Expression, + pub TokenRange, +); #[derive(Debug, Clone)] pub struct ImportStatement(pub Vec, pub TokenRange); @@ -125,7 +132,11 @@ pub struct Block( #[derive(Debug, Clone)] pub enum BlockLevelStatement { Let(LetStatement), - Import { _i: ImportStatement }, + /// Try to set a variable to a specified expression value + Set(String, Expression), + Import { + _i: ImportStatement, + }, Expression(Expression), Return(ReturnType, Expression), } diff --git a/reid/src/ast/parse.rs b/reid/src/ast/parse.rs index a78c951..d0fb3e8 100644 --- a/reid/src/ast/parse.rs +++ b/reid/src/ast/parse.rs @@ -223,6 +223,7 @@ impl Parse for IfExpression { impl Parse for LetStatement { fn parse(mut stream: TokenStream) -> Result { stream.expect(Token::LetKeyword)?; + let mutability = stream.expect(Token::MutKeyword).is_ok(); if let Some(Token::Identifier(variable)) = stream.next() { stream.expect(Token::Equals)?; @@ -232,6 +233,7 @@ impl Parse for LetStatement { Ok(LetStatement( variable, None, // TODO add possibility to name type + mutability, expression, stream.get_range().unwrap(), )) @@ -331,7 +333,7 @@ impl Parse for Block { ReturnType::Hard => { return_stmt = Some((*r_type, e.clone())); break; // Return has to be the last statement - // TODO: Make a mechanism that "can" parse even after this + // TODO: Make a mechanism that "can" parse even after this } ReturnType::Soft => { return_stmt = Some((*r_type, e.clone())); @@ -361,20 +363,40 @@ impl Parse for BlockLevelStatement { Stmt::Return(ReturnType::Hard, exp) } _ => { - if let Ok(e) = stream.parse() { - if stream.expect(Token::Semi).is_ok() { - Stmt::Expression(e) - } else { - Stmt::Return(ReturnType::Soft, e) - } + if let Ok(SetStatement(ident, expr)) = stream.parse() { + Stmt::Set(ident, expr) } else { - Err(stream.expected_err("expression")?)? + if let Ok(e) = stream.parse() { + if stream.expect(Token::Semi).is_ok() { + Stmt::Expression(e) + } else { + Stmt::Return(ReturnType::Soft, e) + } + } else { + Err(stream.expected_err("expression")?)? + } } } }) } } +#[derive(Debug)] +pub struct SetStatement(String, Expression); + +impl Parse for SetStatement { + fn parse(mut stream: TokenStream) -> Result { + if let Some(Token::Identifier(ident)) = stream.next() { + stream.expect(Token::Equals)?; + let expr = stream.parse()?; + stream.expect(Token::Semi)?; + Ok(Self(ident, expr)) + } else { + Err(stream.expected_err("identifier")?)? + } + } +} + impl Parse for TopLevelStatement { fn parse(mut stream: TokenStream) -> Result { use TopLevelStatement as Stmt; diff --git a/reid/src/ast/process.rs b/reid/src/ast/process.rs index 0005244..8b9a08b 100644 --- a/reid/src/ast/process.rs +++ b/reid/src/ast/process.rs @@ -68,12 +68,13 @@ impl ast::Block { .map(|t| t.0.into()) .unwrap_or(mir::TypeKind::Vague(mir::VagueType::Unknown)), s_let.0.clone(), - s_let.3.into(), + s_let.4.into(), ), - s_let.2.process(), + s_let.3.process(), ), - s_let.3, + s_let.4, ), + ast::BlockLevelStatement::Set(_, expression) => todo!(), ast::BlockLevelStatement::Import { _i } => todo!(), ast::BlockLevelStatement::Expression(e) => (StmtKind::Expression(e.process()), e.1), ast::BlockLevelStatement::Return(_, e) => (StmtKind::Expression(e.process()), e.1), diff --git a/reid/src/lexer.rs b/reid/src/lexer.rs index 689e3ba..32238e4 100644 --- a/reid/src/lexer.rs +++ b/reid/src/lexer.rs @@ -12,6 +12,8 @@ pub enum Token { // Keywords /// `let` LetKeyword, + /// `mut` + MutKeyword, /// `import` ImportKeyword, /// `return` @@ -170,6 +172,7 @@ pub fn tokenize>(to_tokenize: T) -> Result, Error // Check for keywords let variant = match value.as_str() { "let" => Token::LetKeyword, + "mut" => Token::MutKeyword, "import" => Token::ImportKeyword, "return" => Token::ReturnKeyword, "fn" => Token::FnKeyword,