From 6c6d2d04a77035d20c8a618fbefa4815af51cd9e Mon Sep 17 00:00:00 2001 From: John Date: Sat, 17 May 2025 21:28:12 -0400 Subject: [PATCH] cl-ast: Remove variantkind, as it was redundant --- compiler/cl-ast/src/ast.rs | 14 ++---- compiler/cl-ast/src/ast_impl/convert.rs | 4 -- compiler/cl-ast/src/ast_impl/display.rs | 24 +++------ compiler/cl-ast/src/ast_impl/weight_of.rs | 23 ++------- compiler/cl-ast/src/ast_visitor/fold.rs | 28 +++-------- compiler/cl-ast/src/ast_visitor/visit.rs | 3 -- compiler/cl-ast/src/ast_visitor/walk.rs | 21 ++------ compiler/cl-interpret/src/interpret.rs | 33 ++++++------ compiler/cl-parser/src/parser.rs | 58 +++++++--------------- compiler/cl-repl/examples/to_c.rs | 27 +++------- compiler/cl-repl/examples/yaml.rs | 17 ++----- compiler/cl-typeck/src/stage/categorize.rs | 29 ++++++----- compiler/cl-typeck/src/stage/populate.rs | 21 +++----- 13 files changed, 93 insertions(+), 209 deletions(-) diff --git a/compiler/cl-ast/src/ast.rs b/compiler/cl-ast/src/ast.rs index 335f51e..249f3ba 100644 --- a/compiler/cl-ast/src/ast.rs +++ b/compiler/cl-ast/src/ast.rs @@ -169,23 +169,15 @@ pub struct StructMember { pub struct Enum { pub name: Sym, pub gens: Generics, - pub variants: Option>, + pub variants: Vec, } /// A single [Enum] variant #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub struct Variant { pub name: Sym, - pub kind: VariantKind, -} - -/// Whether the [Variant] has a C-like constant value, a tuple, or [StructMember]s -#[derive(Clone, Debug, PartialEq, Eq, Hash)] -pub enum VariantKind { - Plain, - CLike(Box), - Tuple(Ty), - Struct(Vec), + pub kind: StructKind, + pub body: Option>, } /// Sub-[items](Item) (associated functions, etc.) for a [Ty] diff --git a/compiler/cl-ast/src/ast_impl/convert.rs b/compiler/cl-ast/src/ast_impl/convert.rs index c4e755e..5d72213 100644 --- a/compiler/cl-ast/src/ast_impl/convert.rs +++ b/compiler/cl-ast/src/ast_impl/convert.rs @@ -39,10 +39,6 @@ impl_from! { Vec => StructKind::Tuple, // TODO: Struct members in struct } - impl From for VariantKind { - Ty => VariantKind::Tuple, - // TODO: enum struct variants - } impl From for TyKind { Path => TyKind::Path, TyTuple => TyKind::Tuple, diff --git a/compiler/cl-ast/src/ast_impl/display.rs b/compiler/cl-ast/src/ast_impl/display.rs index c2f3d93..323c852 100644 --- a/compiler/cl-ast/src/ast_impl/display.rs +++ b/compiler/cl-ast/src/ast_impl/display.rs @@ -227,29 +227,19 @@ impl Display for StructMember { impl Display for Enum { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - let Self { name, gens, variants: kind } = self; + let Self { name, gens, variants } = self; write!(f, "enum {name}{gens}")?; - match kind { - Some(v) => separate(v, ",\n")(f.delimit(SPACED_BRACES)), - None => ";".fmt(f), - } + separate(variants, ",\n")(f.delimit(SPACED_BRACES)) } } impl Display for Variant { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - let Self { name, kind } = self; - write!(f, "{name}{kind}") - } -} - -impl Display for VariantKind { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - VariantKind::Plain => Ok(()), - VariantKind::CLike(n) => write!(f, " = {n}"), - VariantKind::Tuple(v) => v.fmt(f), - VariantKind::Struct(v) => separate(v, ", ")(f.delimit(INLINE_BRACES)), + let Self { name, kind, body } = self; + write!(f, "{name}{kind}")?; + match body { + Some(body) => write!(f, " {body}"), + None => Ok(()), } } } diff --git a/compiler/cl-ast/src/ast_impl/weight_of.rs b/compiler/cl-ast/src/ast_impl/weight_of.rs index 63b02c4..f1630ba 100644 --- a/compiler/cl-ast/src/ast_impl/weight_of.rs +++ b/compiler/cl-ast/src/ast_impl/weight_of.rs @@ -134,29 +134,14 @@ impl WeightOf for StructMember { impl WeightOf for Enum { fn weight_of(&self) -> usize { let Self { name, gens, variants } = self; - name.weight_of() - + gens.weight_of() - + variants - .as_ref() - .map_or(size_of_val(variants), |v| v.weight_of()) + name.weight_of() + gens.weight_of() + variants.weight_of() } } impl WeightOf for Variant { fn weight_of(&self) -> usize { - let Self { name, kind } = self; - name.weight_of() + kind.weight_of() - } -} - -impl WeightOf for VariantKind { - fn weight_of(&self) -> usize { - match self { - VariantKind::Plain => size_of_val(self), - VariantKind::CLike(v) => v.weight_of(), - VariantKind::Tuple(ty) => ty.weight_of(), - VariantKind::Struct(m) => m.weight_of(), - } + let Self { name, kind, body } = self; + name.weight_of() + kind.weight_of() + body.weight_of() } } @@ -559,7 +544,7 @@ impl WeightOf for Return { impl WeightOf for Option { fn weight_of(&self) -> usize { match self { - Some(t) => t.weight_of(), + Some(t) => t.weight_of().max(size_of_val(t)), None => size_of_val(self), } } diff --git a/compiler/cl-ast/src/ast_visitor/fold.rs b/compiler/cl-ast/src/ast_visitor/fold.rs index 08fa247..2327365 100644 --- a/compiler/cl-ast/src/ast_visitor/fold.rs +++ b/compiler/cl-ast/src/ast_visitor/fold.rs @@ -143,16 +143,17 @@ pub trait Fold { Enum { name: self.fold_sym(name), gens: self.fold_generics(gens), - variants: kind.map(|v| v.into_iter().map(|v| self.fold_variant(v)).collect()), + variants: kind.into_iter().map(|v| self.fold_variant(v)).collect(), } } fn fold_variant(&mut self, v: Variant) -> Variant { - let Variant { name, kind } = v; + let Variant { name, kind, body } = v; - Variant { name: self.fold_sym(name), kind: self.fold_variant_kind(kind) } - } - fn fold_variant_kind(&mut self, kind: VariantKind) -> VariantKind { - or_fold_variant_kind(self, kind) + Variant { + name: self.fold_sym(name), + kind: self.fold_struct_kind(kind), + body: body.map(|e| Box::new(self.fold_expr(*e))), + } } fn fold_impl(&mut self, i: Impl) -> Impl { let Impl { target, body } = i; @@ -486,21 +487,6 @@ pub fn or_fold_struct_kind(folder: &mut F, kind: StructKind) - } } -#[inline] -/// Folds a [VariantKind] in the default way -pub fn or_fold_variant_kind(folder: &mut F, kind: VariantKind) -> VariantKind { - match kind { - VariantKind::Plain => VariantKind::Plain, - VariantKind::CLike(n) => VariantKind::CLike(n), - VariantKind::Tuple(t) => VariantKind::Tuple(folder.fold_ty(t)), - VariantKind::Struct(mem) => VariantKind::Struct( - mem.into_iter() - .map(|m| folder.fold_struct_member(m)) - .collect(), - ), - } -} - #[inline] /// Folds an [ImplKind] in the default way pub fn or_fold_impl_kind(folder: &mut F, kind: ImplKind) -> ImplKind { diff --git a/compiler/cl-ast/src/ast_visitor/visit.rs b/compiler/cl-ast/src/ast_visitor/visit.rs index 18f34cb..60fd453 100644 --- a/compiler/cl-ast/src/ast_visitor/visit.rs +++ b/compiler/cl-ast/src/ast_visitor/visit.rs @@ -106,9 +106,6 @@ pub trait Visit<'a>: Sized { fn visit_variant(&mut self, value: &'a Variant) { value.children(self) } - fn visit_variant_kind(&mut self, value: &'a VariantKind) { - value.children(self) - } fn visit_impl(&mut self, value: &'a Impl) { value.children(self) } diff --git a/compiler/cl-ast/src/ast_visitor/walk.rs b/compiler/cl-ast/src/ast_visitor/walk.rs index 683d9af..eae8480 100644 --- a/compiler/cl-ast/src/ast_visitor/walk.rs +++ b/compiler/cl-ast/src/ast_visitor/walk.rs @@ -276,9 +276,7 @@ impl Walk for Enum { let Enum { name, gens, variants } = self; name.visit_in(v); gens.visit_in(v); - if let Some(variants) = variants { - variants.visit_in(v); - } + variants.visit_in(v); } } impl Walk for Variant { @@ -287,23 +285,10 @@ impl Walk for Variant { v.visit_variant(self); } fn children<'a, V: Visit<'a>>(&'a self, v: &mut V) { - let Variant { name, kind } = self; + let Variant { name, kind, body } = self; name.visit_in(v); kind.visit_in(v); - } -} -impl Walk for VariantKind { - #[inline] - fn visit_in<'a, V: Visit<'a>>(&'a self, v: &mut V) { - v.visit_variant_kind(self); - } - fn children<'a, V: Visit<'a>>(&'a self, v: &mut V) { - match self { - VariantKind::Plain => {} - VariantKind::CLike(_) => {} - VariantKind::Tuple(t) => t.visit_in(v), - VariantKind::Struct(m) => m.visit_in(v), - } + body.visit_in(v); } } impl Walk for Impl { diff --git a/compiler/cl-interpret/src/interpret.rs b/compiler/cl-interpret/src/interpret.rs index 1320a2f..b2e9d3e 100644 --- a/compiler/cl-interpret/src/interpret.rs +++ b/compiler/cl-interpret/src/interpret.rs @@ -153,25 +153,26 @@ impl Interpret for Struct { } impl Interpret for Enum { fn interpret(&self, env: &mut Environment) -> IResult { - let Self { name, gens: _, variants: kind } = self; - if let Some(variants) = kind { - env.push_frame(name.to_ref(), Default::default()); - for (idx, Variant { name, kind }) in variants.iter().enumerate() { - match kind { - VariantKind::Plain => env.insert(*name, Some(ConValue::Int(idx as _))), - VariantKind::CLike(idx) => { - let idx = idx.interpret(env)?; - env.insert(*name, Some(idx)) - } - VariantKind::Tuple(ty) => eprintln!("TODO: Enum-tuple variants: {ty}"), - VariantKind::Struct(_) => eprintln!("TODO: Enum-struct members: {kind}"), + let Self { name, gens: _, variants } = self; + env.push_frame(name.to_ref(), Default::default()); + for (idx, Variant { name, kind, body }) in variants.iter().enumerate() { + match (kind, body) { + (StructKind::Empty, None) => env.insert(*name, Some(ConValue::Int(idx as _))), + (StructKind::Empty, Some(idx)) => { + let idx = idx.interpret(env)?; + env.insert(*name, Some(idx)) } + (StructKind::Tuple(_), None) => eprintln!("TODO: Enum-tuple variants: {kind}"), + (StructKind::Struct(_), None) => { + eprintln!("TODO: Enum-struct members: {kind}") + } + _ => eprintln!("Well-formedness error in {self}"), } - let (frame, _) = env - .pop_frame() - .expect("Frame stack should remain balanced."); - env.insert(*name, Some(ConValue::Module(Box::new(frame)))); } + let (frame, _) = env + .pop_frame() + .expect("Frame stack should remain balanced."); + env.insert(*name, Some(ConValue::Module(Box::new(frame)))); Ok(ConValue::Empty) } } diff --git a/compiler/cl-parser/src/parser.rs b/compiler/cl-parser/src/parser.rs index 177f58f..8332211 100644 --- a/compiler/cl-parser/src/parser.rs +++ b/compiler/cl-parser/src/parser.rs @@ -529,22 +529,19 @@ impl Parse<'_> for StructKind { /// Parses the various [kinds of Struct](StructKind) fn parse(p: &mut Parser<'_>) -> PResult { const P: Parsing = Parsing::StructKind; - Ok(match p.peek_kind(P)? { - TokenKind::LParen => StructKind::Tuple(delim( + Ok(match p.peek_kind(P) { + Ok(TokenKind::LParen) => StructKind::Tuple(delim( sep(Ty::parse, TokenKind::Comma, PARENS.1, P), PARENS, P, )(p)?), - TokenKind::LCurly => StructKind::Struct(delim( + Ok(TokenKind::LCurly) => StructKind::Struct(delim( sep(StructMember::parse, TokenKind::Comma, CURLIES.1, P), CURLIES, P, )(p)?), - TokenKind::Semi => { - p.consume_peeked(); - StructKind::Empty - } - got => Err(p.error(ExpectedToken { want: TokenKind::Semi, got }, P))?, + Ok(_) | Err(Error { reason: ErrorKind::EndOfInput, .. }) => StructKind::Empty, + Err(e) => Err(e)?, }) } } @@ -574,15 +571,11 @@ impl Parse<'_> for Enum { variants: { const P: Parsing = Parsing::EnumKind; match p.peek_kind(P)? { - TokenKind::LCurly => Some(delim( + TokenKind::LCurly => delim( sep(Variant::parse, TokenKind::Comma, TokenKind::RCurly, P), CURLIES, P, - )(p)?), - TokenKind::Semi => { - p.consume_peeked(); - None - } + )(p)?, t => Err(p.error(Unexpected(t), P))?, } }, @@ -593,34 +586,19 @@ impl Parse<'_> for Enum { impl Parse<'_> for Variant { /// Parses an [`enum`](Enum) [Variant] fn parse(p: &mut Parser) -> PResult { - Ok(Variant { name: Sym::parse(p)?, kind: VariantKind::parse(p)? }) - } -} + let name = Sym::parse(p)?; + let kind; + let body; -impl Parse<'_> for VariantKind { - /// Parses the various [kinds of Enum Variant](VariantKind) - fn parse(p: &mut Parser<'_>) -> PResult { - const P: Parsing = Parsing::VariantKind; - Ok(match p.peek_kind(P)? { - TokenKind::Eq => { - p.consume_peeked(); - VariantKind::CLike(Box::new(p.parse()?)) - } - TokenKind::LCurly => VariantKind::Struct(delim( - sep(StructMember::parse, TokenKind::Comma, TokenKind::RCurly, P), - CURLIES, - P, - )(p)?), - TokenKind::LParen => { - let tup = Ty::parse(p)?; - if !matches!(tup.kind, TyKind::Tuple(_) | TyKind::Empty) { - Err(p.error(ErrorKind::ExpectedParsing { want: Parsing::TyTuple }, P))? - } + if p.match_type(TokenKind::Eq, Parsing::Variant).is_ok() { + kind = StructKind::Empty; + body = Some(Box::new(Expr::parse(p)?)); + } else { + kind = StructKind::parse(p)?; + body = None; + } - VariantKind::Tuple(tup) - } - _ => VariantKind::Plain, - }) + Ok(Variant { name, kind, body }) } } diff --git a/compiler/cl-repl/examples/to_c.rs b/compiler/cl-repl/examples/to_c.rs index 3124e49..242c09c 100644 --- a/compiler/cl-repl/examples/to_c.rs +++ b/compiler/cl-repl/examples/to_c.rs @@ -330,34 +330,19 @@ pub mod clangify { fn print(&self, y: &mut CLangifier) { let Self { name, gens: _, variants } = self; y.nest("enum ").p(name).p(" {").endl(); - match variants { - Some(v) => { - for (idx, variant) in v.iter().enumerate() { - if idx > 0 { - y.p(",").endl(); - } - y.p(variant); - } + for (idx, variant) in variants.iter().enumerate() { + if idx > 0 { + y.p(",").endl(); } - None => todo!(), + y.p(variant); } y.endl().p("\n}"); } } impl CLangify for Variant { fn print(&self, y: &mut CLangifier) { - let Self { name, kind } = self; - y.p(name).p(kind); - } - } - impl CLangify for VariantKind { - fn print(&self, y: &mut CLangifier) { - match self { - VariantKind::Plain => y, - VariantKind::CLike(v) => y.p(" = ").p(v), - VariantKind::Tuple(v) => y.p("/* TODO: ").p(v).p(" */"), - VariantKind::Struct(v) => y.p("/* TODO: ").p(v).p(" */"), - }; + let Self { name, kind, body } = self; + y.p(name).p(kind).p(body); } } impl CLangify for Impl { diff --git a/compiler/cl-repl/examples/yaml.rs b/compiler/cl-repl/examples/yaml.rs index a6ba1a7..a66bb08 100644 --- a/compiler/cl-repl/examples/yaml.rs +++ b/compiler/cl-repl/examples/yaml.rs @@ -293,18 +293,11 @@ pub mod yamlify { } impl Yamlify for Variant { fn yaml(&self, y: &mut Yamler) { - let Self { name, kind } = self; - y.key("Variant").pair("name", name).yaml(kind); - } - } - impl Yamlify for VariantKind { - fn yaml(&self, y: &mut Yamler) { - match self { - VariantKind::Plain => y, - VariantKind::CLike(v) => y.yaml(v), - VariantKind::Tuple(v) => y.yaml(v), - VariantKind::Struct(v) => y.yaml(v), - }; + let Self { name, kind, body } = self; + y.key("Variant") + .pair("name", name) + .pair("kind", kind) + .pair("body", body); } } impl Yamlify for Impl { diff --git a/compiler/cl-typeck/src/stage/categorize.rs b/compiler/cl-typeck/src/stage/categorize.rs index 8a682b7..a82e75e 100644 --- a/compiler/cl-typeck/src/stage/categorize.rs +++ b/compiler/cl-typeck/src/stage/categorize.rs @@ -106,27 +106,29 @@ fn cat_enum<'a>(_table: &mut Table<'a>, _node: Handle, e: &'a Enum) -> CatResult } fn cat_variant<'a>(table: &mut Table<'a>, node: Handle, v: &'a Variant) -> CatResult<()> { - let Variant { name, kind } = v; + let Variant { name, kind, body } = v; let parent = table.parent(node).copied().unwrap_or(table.root()); table.add_child(parent, *name, node); - match kind { - VariantKind::Plain => { - table.set_ty(node, TypeKind::Instance(parent)); + match (kind, body) { + (StructKind::Empty, None) => { + table.set_ty(node, TypeKind::Adt(Adt::UnitStruct)); Ok(()) } - VariantKind::CLike(c) => { + (StructKind::Empty, Some(c)) => { table.set_body(node, c); - table.set_ty(node, TypeKind::Instance(parent)); + table.set_ty(node, TypeKind::Adt(Adt::UnitStruct)); Ok(()) } - VariantKind::Tuple(ty) => { - let ty = ty - .evaluate(table, node) - .map_err(|e| Error::TypeEval(e, " while categorizing a variant"))?; - table.set_ty(node, TypeKind::Instance(ty)); + (StructKind::Tuple(ty), None) => { + let ty = TypeKind::Adt(Adt::TupleStruct( + ty.iter() + .map(|ty| ty.evaluate(table, node).map(|ty| (Visibility::Public, ty))) + .collect::>()?, + )); + table.set_ty(node, ty); Ok(()) } - VariantKind::Struct(members) => { + (StructKind::Struct(members), None) => { let mut out = vec![]; for StructMember { vis, name, ty } in members { let ty = ty.evaluate(table, node)?; @@ -144,6 +146,9 @@ fn cat_variant<'a>(table: &mut Table<'a>, node: Handle, v: &'a Variant) -> CatRe table.set_ty(node, TypeKind::Adt(Adt::Struct(out))); Ok(()) } + (_, Some(body)) => { + panic!("Unexpected body `{body}` in enum variant `{v}`") + } } } diff --git a/compiler/cl-typeck/src/stage/populate.rs b/compiler/cl-typeck/src/stage/populate.rs index 974cf21..3d5cdf9 100644 --- a/compiler/cl-typeck/src/stage/populate.rs +++ b/compiler/cl-typeck/src/stage/populate.rs @@ -4,7 +4,7 @@ use crate::{ handle::Handle, source::Source, table::{NodeKind, Table}, - type_kind::{Primitive, TypeKind}, + type_kind::TypeKind, }; use cl_ast::{ ItemKind, Sym, @@ -145,7 +145,7 @@ impl<'a> Visit<'a> for Populator<'_, 'a> { self.visit(gens); self.visit(variants); let mut children = Vec::new(); - for variant in variants.iter().flatten() { + for variant in variants.iter() { let mut entry = self.new_entry(NodeKind::Type); variant.visit_in(&mut entry); children.push((variant.name, entry.inner.id())); @@ -155,27 +155,18 @@ impl<'a> Visit<'a> for Populator<'_, 'a> { } fn visit_variant(&mut self, value: &'a cl_ast::Variant) { - let cl_ast::Variant { name, kind } = value; + let cl_ast::Variant { name, kind, body } = value; let mut entry = self.new_entry(NodeKind::Type); entry.inner.set_source(Source::Variant(value)); entry.visit(kind); + if let Some(body) = body { + entry.inner.set_body(body); + } let child = entry.inner.id(); self.inner.add_child(*name, child); } - fn visit_variant_kind(&mut self, value: &'a cl_ast::VariantKind) { - match value { - cl_ast::VariantKind::Plain => self.inner.set_ty(TypeKind::Empty), - cl_ast::VariantKind::CLike(body) => { - self.inner.set_body(body); - self.inner.set_ty(TypeKind::Primitive(Primitive::Integer)) - } - cl_ast::VariantKind::Tuple(_) => None, - cl_ast::VariantKind::Struct(_) => None, - }; - } - fn visit_impl(&mut self, i: &'a cl_ast::Impl) { let cl_ast::Impl { target, body } = i; self.inner.set_source(Source::Impl(i));