From a3b37ae6032a1cac9794f35ca1c264cb8199cf88 Mon Sep 17 00:00:00 2001 From: Huzaifa Raghav Date: Thu, 11 Apr 2024 23:59:36 +0800 Subject: [PATCH] Add if-else data (WIP) --- compiler/oxidate/src/compiler.rs | 1 + src/parser/src/if_else.rs | 39 +++++++++++++++++++++++++++++--- src/parser/src/seq.rs | 2 +- src/parser/src/structs.rs | 30 ++++++++++++++++++++++++ src/types/src/type_checker.rs | 1 + 5 files changed, 69 insertions(+), 4 deletions(-) diff --git a/compiler/oxidate/src/compiler.rs b/compiler/oxidate/src/compiler.rs index e7f2a1c..f1c12d7 100644 --- a/compiler/oxidate/src/compiler.rs +++ b/compiler/oxidate/src/compiler.rs @@ -86,6 +86,7 @@ impl Compiler { Expr::BlockExpr(blk) => { Compiler::compile_block(blk, arr)?; } + _ => todo!(), } Ok(()) diff --git a/src/parser/src/if_else.rs b/src/parser/src/if_else.rs index 944f901..7e9e8df 100644 --- a/src/parser/src/if_else.rs +++ b/src/parser/src/if_else.rs @@ -1,6 +1,7 @@ use crate::Decl; // use crate::Decl::*; use crate::Expr; +use crate::IfElseData; use crate::ParseError; use crate::Parser; // use crate::{BinOpType, UnOpType}; @@ -15,11 +16,33 @@ impl<'inp> Parser<'inp> { self.consume_token_type(Token::OpenParen, "Expected open parenthesis")?; dbg!("OK", &self.prev_tok); - let cond = self.parse_expr(min_bp); + let cond = self.parse_expr(min_bp)?.to_expr()?; dbg!(&cond); // got cond dbg!("peek after:", &self.lexer.peek()); // OpenBrace - Ok(Decl::ExprStmt(Expr::Bool(true))) + + // go past OpenBrace, put in prev_tok + self.consume_token_type( + Token::OpenBrace, + &format!("Expected {} for if block", Token::OpenBrace), + )?; + + let if_blk = self.parse_blk(min_bp)?.to_block()?; + + dbg!("after parse_blk", &if_blk); + + dbg!("peek after parse_blk", &self.lexer.peek()); + + let stmt = IfElseData { + cond, + if_blk, + else_blk: None, + }; + + let expr = Expr::IfElseExpr(Box::new(stmt)); + + // parse else blk if avail + Ok(Decl::ExprStmt(expr)) } } @@ -31,9 +54,19 @@ mod tests { fn parse_if_basic() { let t = r" if (true) { - + 30; + 40; } "; // test_parse(t, ""); + + // let t = r" + // if (true) { + // 30; + // } else { + // 40; + // } + // "; + // test_parse(t, ""); } } diff --git a/src/parser/src/seq.rs b/src/parser/src/seq.rs index 45021b8..664d2b7 100644 --- a/src/parser/src/seq.rs +++ b/src/parser/src/seq.rs @@ -22,7 +22,7 @@ impl<'inp> Parser<'inp> { // dbg!("prev_tok:", &self.prev_tok); let expr = self.parse_decl()?; - // dbg!("Got expr:", &expr); + dbg!("Got expr:", &expr); // dbg!("Peek:", &self.lexer.peek()); // end of block: lexer empty OR curly brace (TODO add curly later) diff --git a/src/parser/src/structs.rs b/src/parser/src/structs.rs index 0865443..101e206 100644 --- a/src/parser/src/structs.rs +++ b/src/parser/src/structs.rs @@ -65,6 +65,7 @@ pub enum Expr { UnOpExpr(UnOpType, Box), BinOpExpr(BinOpType, Box, Box), BlockExpr(BlockSeq), // expr can be a block + IfElseExpr(Box), } impl Display for Expr { @@ -81,6 +82,8 @@ impl Display for Expr { } Expr::Symbol(val) => val.to_string(), Expr::BlockExpr(seq) => format!("{{ {} }}", seq), + // Expr::BlockExpr(seq) => seq.to_string(), + Expr::IfElseExpr(expr) => expr.to_string(), }; write!(f, "{}", string) @@ -118,6 +121,24 @@ impl Display for AssignStmt { } } +#[derive(Debug, Clone)] +pub struct IfElseData { + pub cond: Expr, + pub if_blk: BlockSeq, + pub else_blk: Option, +} + +impl Display for IfElseData { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + let mut s = format!("if {} {}", self.cond, self.if_blk); + if let Some(ref else_blk) = self.else_blk { + s.push(' '); + s.push_str(&format!("else {}", else_blk)); + } + + write!(f, "{}", s) + } +} // Later: LetStmt, IfStmt, FnDef, etc. #[derive(Debug, Clone)] pub enum Decl { @@ -140,6 +161,15 @@ impl Decl { Self::ExprStmt(expr) => Ok(expr.clone()), } } + + pub fn to_block(&self) -> Result { + if let Self::ExprStmt(Expr::BlockExpr(seq)) = &self { + return Ok(seq.clone()); + } + + let e = format!("Expected block but got '{}'", self); + Err(ParseError::new(&e)) + } } impl Display for Decl { diff --git a/src/types/src/type_checker.rs b/src/types/src/type_checker.rs index 3cea2f5..fcafd8a 100644 --- a/src/types/src/type_checker.rs +++ b/src/types/src/type_checker.rs @@ -184,6 +184,7 @@ impl<'prog> TypeChecker<'prog> { return self.check_binop(op, lhs, rhs); } Expr::BlockExpr(blk) => self.check_block(blk)?, + _ => todo!(), }; if local_errs.is_ok() {