cl-ast: Move let into Expr
				
					
				
			This commit is contained in:
		| @@ -323,7 +323,6 @@ pub struct Stmt { | ||||
| #[derive(Clone, Debug, PartialEq, Eq, Hash)] | ||||
| pub enum StmtKind { | ||||
|     Empty, | ||||
|     Local(Let), | ||||
|     Item(Box<Item>), | ||||
|     Expr(Box<Expr>), | ||||
| } | ||||
| @@ -342,6 +341,7 @@ pub struct Let { | ||||
|     pub name: Sym, | ||||
|     pub ty: Option<Box<Ty>>, | ||||
|     pub init: Option<Box<Expr>>, | ||||
|     pub tail: Option<Box<Expr>>, | ||||
| } | ||||
|  | ||||
| /// An expression, the beating heart of the language | ||||
| @@ -357,6 +357,8 @@ pub enum ExprKind { | ||||
|     /// An empty expression: `(` `)` | ||||
|     #[default] | ||||
|     Empty, | ||||
|     /// A local bind instruction, `let` [`Sym`] `=` [`Expr`] | ||||
|     Let(Let), | ||||
|     /// An [Assign]ment expression: [`Expr`] (`=` [`Expr`])\+ | ||||
|     Assign(Assign), | ||||
|     /// A [Modify]-assignment expression: [`Expr`] ([`ModifyKind`] [`Expr`])\+ | ||||
|   | ||||
| @@ -389,7 +389,6 @@ mod display { | ||||
|         fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||||
|             match self { | ||||
|                 StmtKind::Empty => Ok(()), | ||||
|                 StmtKind::Local(v) => v.fmt(f), | ||||
|                 StmtKind::Item(v) => v.fmt(f), | ||||
|                 StmtKind::Expr(v) => v.fmt(f), | ||||
|             } | ||||
| @@ -407,7 +406,7 @@ mod display { | ||||
|  | ||||
|     impl Display for Let { | ||||
|         fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||||
|             let Self { mutable, name, ty, init } = self; | ||||
|             let Self { mutable, name, ty, init, tail } = self; | ||||
|             write!(f, "let {mutable}{name}")?; | ||||
|             if let Some(value) = ty { | ||||
|                 write!(f, ": {value}")?; | ||||
| @@ -415,6 +414,9 @@ mod display { | ||||
|             if let Some(value) = init { | ||||
|                 write!(f, " = {value}")?; | ||||
|             } | ||||
|             if let Some(value) = tail { | ||||
|                 write!(f, ";\n{value}")?; | ||||
|             } | ||||
|             Ok(()) | ||||
|         } | ||||
|     } | ||||
| @@ -429,6 +431,7 @@ mod display { | ||||
|         fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { | ||||
|             match self { | ||||
|                 ExprKind::Empty => "()".fmt(f), | ||||
|                 ExprKind::Let(v) => v.fmt(f), | ||||
|                 ExprKind::Assign(v) => v.fmt(f), | ||||
|                 ExprKind::Modify(v) => v.fmt(f), | ||||
|                 ExprKind::Binary(v) => v.fmt(f), | ||||
| @@ -763,11 +766,11 @@ mod convert { | ||||
|             TyFn => TyKind::Fn, | ||||
|         } | ||||
|         impl From for StmtKind { | ||||
|             Let => StmtKind::Local, | ||||
|             Item => StmtKind::Item, | ||||
|             Expr => StmtKind::Expr, | ||||
|         } | ||||
|         impl From for ExprKind { | ||||
|             Let => ExprKind::Let, | ||||
|             Assign => ExprKind::Assign, | ||||
|             Modify => ExprKind::Modify, | ||||
|             Binary => ExprKind::Binary, | ||||
|   | ||||
| @@ -227,12 +227,13 @@ pub trait Fold { | ||||
|         s | ||||
|     } | ||||
|     fn fold_let(&mut self, l: Let) -> Let { | ||||
|         let Let { mutable, name, ty, init } = l; | ||||
|         let Let { mutable, name, ty, init, tail } = l; | ||||
|         Let { | ||||
|             mutable: self.fold_mutability(mutable), | ||||
|             name: self.fold_sym(name), | ||||
|             ty: ty.map(|t| Box::new(self.fold_ty(*t))), | ||||
|             init: init.map(|e| Box::new(self.fold_expr(*e))), | ||||
|             tail: tail.map(|e| Box::new(self.fold_expr(*e))), | ||||
|         } | ||||
|     } | ||||
|     fn fold_expr(&mut self, e: Expr) -> Expr { | ||||
| @@ -525,7 +526,6 @@ pub fn or_fold_ty_kind<F: Fold + ?Sized>(folder: &mut F, kind: TyKind) -> TyKind | ||||
| pub fn or_fold_stmt_kind<F: Fold + ?Sized>(folder: &mut F, kind: StmtKind) -> StmtKind { | ||||
|     match kind { | ||||
|         StmtKind::Empty => StmtKind::Empty, | ||||
|         StmtKind::Local(l) => StmtKind::Local(folder.fold_let(l)), | ||||
|         StmtKind::Item(i) => StmtKind::Item(Box::new(folder.fold_item(*i))), | ||||
|         StmtKind::Expr(e) => StmtKind::Expr(Box::new(folder.fold_expr(*e))), | ||||
|     } | ||||
| @@ -535,6 +535,7 @@ pub fn or_fold_stmt_kind<F: Fold + ?Sized>(folder: &mut F, kind: StmtKind) -> St | ||||
| pub fn or_fold_expr_kind<F: Fold + ?Sized>(folder: &mut F, kind: ExprKind) -> ExprKind { | ||||
|     match kind { | ||||
|         ExprKind::Empty => ExprKind::Empty, | ||||
|         ExprKind::Let(l) => ExprKind::Let(folder.fold_let(l)), | ||||
|         ExprKind::Assign(a) => ExprKind::Assign(folder.fold_assign(a)), | ||||
|         ExprKind::Modify(m) => ExprKind::Modify(folder.fold_modify(m)), | ||||
|         ExprKind::Binary(b) => ExprKind::Binary(folder.fold_binary(b)), | ||||
|   | ||||
| @@ -192,7 +192,7 @@ pub trait Visit<'a>: Sized { | ||||
|     } | ||||
|     fn visit_semi(&mut self, _s: &'a Semi) {} | ||||
|     fn visit_let(&mut self, l: &'a Let) { | ||||
|         let Let { mutable, name, ty, init } = l; | ||||
|         let Let { mutable, name, ty, init, tail } = l; | ||||
|         self.visit_mutability(mutable); | ||||
|         self.visit_sym(name); | ||||
|         if let Some(ty) = ty { | ||||
| @@ -201,6 +201,9 @@ pub trait Visit<'a>: Sized { | ||||
|         if let Some(init) = init { | ||||
|             self.visit_expr(init) | ||||
|         } | ||||
|         if let Some(tail) = tail { | ||||
|             self.visit_expr(tail) | ||||
|         } | ||||
|     } | ||||
|     fn visit_expr(&mut self, e: &'a Expr) { | ||||
|         let Expr { extents, kind } = e; | ||||
| @@ -448,7 +451,6 @@ pub fn or_visit_ty_kind<'a, V: Visit<'a>>(visitor: &mut V, kind: &'a TyKind) { | ||||
| pub fn or_visit_stmt_kind<'a, V: Visit<'a>>(visitor: &mut V, kind: &'a StmtKind) { | ||||
|     match kind { | ||||
|         StmtKind::Empty => {} | ||||
|         StmtKind::Local(l) => visitor.visit_let(l), | ||||
|         StmtKind::Item(i) => visitor.visit_item(i), | ||||
|         StmtKind::Expr(e) => visitor.visit_expr(e), | ||||
|     } | ||||
| @@ -457,6 +459,7 @@ pub fn or_visit_stmt_kind<'a, V: Visit<'a>>(visitor: &mut V, kind: &'a StmtKind) | ||||
| pub fn or_visit_expr_kind<'a, V: Visit<'a>>(visitor: &mut V, e: &'a ExprKind) { | ||||
|     match e { | ||||
|         ExprKind::Empty => {} | ||||
|         ExprKind::Let(l) => visitor.visit_let(l), | ||||
|         ExprKind::Assign(a) => visitor.visit_assign(a), | ||||
|         ExprKind::Modify(m) => visitor.visit_modify(m), | ||||
|         ExprKind::Binary(b) => visitor.visit_binary(b), | ||||
|   | ||||
| @@ -105,7 +105,6 @@ impl Interpret for Stmt { | ||||
|         let Self { extents: _, kind, semi } = self; | ||||
|         let out = match kind { | ||||
|             StmtKind::Empty => ConValue::Empty, | ||||
|             StmtKind::Local(stmt) => stmt.interpret(env)?, | ||||
|             StmtKind::Item(stmt) => stmt.interpret(env)?, | ||||
|             StmtKind::Expr(stmt) => stmt.interpret(env)?, | ||||
|         }; | ||||
| @@ -117,9 +116,10 @@ impl Interpret for Stmt { | ||||
| } | ||||
| impl Interpret for Let { | ||||
|     fn interpret(&self, env: &mut Environment) -> IResult<ConValue> { | ||||
|         let Let { mutable: _, name, ty: _, init } = self; | ||||
|         let Let { mutable: _, name, ty: _, init, tail } = self; | ||||
|         let init = init.as_ref().map(|i| i.interpret(env)).transpose()?; | ||||
|         env.insert(*name, init); | ||||
|         tail.as_ref().map(|e| e.interpret(env)).transpose()?; | ||||
|         Ok(ConValue::Empty) | ||||
|     } | ||||
| } | ||||
| @@ -134,6 +134,7 @@ impl Interpret for ExprKind { | ||||
|     fn interpret(&self, env: &mut Environment) -> IResult<ConValue> { | ||||
|         match self { | ||||
|             ExprKind::Empty => Ok(ConValue::Empty), | ||||
|             ExprKind::Let(v) => v.interpret(env), | ||||
|             ExprKind::Assign(v) => v.interpret(env), | ||||
|             ExprKind::Modify(v) => v.interpret(env), | ||||
|             ExprKind::Binary(v) => v.interpret(env), | ||||
|   | ||||
| @@ -815,31 +815,10 @@ impl<'t> Parser<'t> { | ||||
|     pub fn stmtkind(&mut self) -> PResult<StmtKind> { | ||||
|         Ok(match self.peek_kind(Parsing::StmtKind)? { | ||||
|             TokenKind::Semi => StmtKind::Empty, | ||||
|             TokenKind::Let => self.parse_let()?.into(), | ||||
|             item_like!() => self.item()?.into(), | ||||
|             _ => self.expr()?.into(), | ||||
|         }) | ||||
|     } | ||||
|  | ||||
|     pub fn parse_let(&mut self) -> PResult<Let> { | ||||
|         self.consume_peeked(); | ||||
|         Ok(Let { | ||||
|             mutable: self.mutability(), | ||||
|             name: self.identifier()?, | ||||
|             ty: if Ok(TokenKind::Colon) == self.peek_kind(Parsing::Let) { | ||||
|                 self.consume_peeked(); | ||||
|                 Some(self.ty()?.into()) | ||||
|             } else { | ||||
|                 None | ||||
|             }, | ||||
|             init: if Ok(TokenKind::Eq) == self.peek_kind(Parsing::Let) { | ||||
|                 self.consume_peeked(); | ||||
|                 Some(self.expr()?.into()) | ||||
|             } else { | ||||
|                 None | ||||
|             }, | ||||
|         }) | ||||
|     } | ||||
| } | ||||
|  | ||||
| /// # Expression parsing | ||||
| @@ -863,6 +842,7 @@ impl<'t> Parser<'t> { | ||||
|             TokenKind::LCurly => self.block()?.into(), | ||||
|             TokenKind::LBrack => self.exprkind_arraylike()?, | ||||
|             TokenKind::LParen => self.exprkind_tuplelike()?, | ||||
|             TokenKind::Let => self.parse_let()?.into(), | ||||
|             TokenKind::Loop => { | ||||
|                 self.consume_peeked(); | ||||
|                 Loop { body: self.expr()?.into() }.into() | ||||
| @@ -1157,6 +1137,29 @@ impl<'t> Parser<'t> { | ||||
|         const A_BLOCK: Parsing = Parsing::Block; | ||||
|         Ok(Block { stmts: delim(rep(Self::stmt, CURLIES.1, A_BLOCK), CURLIES, A_BLOCK)(self)? }) | ||||
|     } | ||||
|  | ||||
|     pub fn parse_let(&mut self) -> PResult<Let> { | ||||
|         self.consume_peeked(); | ||||
|         Ok(Let { | ||||
|             mutable: self.mutability(), | ||||
|             name: self.identifier()?, | ||||
|             ty: if self.match_type(TokenKind::Colon, Parsing::Let).is_ok() { | ||||
|                 Some(self.ty()?.into()) | ||||
|             } else { | ||||
|                 None | ||||
|             }, | ||||
|             init: if self.match_type(TokenKind::Eq, Parsing::Let).is_ok() { | ||||
|                 Some(self.expr()?.into()) | ||||
|             } else { | ||||
|                 None | ||||
|             }, | ||||
|             tail: if self.match_type(TokenKind::Semi, Parsing::Let).is_ok() { | ||||
|                 Some(self.expr()?.into()) | ||||
|             } else { | ||||
|                 None | ||||
|             }, | ||||
|         }) | ||||
|     } | ||||
| } | ||||
| /// ## Control flow subexpressions | ||||
| impl<'t> Parser<'t> { | ||||
|   | ||||
| @@ -363,7 +363,6 @@ pub mod yamlify { | ||||
|         fn yaml(&self, y: &mut Yamler) { | ||||
|             match self { | ||||
|                 StmtKind::Empty => y, | ||||
|                 StmtKind::Local(s) => y.yaml(s), | ||||
|                 StmtKind::Item(s) => y.yaml(s), | ||||
|                 StmtKind::Expr(s) => y.yaml(s), | ||||
|             }; | ||||
| @@ -371,12 +370,13 @@ pub mod yamlify { | ||||
|     } | ||||
|     impl Yamlify for Let { | ||||
|         fn yaml(&self, y: &mut Yamler) { | ||||
|             let Self { mutable, name, ty, init } = self; | ||||
|             let Self { mutable, name, ty, init, tail } = self; | ||||
|             y.key("Let") | ||||
|                 .pair("name", name) | ||||
|                 .yaml(mutable) | ||||
|                 .pair("ty", ty) | ||||
|                 .pair("init", init); | ||||
|                 .pair("init", init) | ||||
|                 .pair("tail", tail); | ||||
|         } | ||||
|     } | ||||
|     impl Yamlify for Expr { | ||||
| @@ -388,6 +388,7 @@ pub mod yamlify { | ||||
|     impl Yamlify for ExprKind { | ||||
|         fn yaml(&self, y: &mut Yamler) { | ||||
|             match self { | ||||
|                 ExprKind::Let(k) => k.yaml(y), | ||||
|                 ExprKind::Assign(k) => k.yaml(y), | ||||
|                 ExprKind::Modify(k) => k.yaml(y), | ||||
|                 ExprKind::Binary(k) => k.yaml(y), | ||||
|   | ||||
| @@ -145,35 +145,25 @@ impl<'a> Visit<'a> for Populator<'_, 'a> { | ||||
|         self.visit_use_tree(tree); | ||||
|     } | ||||
|  | ||||
|     fn visit_stmt(&mut self, s: &'a cl_ast::Stmt) { | ||||
|         let cl_ast::Stmt { extents, kind, semi } = s; | ||||
|         let cl_ast::StmtKind::Local(local) = kind else { | ||||
|             self.visit_span(extents); | ||||
|             self.visit_stmt_kind(kind); | ||||
|             self.visit_semi(semi); | ||||
|             return; | ||||
|         }; | ||||
|  | ||||
|         let mut entry = self.new_entry(NodeKind::Local); | ||||
|         entry.inner.set_span(*extents); | ||||
|         entry.visit_let(local); | ||||
|  | ||||
|         if let (Some(name), child) = (entry.name, entry.inner.id()) { | ||||
|             self.inner.add_child(name, child); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     fn visit_let(&mut self, l: &'a cl_ast::Let) { | ||||
|         let cl_ast::Let { mutable, name, ty, init } = l; | ||||
|         self.inner.set_source(Source::Local(l)); | ||||
|         self.set_name(*name); | ||||
|         let cl_ast::Let { mutable, name, ty, init, tail } = l; | ||||
|         let mut entry = self.new_entry(NodeKind::Local); | ||||
|  | ||||
|         self.visit_mutability(mutable); | ||||
|         entry.inner.set_source(Source::Local(l)); | ||||
|         entry.set_name(*name); | ||||
|  | ||||
|         entry.visit_mutability(mutable); | ||||
|         if let Some(ty) = ty { | ||||
|             self.visit_ty(ty); | ||||
|             entry.visit_ty(ty); | ||||
|         } | ||||
|         if let Some(init) = init { | ||||
|             self.visit_expr(init) | ||||
|             entry.visit_expr(init) | ||||
|         } | ||||
|         if let Some(tail) = tail { | ||||
|             entry.visit_expr(tail) | ||||
|         } | ||||
|  | ||||
|         let child = entry.inner.id(); | ||||
|         self.inner.add_child(*name, child); | ||||
|     } | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user