diff --git a/compiler/cl-ast/src/ast.rs b/compiler/cl-ast/src/ast.rs index 1b1b3a0..c1988e0 100644 --- a/compiler/cl-ast/src/ast.rs +++ b/compiler/cl-ast/src/ast.rs @@ -398,10 +398,6 @@ pub enum ExprKind { If(If), /// A [For] expression: `for` Pattern `in` [`Expr`] [`Block`] [`Else`]? For(For), - /// A [Break] expression: `break` [`Expr`]? - Break(Break), - /// A [Return] expression `return` [`Expr`]? - Return(Return), /// A continue expression: `continue` Continue, } @@ -482,6 +478,8 @@ pub enum UnaryKind { Not, /// A Loop expression: `loop` [`Block`] Loop, + Break, + Return, /// Unused At, /// Unused @@ -600,15 +598,3 @@ pub struct For { pub struct Else { pub body: Option>, } - -/// A [Break] expression: `break` [`Expr`]? -#[derive(Clone, Debug, PartialEq, Eq, Hash)] -pub struct Break { - pub body: Option>, -} - -/// A [Return] expression `return` [`Expr`]? -#[derive(Clone, Debug, PartialEq, Eq, Hash)] -pub struct Return { - pub body: Option>, -} diff --git a/compiler/cl-ast/src/ast_impl.rs b/compiler/cl-ast/src/ast_impl.rs index 34c5964..1ba6e56 100644 --- a/compiler/cl-ast/src/ast_impl.rs +++ b/compiler/cl-ast/src/ast_impl.rs @@ -451,8 +451,6 @@ mod display { ExprKind::While(v) => v.fmt(f), ExprKind::If(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), } } @@ -542,6 +540,8 @@ mod display { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { UnaryKind::Loop => "loop ", + UnaryKind::Break => "break ", + UnaryKind::Return => "return ", UnaryKind::Deref => "*", UnaryKind::Neg => "-", 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 { @@ -776,8 +756,6 @@ mod convert { While => ExprKind::While, If => ExprKind::If, For => ExprKind::For, - Break => ExprKind::Break, - Return => ExprKind::Return, } impl From for Literal { bool => Literal::Bool, diff --git a/compiler/cl-ast/src/ast_visitor/fold.rs b/compiler/cl-ast/src/ast_visitor/fold.rs index c784348..92d3f34 100644 --- a/compiler/cl-ast/src/ast_visitor/fold.rs +++ b/compiler/cl-ast/src/ast_visitor/fold.rs @@ -368,14 +368,6 @@ pub trait Fold { let Else { body } = 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] @@ -547,8 +539,6 @@ pub fn or_fold_expr_kind(folder: &mut F, kind: ExprKind) -> Ex ExprKind::While(w) => ExprKind::While(folder.fold_while(w)), ExprKind::If(i) => ExprKind::If(folder.fold_if(i)), 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, } } diff --git a/compiler/cl-ast/src/ast_visitor/visit.rs b/compiler/cl-ast/src/ast_visitor/visit.rs index 5926cd2..7519f12 100644 --- a/compiler/cl-ast/src/ast_visitor/visit.rs +++ b/compiler/cl-ast/src/ast_visitor/visit.rs @@ -322,18 +322,6 @@ pub trait Visit<'a>: Sized { 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) {} } @@ -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::If(i) => visitor.visit_if(i), 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(), } } diff --git a/compiler/cl-ast/src/desugar/while_else.rs b/compiler/cl-ast/src/desugar/while_else.rs index 3a75f02..d9d1a12 100644 --- a/compiler/cl-ast/src/desugar/while_else.rs +++ b/compiler/cl-ast/src/desugar/while_else.rs @@ -21,9 +21,12 @@ fn desugar_while(extents: Span, kind: ExprKind) -> ExprKind { match kind { // work backwards: fail -> break -> if -> loop 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 - let fail_span = body.as_ref().map(|body| body.extents).unwrap_or(extents); - let break_expr = Expr { extents: fail_span, kind: ExprKind::Break(Break { body }) }; + let kind = ExprKind::Unary(Unary { kind: UnaryKind::Break, tail: kind.into() }); + let break_expr = Expr { extents, kind }; let loop_body = If { cond, pass, fail: Else { body: Some(Box::new(break_expr)) } }; let loop_body = ExprKind::If(loop_body); diff --git a/compiler/cl-interpret/src/interpret.rs b/compiler/cl-interpret/src/interpret.rs index a007ecb..779371a 100644 --- a/compiler/cl-interpret/src/interpret.rs +++ b/compiler/cl-interpret/src/interpret.rs @@ -154,8 +154,6 @@ impl Interpret for ExprKind { ExprKind::While(v) => v.interpret(env), ExprKind::If(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), } } @@ -330,6 +328,8 @@ impl Interpret for Unary { e => e?, }; }, + UnaryKind::Break => Err(Error::Break(tail.interpret(env)?)), + UnaryKind::Return => Err(Error::Return(tail.interpret(env)?)), UnaryKind::Deref => { let operand = tail.interpret(env)?; env.call("deref".into(), &[operand]) @@ -579,23 +579,3 @@ impl Interpret for Else { } } } -impl Interpret for Return { - fn interpret(&self, env: &mut Environment) -> IResult { - 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 { - let Self { body } = self; - Err(Error::Break( - body.as_ref() - .map(|body| body.interpret(env)) - .unwrap_or(Ok(ConValue::Empty))?, - )) - } -} diff --git a/compiler/cl-parser/src/parser.rs b/compiler/cl-parser/src/parser.rs index 9f66705..75c88e7 100644 --- a/compiler/cl-parser/src/parser.rs +++ b/compiler/cl-parser/src/parser.rs @@ -836,6 +836,7 @@ impl<'t> Parser<'t> { let parsing = Parsing::ExprKind; // Prefix expressions let mut head = match self.peek_kind(Parsing::Unary)? { + TokenKind::Semi => return Ok(ExprKind::Empty), // TODO: is this okay? literal_like!() => self.literal()?.into(), path_like!() => self.exprkind_pathlike()?, TokenKind::Amp | TokenKind::AmpAmp => self.addrof()?.into(), @@ -846,8 +847,6 @@ impl<'t> Parser<'t> { TokenKind::While => ExprKind::While(self.parse_while()?), TokenKind::If => ExprKind::If(self.parse_if()?), TokenKind::For => ExprKind::For(self.parse_for()?), - TokenKind::Break => ExprKind::Break(self.parse_break()?), - TokenKind::Return => ExprKind::Return(self.parse_return()?), TokenKind::Continue => { self.consume_peeked(); ExprKind::Continue @@ -1159,24 +1158,6 @@ impl<'t> Parser<'t> { } /// ## Control flow subexpressions impl<'t> Parser<'t> { - /// [Break] = `break` (*unconsumed* `;` | [Expr]) - pub fn parse_break(&mut self) -> PResult { - self.consume_peeked(); - Ok(Break { body: self.ret_body(Parsing::Break)? }) - } - /// [Return] = `return` (*unconsumed* `;` | [Expr]) - pub fn parse_return(&mut self) -> PResult { - self.consume_peeked(); - Ok(Return { body: self.ret_body(Parsing::Return)? }) - } - /// ret_body = (*unconsumed* `;` | [Expr]) - fn ret_body(&mut self, while_parsing: Parsing) -> PResult>> { - Ok(match self.peek_kind(while_parsing)? { - TokenKind::Semi => None, - _ => Some(self.expr()?.into()), - }) - } - /// [While] = `while` [Expr] [Block] [Else]? pub fn parse_while(&mut self) -> PResult { self.consume_peeked(); @@ -1291,7 +1272,7 @@ impl From for Precedence { fn from(value: UnaryKind) -> Self { use UnaryKind as Op; 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, } } @@ -1310,6 +1291,8 @@ macro operator($($name:ident ($takes:ident => $returns:ident) {$($t:ident => $p: operator! { from_prefix (TokenKind => UnaryKind) { Loop => Loop, + Break => Break, + Return => Return, Star => Deref, Minus => Neg, Bang => Not, diff --git a/compiler/cl-repl/examples/yaml.rs b/compiler/cl-repl/examples/yaml.rs index 9425f2a..d14daed 100644 --- a/compiler/cl-repl/examples/yaml.rs +++ b/compiler/cl-repl/examples/yaml.rs @@ -409,8 +409,6 @@ pub mod yamlify { ExprKind::While(k) => k.yaml(y), ExprKind::If(k) => k.yaml(y), ExprKind::For(k) => k.yaml(y), - ExprKind::Break(k) => k.yaml(y), - ExprKind::Return(k) => k.yaml(y), ExprKind::Continue => { y.key("Continue"); } @@ -569,18 +567,6 @@ pub mod yamlify { .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 { fn yaml(&self, y: &mut Yamler) { y.value(format_args!("\"{self}\""));