Add block expressions and if expressions

If and block statements are now expressions. The last expression, if
any, is used as the return value of this expression.

Also fixed a (major) bug in the if statement generation that was causing
the wrong jump address to be generated.

Signed-off-by: Alek Ratzloff <alekratz@gmail.com>
This commit is contained in:
2024-10-21 15:39:48 -07:00
parent 7bce6f8e23
commit 46c38de20c
5 changed files with 295 additions and 194 deletions

View File

@@ -562,19 +562,8 @@ impl Parser {
fn stmt_wrapped(&mut self) -> Result<StmtP> {
if self.mat(TokenKind::Return)? {
self.return_stmt()
} else if self.mat(TokenKind::If)? {
self.if_stmt()
} else if self.mat(TokenKind::Import)? {
self.import_stmt()
} else if self.mat(TokenKind::LBrace)? {
let lbrace = self.prev.clone().unwrap();
let stmts = self.block()?;
let rbrace = self.prev.clone().unwrap();
Ok(Box::new(BlockStmt {
lbrace,
stmts,
rbrace,
}) as Box<dyn Stmt + 'static>)
} else if self.current.kind == TokenKind::Name
&& (self.next.kind == TokenKind::Eq
|| self.next.kind == TokenKind::PlusEq
@@ -657,21 +646,30 @@ impl Parser {
Ok(Box::new(ReturnStmt { return_kw, expr }))
}
fn if_stmt(&mut self) -> Result<StmtP> {
fn if_expr(&mut self) -> Result<ExprP> {
let if_kw = self.prev.clone().unwrap();
let condition = self.expr()?;
self.expect("expect '{' after 'if' condition", TokenKind::LBrace)?;
let then_branch = self.block_stmt()?;
let mut else_branch = Vec::new();
let then_branch = self.block_expr()?;
let mut else_branch = None;
if self.mat(TokenKind::Else)? {
if self.mat(TokenKind::If)? {
else_branch.push(self.if_stmt()?);
let lbrace = self.current.clone();
let if_expr = self.if_expr()?;
let rbrace = self.prev.clone().unwrap();
else_branch = Some(BlockExpr {
lbrace,
stmts: Default::default(),
return_expr: Some(if_expr),
rbrace,
});
} else {
self.expect("expect '{' after else statement", TokenKind::LBrace)?;
else_branch = self.block()?;
else_branch = Some(self.block_expr()?);
}
}
Ok(Box::new(IfStmt {
Ok(Box::new(IfExpr {
if_kw,
condition,
then_branch,
@@ -754,16 +752,28 @@ impl Parser {
Ok(Box::new(import_stmt))
}
fn block_stmt(&mut self) -> Result<BlockStmt> {
fn block_expr(&mut self) -> Result<BlockExpr> {
let lbrace = self.prev.clone().unwrap();
assert_eq!(lbrace.kind, TokenKind::LBrace);
let stmts = self.block()?;
let mut stmts = self.block()?;
let rbrace = self.prev.clone().unwrap();
assert_eq!(rbrace.kind, TokenKind::RBrace);
Ok(BlockStmt {
let return_expr = if let Some(last) = stmts.pop() {
if last.as_any_ref().downcast_ref::<ExprStmt>().is_some() {
let stmt = last.as_any().downcast::<ExprStmt>().unwrap();
Some(stmt.expr)
} else {
None
}
} else {
None
};
Ok(BlockExpr {
lbrace,
stmts,
rbrace,
return_expr,
})
}
@@ -951,6 +961,10 @@ impl Parser {
Ok(expr)
} else if self.mat(TokenKind::LBracket)? {
self.list_or_map()
} else if self.mat(TokenKind::LBrace)? {
Ok(Box::new(self.block_expr()?))
} else if self.mat(TokenKind::If)? {
self.if_expr()
} else {
Err(self.error(format!("unexpected token {:?}", self.current.kind)))
}