cl-ast: Unify break, return, and unary expressions

This commit is contained in:
John 2024-07-30 20:16:07 -05:00
parent 0e545077c6
commit adb0fd229c
8 changed files with 15 additions and 123 deletions

View File

@ -398,10 +398,6 @@ pub enum ExprKind {
If(If), If(If),
/// A [For] expression: `for` Pattern `in` [`Expr`] [`Block`] [`Else`]? /// A [For] expression: `for` Pattern `in` [`Expr`] [`Block`] [`Else`]?
For(For), For(For),
/// A [Break] expression: `break` [`Expr`]?
Break(Break),
/// A [Return] expression `return` [`Expr`]?
Return(Return),
/// A continue expression: `continue` /// A continue expression: `continue`
Continue, Continue,
} }
@ -482,6 +478,8 @@ pub enum UnaryKind {
Not, Not,
/// A Loop expression: `loop` [`Block`] /// A Loop expression: `loop` [`Block`]
Loop, Loop,
Break,
Return,
/// Unused /// Unused
At, At,
/// Unused /// Unused
@ -600,15 +598,3 @@ pub struct For {
pub struct Else { pub struct Else {
pub body: Option<Box<Expr>>, pub body: Option<Box<Expr>>,
} }
/// A [Break] expression: `break` [`Expr`]?
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct Break {
pub body: Option<Box<Expr>>,
}
/// A [Return] expression `return` [`Expr`]?
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct Return {
pub body: Option<Box<Expr>>,
}

View File

@ -451,8 +451,6 @@ mod display {
ExprKind::While(v) => v.fmt(f), ExprKind::While(v) => v.fmt(f),
ExprKind::If(v) => v.fmt(f), ExprKind::If(v) => v.fmt(f),
ExprKind::For(v) => v.fmt(f), ExprKind::For(v) => v.fmt(f),
ExprKind::Break(v) => v.fmt(f),
ExprKind::Return(v) => v.fmt(f),
ExprKind::Continue => "continue".fmt(f), ExprKind::Continue => "continue".fmt(f),
} }
} }
@ -542,6 +540,8 @@ mod display {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self { match self {
UnaryKind::Loop => "loop ", UnaryKind::Loop => "loop ",
UnaryKind::Break => "break ",
UnaryKind::Return => "return ",
UnaryKind::Deref => "*", UnaryKind::Deref => "*",
UnaryKind::Neg => "-", UnaryKind::Neg => "-",
UnaryKind::Not => "!", UnaryKind::Not => "!",
@ -673,26 +673,6 @@ mod display {
} }
} }
} }
impl Display for Break {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "break")?;
match &self.body {
Some(body) => write!(f, " {body}"),
_ => Ok(()),
}
}
}
impl Display for Return {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "return")?;
match &self.body {
Some(body) => write!(f, " {body}"),
_ => Ok(()),
}
}
}
} }
mod convert { mod convert {
@ -776,8 +756,6 @@ mod convert {
While => ExprKind::While, While => ExprKind::While,
If => ExprKind::If, If => ExprKind::If,
For => ExprKind::For, For => ExprKind::For,
Break => ExprKind::Break,
Return => ExprKind::Return,
} }
impl From for Literal { impl From for Literal {
bool => Literal::Bool, bool => Literal::Bool,

View File

@ -368,14 +368,6 @@ pub trait Fold {
let Else { body } = e; let Else { body } = e;
Else { body: body.map(|e| Box::new(self.fold_expr(*e))) } Else { body: body.map(|e| Box::new(self.fold_expr(*e))) }
} }
fn fold_break(&mut self, b: Break) -> Break {
let Break { body } = b;
Break { body: body.map(|e| Box::new(self.fold_expr(*e))) }
}
fn fold_return(&mut self, r: Return) -> Return {
let Return { body } = r;
Return { body: body.map(|e| Box::new(self.fold_expr(*e))) }
}
} }
#[inline] #[inline]
@ -547,8 +539,6 @@ pub fn or_fold_expr_kind<F: Fold + ?Sized>(folder: &mut F, kind: ExprKind) -> Ex
ExprKind::While(w) => ExprKind::While(folder.fold_while(w)), ExprKind::While(w) => ExprKind::While(folder.fold_while(w)),
ExprKind::If(i) => ExprKind::If(folder.fold_if(i)), ExprKind::If(i) => ExprKind::If(folder.fold_if(i)),
ExprKind::For(f) => ExprKind::For(folder.fold_for(f)), ExprKind::For(f) => ExprKind::For(folder.fold_for(f)),
ExprKind::Break(b) => ExprKind::Break(folder.fold_break(b)),
ExprKind::Return(r) => ExprKind::Return(folder.fold_return(r)),
ExprKind::Continue => ExprKind::Continue, ExprKind::Continue => ExprKind::Continue,
} }
} }

