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:
@@ -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)))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user