Revert "cl-ast: Unify break
, return
, and unary
expressions"
This reverts commit adb0fd229c
.
This commit is contained in:
parent
5e7ba6de24
commit
388a69948e
@ -398,6 +398,10 @@ 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,
|
||||||
}
|
}
|
||||||
@ -478,8 +482,6 @@ 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
|
||||||
@ -598,3 +600,15 @@ 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>>,
|
||||||
|
}
|
||||||
|
@ -451,6 +451,8 @@ 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),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -540,8 +542,6 @@ 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 => "!",
|
||||||
@ -684,6 +684,26 @@ 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 {
|
||||||
@ -767,6 +787,8 @@ 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,
|
||||||
|
@ -368,6 +368,14 @@ 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]
|
||||||
@ -539,6 +547,8 @@ 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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -322,6 +322,18 @@ 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) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -461,6 +473,8 @@ 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(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,12 +21,9 @@ 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 kind = ExprKind::Unary(Unary { kind: UnaryKind::Break, tail: kind.into() });
|
let fail_span = body.as_ref().map(|body| body.extents).unwrap_or(extents);
|
||||||
let break_expr = Expr { extents, kind };
|
let break_expr = Expr { extents: fail_span, kind: ExprKind::Break(Break { body }) };
|
||||||
|
|
||||||
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);
|
||||||
|
@ -154,6 +154,8 @@ 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),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -328,8 +330,6 @@ 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,3 +579,23 @@ 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))?,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -836,7 +836,6 @@ 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(),
|
||||||
@ -847,6 +846,8 @@ 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
|
||||||
@ -1158,6 +1159,24 @@ 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();
|
||||||
@ -1272,7 +1291,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 | Op::Break | Op::Return => Precedence::Assign,
|
Op::Loop => 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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1291,8 +1310,6 @@ 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,
|
||||||
|
@ -409,6 +409,8 @@ 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");
|
||||||
}
|
}
|
||||||
@ -567,6 +569,18 @@ 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}\""));
|
||||||
|
Loading…
Reference in New Issue
Block a user