View File

@ -322,18 +322,6 @@ pub trait Visit<'a>: Sized {
self.visit_expr(body) self.visit_expr(body)
} }
} }
fn visit_break(&mut self, b: &'a Break) {
let Break { body } = b;
if let Some(body) = body {
self.visit_expr(body)
}
}
fn visit_return(&mut self, r: &'a Return) {
let Return { body } = r;
if let Some(body) = body {
self.visit_expr(body)
}
}
fn visit_continue(&mut self) {} fn visit_continue(&mut self) {}
} }
@ -473,8 +461,6 @@ pub fn or_visit_expr_kind<'a, V: Visit<'a>>(visitor: &mut V, e: &'a ExprKind) {
ExprKind::While(w) => visitor.visit_while(w), ExprKind::While(w) => visitor.visit_while(w),
ExprKind::If(i) => visitor.visit_if(i), ExprKind::If(i) => visitor.visit_if(i),
ExprKind::For(f) => visitor.visit_for(f), ExprKind::For(f) => visitor.visit_for(f),
ExprKind::Break(b) => visitor.visit_break(b),
ExprKind::Return(r) => visitor.visit_return(r),
ExprKind::Continue => visitor.visit_continue(), ExprKind::Continue => visitor.visit_continue(),
} }
} }

View File

@ -21,9 +21,12 @@ fn desugar_while(extents: Span, kind: ExprKind) -> ExprKind {
match kind { match kind {
// work backwards: fail -> break -> if -> loop // work backwards: fail -> break -> if -> loop
ExprKind::While(While { cond, pass, fail: Else { body } }) => { ExprKind::While(While { cond, pass, fail: Else { body } }) => {
let Expr { extents, kind } = body
.map(|b| *b)
.unwrap_or(Expr { extents, kind: ExprKind::Empty });
// Preserve the else-expression's extents, if present, or use the parent's extents // Preserve the else-expression's extents, if present, or use the parent's extents
let fail_span = body.as_ref().map(|body| body.extents).unwrap_or(extents); let kind = ExprKind::Unary(Unary { kind: UnaryKind::Break, tail: kind.into() });
let break_expr = Expr { extents: fail_span, kind: ExprKind::Break(Break { body }) }; let break_expr = Expr { extents, kind };
let loop_body = If { cond, pass, fail: Else { body: Some(Box::new(break_expr)) } }; let loop_body = If { cond, pass, fail: Else { body: Some(Box::new(break_expr)) } };
let loop_body = ExprKind::If(loop_body); let loop_body = ExprKind::If(loop_body);

View File

@ -154,8 +154,6 @@ impl Interpret for ExprKind {
ExprKind::While(v) => v.interpret(env), ExprKind::While(v) => v.interpret(env),
ExprKind::If(v) => v.interpret(env), ExprKind::If(v) => v.interpret(env),
ExprKind::For(v) => v.interpret(env), ExprKind::For(v) => v.interpret(env),
ExprKind::Break(v) => v.interpret(env),
ExprKind::Return(v) => v.interpret(env),
ExprKind::Continue => Err(Error::Continue), ExprKind::Continue => Err(Error::Continue),
} }
} }
@ -330,6 +328,8 @@ impl Interpret for Unary {
e => e?, e => e?,
}; };
}, },
UnaryKind::Break => Err(Error::Break(tail.interpret(env)?)),
UnaryKind::Return => Err(Error::Return(tail.interpret(env)?)),
UnaryKind::Deref => { UnaryKind::Deref => {
let operand = tail.interpret(env)?; let operand = tail.interpret(env)?;
env.call("deref".into(), &[operand]) env.call("deref".into(), &[operand])
@ -579,23 +579,3 @@ impl Interpret for Else {
} }
} }
} }
impl Interpret for Return {
fn interpret(&self, env: &mut Environment) -> IResult<ConValue> {
let Self { body } = self;
Err(Error::Return(
body.as_ref()
.map(|body| body.interpret(env))
.unwrap_or(Ok(ConValue::Empty))?,
))
}
}
impl Interpret for Break {
fn interpret(&self, env: &mut Environment) -> IResult<ConValue> {
let Self { body } = self;
Err(Error::Break(
body.as_ref()
.map(|body| body.interpret(env))
.unwrap_or(Ok(ConValue::Empty))?,
))
}
}

View File

