Implement do yeet expression

This commit is contained in:
Maybe Waffle 2022-12-28 23:17:13 +00:00
parent 4a16afa264
commit 346bf5fb5b
9 changed files with 72 additions and 4 deletions

View File

@ -371,6 +371,10 @@ impl ExprCollector<'_> {
let expr = e.expr().map(|e| self.collect_expr(e)); let expr = e.expr().map(|e| self.collect_expr(e));
self.alloc_expr(Expr::Yield { expr }, syntax_ptr) self.alloc_expr(Expr::Yield { expr }, syntax_ptr)
} }
ast::Expr::YeetExpr(e) => {
let expr = e.expr().map(|e| self.collect_expr(e));
self.alloc_expr(Expr::Yeet { expr }, syntax_ptr)
}
ast::Expr::RecordExpr(e) => { ast::Expr::RecordExpr(e) => {
let path = let path =
e.path().and_then(|path| self.expander.parse_path(self.db, path)).map(Box::new); e.path().and_then(|path| self.expander.parse_path(self.db, path)).map(Box::new);

View File

@ -247,6 +247,15 @@ impl<'a> Printer<'a> {
self.print_expr(*expr); self.print_expr(*expr);
} }
} }
Expr::Yeet { expr } => {
w!(self, "do");
self.whitespace();
w!(self, "yeet");
if let Some(expr) = expr {
self.whitespace();
self.print_expr(*expr);
}
}
Expr::RecordLit { path, fields, spread, ellipsis, is_assignee_expr: _ } => { Expr::RecordLit { path, fields, spread, ellipsis, is_assignee_expr: _ } => {
match path { match path {
Some(path) => self.print_path(path), Some(path) => self.print_path(path),

View File

@ -137,6 +137,9 @@ pub enum Expr {
Yield { Yield {
expr: Option<ExprId>, expr: Option<ExprId>,
}, },
Yeet {
expr: Option<ExprId>,
},
RecordLit { RecordLit {
path: Option<Box<Path>>, path: Option<Box<Path>>,
fields: Box<[RecordLitField]>, fields: Box<[RecordLitField]>,
@ -313,7 +316,10 @@ impl Expr {
arms.iter().map(|arm| arm.expr).for_each(f); arms.iter().map(|arm| arm.expr).for_each(f);
} }
Expr::Continue { .. } => {} Expr::Continue { .. } => {}
Expr::Break { expr, .. } | Expr::Return { expr } | Expr::Yield { expr } => { Expr::Break { expr, .. }
| Expr::Return { expr }
| Expr::Yield { expr }
| Expr::Yeet { expr } => {
if let &Some(expr) = expr { if let &Some(expr) = expr {
f(expr); f(expr);
} }

View File

@ -465,6 +465,12 @@ impl<'a> InferenceContext<'a> {
TyKind::Error.intern(Interner) TyKind::Error.intern(Interner)
} }
} }
Expr::Yeet { expr } => {
if let &Some(expr) = expr {
self.infer_expr_inner(expr, &Expectation::None);
}
TyKind::Never.intern(Interner)
}
Expr::RecordLit { path, fields, spread, .. } => { Expr::RecordLit { path, fields, spread, .. } => {
let (ty, def_id) = self.resolve_variant(path.as_deref(), false); let (ty, def_id) = self.resolve_variant(path.as_deref(), false);
if let Some(variant) = def_id { if let Some(variant) = def_id {

View File

@ -328,7 +328,8 @@ pub fn for_each_tail_expr(expr: &ast::Expr, cb: &mut dyn FnMut(&ast::Expr)) {
| ast::Expr::WhileExpr(_) | ast::Expr::WhileExpr(_)
| ast::Expr::LetExpr(_) | ast::Expr::LetExpr(_)
| ast::Expr::UnderscoreExpr(_) | ast::Expr::UnderscoreExpr(_)
| ast::Expr::YieldExpr(_) => cb(expr), | ast::Expr::YieldExpr(_)
| ast::Expr::YeetExpr(_) => cb(expr),
} }
} }

View File

@ -174,6 +174,7 @@ fn keyword(
| T![return] | T![return]
| T![while] | T![while]
| T![yield] => h | HlMod::ControlFlow, | T![yield] => h | HlMod::ControlFlow,
T![do] | T![yeet] if parent_matches::<ast::YeetExpr>(&token) => h | HlMod::ControlFlow,
T![for] if parent_matches::<ast::ForExpr>(&token) => h | HlMod::ControlFlow, T![for] if parent_matches::<ast::ForExpr>(&token) => h | HlMod::ControlFlow,
T![unsafe] => h | HlMod::Unsafe, T![unsafe] => h | HlMod::Unsafe,
T![true] | T![false] => HlTag::BoolLiteral.into(), T![true] | T![false] => HlTag::BoolLiteral.into(),

View File

@ -359,6 +359,7 @@ Expr =
| TupleExpr | TupleExpr
| WhileExpr | WhileExpr
| YieldExpr | YieldExpr
| YeetExpr
| LetExpr | LetExpr
| UnderscoreExpr | UnderscoreExpr
@ -503,6 +504,9 @@ ReturnExpr =
YieldExpr = YieldExpr =
Attr* 'yield' Expr? Attr* 'yield' Expr?
YeetExpr =
Attr* 'do' 'yeet' Expr?
LetExpr = LetExpr =
Attr* 'let' Pat '=' Expr Attr* 'let' Pat '=' Expr

View File

@ -1063,6 +1063,17 @@ impl YieldExpr {
pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) } pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
} }
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct YeetExpr {
pub(crate) syntax: SyntaxNode,
}
impl ast::HasAttrs for YeetExpr {}
impl YeetExpr {
pub fn do_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![do]) }
pub fn yeet_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![yeet]) }
pub fn expr(&self) -> Option<Expr> { support::child(&self.syntax) }
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)] #[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct LetExpr { pub struct LetExpr {
pub(crate) syntax: SyntaxNode, pub(crate) syntax: SyntaxNode,
@ -1541,6 +1552,7 @@ pub enum Expr {
TupleExpr(TupleExpr), TupleExpr(TupleExpr),
WhileExpr(WhileExpr), WhileExpr(WhileExpr),
YieldExpr(YieldExpr), YieldExpr(YieldExpr),
YeetExpr(YeetExpr),
LetExpr(LetExpr), LetExpr(LetExpr),
UnderscoreExpr(UnderscoreExpr), UnderscoreExpr(UnderscoreExpr),
} }
@ -2694,6 +2706,17 @@ impl AstNode for YieldExpr {
} }
fn syntax(&self) -> &SyntaxNode { &self.syntax } fn syntax(&self) -> &SyntaxNode { &self.syntax }
} }
impl AstNode for YeetExpr {
fn can_cast(kind: SyntaxKind) -> bool { kind == YEET_EXPR }
fn cast(syntax: SyntaxNode) -> Option<Self> {
if Self::can_cast(syntax.kind()) {
Some(Self { syntax })
} else {
None
}
}
fn syntax(&self) -> &SyntaxNode { &self.syntax }
}
impl AstNode for LetExpr { impl AstNode for LetExpr {
fn can_cast(kind: SyntaxKind) -> bool { kind == LET_EXPR } fn can_cast(kind: SyntaxKind) -> bool { kind == LET_EXPR }
fn cast(syntax: SyntaxNode) -> Option<Self> { fn cast(syntax: SyntaxNode) -> Option<Self> {
@ -3382,6 +3405,9 @@ impl From<WhileExpr> for Expr {
impl From<YieldExpr> for Expr { impl From<YieldExpr> for Expr {
fn from(node: YieldExpr) -> Expr { Expr::YieldExpr(node) } fn from(node: YieldExpr) -> Expr { Expr::YieldExpr(node) }
} }
impl From<YeetExpr> for Expr {
fn from(node: YeetExpr) -> Expr { Expr::YeetExpr(node) }
}
impl From<LetExpr> for Expr { impl From<LetExpr> for Expr {
fn from(node: LetExpr) -> Expr { Expr::LetExpr(node) } fn from(node: LetExpr) -> Expr { Expr::LetExpr(node) }
} }
@ -3422,6 +3448,7 @@ impl AstNode for Expr {
| TUPLE_EXPR | TUPLE_EXPR
| WHILE_EXPR | WHILE_EXPR
| YIELD_EXPR | YIELD_EXPR
| YEET_EXPR
| LET_EXPR | LET_EXPR
| UNDERSCORE_EXPR | UNDERSCORE_EXPR
) )
@ -3458,6 +3485,7 @@ impl AstNode for Expr {
TUPLE_EXPR => Expr::TupleExpr(TupleExpr { syntax }), TUPLE_EXPR => Expr::TupleExpr(TupleExpr { syntax }),
WHILE_EXPR => Expr::WhileExpr(WhileExpr { syntax }), WHILE_EXPR => Expr::WhileExpr(WhileExpr { syntax }),
YIELD_EXPR => Expr::YieldExpr(YieldExpr { syntax }), YIELD_EXPR => Expr::YieldExpr(YieldExpr { syntax }),
YEET_EXPR => Expr::YeetExpr(YeetExpr { syntax }),
LET_EXPR => Expr::LetExpr(LetExpr { syntax }), LET_EXPR => Expr::LetExpr(LetExpr { syntax }),
UNDERSCORE_EXPR => Expr::UnderscoreExpr(UnderscoreExpr { syntax }), UNDERSCORE_EXPR => Expr::UnderscoreExpr(UnderscoreExpr { syntax }),
_ => return None, _ => return None,
@ -3496,6 +3524,7 @@ impl AstNode for Expr {
Expr::TupleExpr(it) => &it.syntax, Expr::TupleExpr(it) => &it.syntax,
Expr::WhileExpr(it) => &it.syntax, Expr::WhileExpr(it) => &it.syntax,
Expr::YieldExpr(it) => &it.syntax, Expr::YieldExpr(it) => &it.syntax,
Expr::YeetExpr(it) => &it.syntax,
Expr::LetExpr(it) => &it.syntax, Expr::LetExpr(it) => &it.syntax,
Expr::UnderscoreExpr(it) => &it.syntax, Expr::UnderscoreExpr(it) => &it.syntax,
} }
@ -3963,6 +3992,7 @@ impl AstNode for AnyHasAttrs {
| TUPLE_EXPR | TUPLE_EXPR
| WHILE_EXPR | WHILE_EXPR
| YIELD_EXPR | YIELD_EXPR
| YEET_EXPR
| LET_EXPR | LET_EXPR
| UNDERSCORE_EXPR | UNDERSCORE_EXPR
| STMT_LIST | STMT_LIST
@ -4655,6 +4685,11 @@ impl std::fmt::Display for YieldExpr {
std::fmt::Display::fmt(self.syntax(), f) std::fmt::Display::fmt(self.syntax(), f)
} }
} }
impl std::fmt::Display for YeetExpr {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Display::fmt(self.syntax(), f)
}
}
impl std::fmt::Display for LetExpr { impl std::fmt::Display for LetExpr {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
std::fmt::Display::fmt(self.syntax(), f) std::fmt::Display::fmt(self.syntax(), f)

View File

@ -130,7 +130,7 @@ impl Expr {
// //
ContinueExpr(_) => (0, 0), ContinueExpr(_) => (0, 0),
ClosureExpr(_) | ReturnExpr(_) | YieldExpr(_) | BreakExpr(_) => (0, 1), ClosureExpr(_) | ReturnExpr(_) | YieldExpr(_) | YeetExpr(_) | BreakExpr(_) => (0, 1),
RangeExpr(_) => (5, 5), RangeExpr(_) => (5, 5),
@ -291,6 +291,7 @@ impl Expr {
ReturnExpr(e) => e.return_token(), ReturnExpr(e) => e.return_token(),
TryExpr(e) => e.question_mark_token(), TryExpr(e) => e.question_mark_token(),
YieldExpr(e) => e.yield_token(), YieldExpr(e) => e.yield_token(),
YeetExpr(e) => e.do_token(),
LetExpr(e) => e.let_token(), LetExpr(e) => e.let_token(),
ArrayExpr(_) | TupleExpr(_) | Literal(_) | PathExpr(_) | ParenExpr(_) ArrayExpr(_) | TupleExpr(_) | Literal(_) | PathExpr(_) | ParenExpr(_)
@ -313,7 +314,8 @@ impl Expr {
// For BinExpr and RangeExpr this is technically wrong -- the child can be on the left... // For BinExpr and RangeExpr this is technically wrong -- the child can be on the left...
BinExpr(_) | RangeExpr(_) | BoxExpr(_) | BreakExpr(_) | ContinueExpr(_) BinExpr(_) | RangeExpr(_) | BoxExpr(_) | BreakExpr(_) | ContinueExpr(_)
| PrefixExpr(_) | RefExpr(_) | ReturnExpr(_) | YieldExpr(_) | LetExpr(_) => self | PrefixExpr(_) | RefExpr(_) | ReturnExpr(_) | YieldExpr(_) | YeetExpr(_)
| LetExpr(_) => self
.syntax() .syntax()
.parent() .parent()
.and_then(Expr::cast) .and_then(Expr::cast)