From 0760cfbd4983ce0832b5b496e8925867c80538dd Mon Sep 17 00:00:00 2001 From: Huzaifa Raghav Date: Thu, 18 Apr 2024 23:03:47 +0800 Subject: [PATCH] Add wait and post to parser --- compiler/oxidate/src/compiler.rs | 2 ++ src/lexer/src/lib.rs | 19 ++++++++++ src/parser/src/lib.rs | 62 +++++++++++++++++++++++++++++++- src/parser/src/structs.rs | 8 +++++ src/types/src/type_checker.rs | 10 ++++++ 5 files changed, 100 insertions(+), 1 deletion(-) diff --git a/compiler/oxidate/src/compiler.rs b/compiler/oxidate/src/compiler.rs index 4d35ba5..695eff1 100644 --- a/compiler/oxidate/src/compiler.rs +++ b/compiler/oxidate/src/compiler.rs @@ -326,6 +326,8 @@ impl Compiler { // push RESET arr.push(ByteCode::RESET(bytecode::FrameType::CallFrame)) } + Decl::WaitStmt(_) => {} + Decl::PostStmt(_) => {} }; Ok(()) diff --git a/src/lexer/src/lib.rs b/src/lexer/src/lib.rs index a48d6b6..28df9d0 100644 --- a/src/lexer/src/lib.rs +++ b/src/lexer/src/lib.rs @@ -145,6 +145,12 @@ pub enum Token { #[token("join")] Join, + #[token("wait")] + Wait, + + #[token("post")] + Post, + #[token("false", |_| false)] #[token("true", |_| true)] Bool(bool), @@ -222,6 +228,8 @@ impl Token { Self::FnDeclReturn => "->".to_string(), Self::Spawn => "spawn".to_string(), Self::Join => "join".to_string(), + Self::Wait => "wait".to_string(), + Self::Post => "post".to_string(), } } } @@ -636,4 +644,15 @@ mod test { assert_eq!(lexer.next().unwrap().unwrap(), Token::Spawn); assert_eq!(lexer.next().unwrap().unwrap(), Token::Join); } + + #[test] + fn test_lex_wait_post() { + let t = r" + wait post + "; + let mut lexer = Token::lexer(t); + + assert_eq!(lexer.next().unwrap().unwrap(), Token::Wait); + assert_eq!(lexer.next().unwrap().unwrap(), Token::Post); + } } diff --git a/src/parser/src/lib.rs b/src/parser/src/lib.rs index 59e0db0..a237a42 100644 --- a/src/parser/src/lib.rs +++ b/src/parser/src/lib.rs @@ -241,6 +241,25 @@ impl<'inp> Parser<'inp> { Err(ParseError::new("join expected variable for thread to join")) } } + // wait sem; + Token::Wait => { + self.advance(); + let sem = self.parse_expr(0)?.to_expr()?; + if let Expr::Symbol(sem_sym) = sem { + Ok(Decl::WaitStmt(sem_sym)) + } else { + Err(ParseError::new("wait expected semaphore variable")) + } + } + Token::Post => { + self.advance(); + let sem = self.parse_expr(0)?.to_expr()?; + if let Expr::Symbol(sem_sym) = sem { + Ok(Decl::PostStmt(sem_sym)) + } else { + Err(ParseError::new("post expected semaphore variable")) + } + } // if not is_loop, error Token::Break => { if !self.is_loop { @@ -397,7 +416,7 @@ mod tests { } #[test] - fn test_parse_spawn_join() { + fn test_parse_concurrency() { let t = r" let t = spawn func(); spawn f2(); @@ -416,5 +435,46 @@ mod tests { let res = join t; "; test_parse(t, "let t = spawn func();let res = join t;"); + + // wait and post + let t = r" + let sem = sem_create(); + wait sem; + post sem; + "; + test_parse(t, "let sem = sem_create();wait sem;post sem;"); + + let t = r" + wait 2+2; + "; + test_parse_err(t, "expected semaphore variable", true); + + let t = r" + post 2+2; + "; + test_parse_err(t, "expected semaphore variable", true); + + // can't assign wait/post + let t = r" + let x = wait sem; + "; + test_parse_err(t, "wait is not an expression", true); + + // can't assign wait/post + let t = r" + let x = post sem; + "; + test_parse_err(t, "post is not an expression", true); + + // must be stmt with semi + let t = r" + wait sem + "; + test_parse_err(t, "Expected semicolon", true); + + let t = r" + post sem + "; + test_parse_err(t, "Expected semicolon", true); } } diff --git a/src/parser/src/structs.rs b/src/parser/src/structs.rs index 1d1fc43..4fbe667 100644 --- a/src/parser/src/structs.rs +++ b/src/parser/src/structs.rs @@ -261,6 +261,10 @@ pub enum Decl { BreakStmt, // only inside fn ReturnStmt(Option), + // wait sem; - stmt only + WaitStmt(String), + // post sem; - stmt only + PostStmt(String), } impl Decl { @@ -284,6 +288,8 @@ impl Decl { Self::LoopStmt(_) => Err(ParseError::new("loop is not an expression")), Self::BreakStmt => Err(ParseError::new("break is not an expression")), Self::ReturnStmt(_) => Err(ParseError::new("return is not an expression")), + Self::WaitStmt(_) => Err(ParseError::new("wait is not an expression")), + Self::PostStmt(_) => Err(ParseError::new("post is not an expression")), Self::ExprStmt(expr) => Ok(expr.clone()), } } @@ -326,6 +332,8 @@ impl Display for Decl { }; format!("{}{}", Token::Return, str) } + Decl::WaitStmt(sym) => format!("wait {}", sym), + Decl::PostStmt(sym) => format!("post {}", sym), }; write!(f, "{}", string) diff --git a/src/types/src/type_checker.rs b/src/types/src/type_checker.rs index 2a5dd6b..9e75aee 100644 --- a/src/types/src/type_checker.rs +++ b/src/types/src/type_checker.rs @@ -449,6 +449,16 @@ impl<'prog> TypeChecker<'prog> { must_break: true, must_return: true, }), + Decl::WaitStmt(_) => Ok(CheckResult { + ty: Type::Unit, + must_break: false, + must_return: false, + }), + Decl::PostStmt(_) => Ok(CheckResult { + ty: Type::Unit, + must_break: false, + must_return: false, + }), } // Ok(())