@ -836,6 +836,7 @@ impl<'t> Parser<'t> {
let parsing = Parsing::ExprKind; let parsing = Parsing::ExprKind;
// Prefix expressions // Prefix expressions
let mut head = match self.peek_kind(Parsing::Unary)? { let mut head = match self.peek_kind(Parsing::Unary)? {
TokenKind::Semi => return Ok(ExprKind::Empty), // TODO: is this okay?
literal_like!() => self.literal()?.into(), literal_like!() => self.literal()?.into(),
path_like!() => self.exprkind_pathlike()?, path_like!() => self.exprkind_pathlike()?,
TokenKind::Amp | TokenKind::AmpAmp => self.addrof()?.into(), TokenKind::Amp | TokenKind::AmpAmp => self.addrof()?.into(),
@ -846,8 +847,6 @@ impl<'t> Parser<'t> {
TokenKind::While => ExprKind::While(self.parse_while()?), TokenKind::While => ExprKind::While(self.parse_while()?),
TokenKind::If => ExprKind::If(self.parse_if()?), TokenKind::If => ExprKind::If(self.parse_if()?),
TokenKind::For => ExprKind::For(self.parse_for()?), TokenKind::For => ExprKind::For(self.parse_for()?),
TokenKind::Break => ExprKind::Break(self.parse_break()?),
TokenKind::Return => ExprKind::Return(self.parse_return()?),
TokenKind::Continue => { TokenKind::Continue => {
self.consume_peeked(); self.consume_peeked();
ExprKind::Continue ExprKind::Continue
@ -1159,24 +1158,6 @@ impl<'t> Parser<'t> {
} }
/// ## Control flow subexpressions /// ## Control flow subexpressions
impl<'t> Parser<'t> { impl<'t> Parser<'t> {
/// [Break] = `break` (*unconsumed* `;` | [Expr])
pub fn parse_break(&mut self) -> PResult<Break> {
self.consume_peeked();
Ok(Break { body: self.ret_body(Parsing::Break)? })
}
/// [Return] = `return` (*unconsumed* `;` | [Expr])
pub fn parse_return(&mut self) -> PResult<Return> {
self.consume_peeked();
Ok(Return { body: self.ret_body(Parsing::Return)? })
}
/// ret_body = (*unconsumed* `;` | [Expr])
fn ret_body(&mut self, while_parsing: Parsing) -> PResult<Option<Box<Expr>>> {
Ok(match self.peek_kind(while_parsing)? {
TokenKind::Semi => None,
_ => Some(self.expr()?.into()),
})
}
/// [While] = `while` [Expr] [Block] [Else]? /// [While] = `while` [Expr] [Block] [Else]?
pub fn parse_while(&mut self) -> PResult<While> { pub fn parse_while(&mut self) -> PResult<While> {
self.consume_peeked(); self.consume_peeked();
@ -1291,7 +1272,7 @@ impl From<UnaryKind> for Precedence {
fn from(value: UnaryKind) -> Self { fn from(value: UnaryKind) -> Self {
use UnaryKind as Op; use UnaryKind as Op;
match value { match value {
Op::Loop => Precedence::Assign, Op::Loop | Op::Break | Op::Return => Precedence::Assign,
Op::Deref | Op::Neg | Op::Not | Op::At | Op::Tilde => Precedence::Unary, Op::Deref | Op::Neg | Op::Not | Op::At | Op::Tilde => Precedence::Unary,
} }
} }
@ -1310,6 +1291,8 @@ macro operator($($name:ident ($takes:ident => $returns:ident) {$($t:ident => $p:
operator! { operator! {
from_prefix (TokenKind => UnaryKind) { from_prefix (TokenKind => UnaryKind) {
Loop => Loop, Loop => Loop,
Break => Break,
Return => Return,
Star => Deref, Star => Deref,
Minus => Neg, Minus => Neg,
Bang => Not, Bang => Not,

View File

@ -409,8 +409,6 @@ pub mod yamlify {
ExprKind::While(k) => k.yaml(y), ExprKind::While(k) => k.yaml(y),
ExprKind::If(k) => k.yaml(y), ExprKind::If(k) => k.yaml(y),
ExprKind::For(k) => k.yaml(y), ExprKind::For(k) => k.yaml(y),
ExprKind::Break(k) => k.yaml(y),
ExprKind::Return(k) => k.yaml(y),
ExprKind::Continue => { ExprKind::Continue => {
y.key("Continue"); y.key("Continue");
} }
@ -569,18 +567,6 @@ pub mod yamlify {
.yaml(fail); .yaml(fail);
} }
} }
impl Yamlify for Break {
fn yaml(&self, y: &mut Yamler) {
let Self { body } = self;
y.key("Break").yaml(body);
}
}
impl Yamlify for Return {
fn yaml(&self, y: &mut Yamler) {
let Self { body } = self;
y.key("Return").yaml(body);
}
}
impl Yamlify for Literal { impl Yamlify for Literal {
fn yaml(&self, y: &mut Yamler) { fn yaml(&self, y: &mut Yamler) {
y.value(format_args!("\"{self}\"")); y.value(format_args!("\"{self}\""));