cl-ast: Remove variantkind, as it was redundant

This commit is contained in:
John 2025-05-17 21:28:12 -04:00
parent a023551d9f
commit 6c6d2d04a7
13 changed files with 93 additions and 209 deletions

View File

@ -169,23 +169,15 @@ pub struct StructMember {
pub struct Enum { pub struct Enum {
pub name: Sym, pub name: Sym,
pub gens: Generics, pub gens: Generics,
pub variants: Option<Vec<Variant>>, pub variants: Vec<Variant>,
} }
/// A single [Enum] variant /// A single [Enum] variant
#[derive(Clone, Debug, PartialEq, Eq, Hash)] #[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct Variant { pub struct Variant {
pub name: Sym, pub name: Sym,
pub kind: VariantKind, pub kind: StructKind,
} pub body: Option<Box<Expr>>,
/// 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<Expr>),
Tuple(Ty),
Struct(Vec<StructMember>),
} }
/// Sub-[items](Item) (associated functions, etc.) for a [Ty] /// Sub-[items](Item) (associated functions, etc.) for a [Ty]

View File

@ -39,10 +39,6 @@ impl_from! {
Vec<Ty> => StructKind::Tuple, Vec<Ty> => StructKind::Tuple,
// TODO: Struct members in struct // TODO: Struct members in struct
} }
impl From for VariantKind {
Ty => VariantKind::Tuple,
// TODO: enum struct variants
}
impl From for TyKind { impl From for TyKind {
Path => TyKind::Path, Path => TyKind::Path,
TyTuple => TyKind::Tuple, TyTuple => TyKind::Tuple,

View File

@ -227,29 +227,19 @@ impl Display for StructMember {
impl Display for Enum { impl Display for Enum {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 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}")?; write!(f, "enum {name}{gens}")?;
match kind { separate(variants, ",\n")(f.delimit(SPACED_BRACES))
Some(v) => separate(v, ",\n")(f.delimit(SPACED_BRACES)),
None => ";".fmt(f),
}
} }
} }
impl Display for Variant { impl Display for Variant {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let Self { name, kind } = self; let Self { name, kind, body } = self;
write!(f, "{name}{kind}") write!(f, "{name}{kind}")?;
} match body {
} Some(body) => write!(f, " {body}"),
None => Ok(()),
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)),
} }
} }
} }

View File

@ -134,29 +134,14 @@ impl WeightOf for StructMember {
impl WeightOf for Enum { impl WeightOf for Enum {
fn weight_of(&self) -> usize { fn weight_of(&self) -> usize {
let Self { name, gens, variants } = self; let Self { name, gens, variants } = self;
name.weight_of() name.weight_of() + gens.weight_of() + variants.weight_of()
+ gens.weight_of()
+ variants
.as_ref()
.map_or(size_of_val(variants), |v| v.weight_of())
} }
} }
impl WeightOf for Variant { impl WeightOf for Variant {
fn weight_of(&self) -> usize { fn weight_of(&self) -> usize {
let Self { name, kind } = self; let Self { name, kind, body } = self;
name.weight_of() + kind.weight_of() name.weight_of() + kind.weight_of() + body.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(),
}
} }
} }
@ -559,7 +544,7 @@ impl WeightOf for Return {
impl<T: WeightOf> WeightOf for Option<T> { impl<T: WeightOf> WeightOf for Option<T> {
fn weight_of(&self) -> usize { fn weight_of(&self) -> usize {
match self { match self {
Some(t) => t.weight_of(), Some(t) => t.weight_of().max(size_of_val(t)),
None => size_of_val(self), None => size_of_val(self),
} }
} }

View File

@ -143,16 +143,17 @@ pub trait Fold {
Enum { Enum {
name: self.fold_sym(name), name: self.fold_sym(name),
gens: self.fold_generics(gens), 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 { 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) } Variant {
name: self.fold_sym(name),
kind: self.fold_struct_kind(kind),
body: body.map(|e| Box::new(self.fold_expr(*e))),
} }
fn fold_variant_kind(&mut self, kind: VariantKind) -> VariantKind {
or_fold_variant_kind(self, kind)
} }
fn fold_impl(&mut self, i: Impl) -> Impl { fn fold_impl(&mut self, i: Impl) -> Impl {
let Impl { target, body } = i; let Impl { target, body } = i;
@ -486,21 +487,6 @@ pub fn or_fold_struct_kind<F: Fold + ?Sized>(folder: &mut F, kind: StructKind) -
} }
} }
#[inline]
/// Folds a [VariantKind] in the default way
pub fn or_fold_variant_kind<F: Fold + ?Sized>(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] #[inline]
/// Folds an [ImplKind] in the default way /// Folds an [ImplKind] in the default way
pub fn or_fold_impl_kind<F: Fold + ?Sized>(folder: &mut F, kind: ImplKind) -> ImplKind { pub fn or_fold_impl_kind<F: Fold + ?Sized>(folder: &mut F, kind: ImplKind) -> ImplKind {

View File

@ -106,9 +106,6 @@ pub trait Visit<'a>: Sized {
fn visit_variant(&mut self, value: &'a Variant) { fn visit_variant(&mut self, value: &'a Variant) {
value.children(self) value.children(self)
} }
fn visit_variant_kind(&mut self, value: &'a VariantKind) {
value.children(self)
}
fn visit_impl(&mut self, value: &'a Impl) { fn visit_impl(&mut self, value: &'a Impl) {
value.children(self) value.children(self)
} }

View File

@ -276,34 +276,19 @@ impl Walk for Enum {
let Enum { name, gens, variants } = self; let Enum { name, gens, variants } = self;
name.visit_in(v); name.visit_in(v);
gens.visit_in(v); gens.visit_in(v);
if let Some(variants) = variants {
variants.visit_in(v); variants.visit_in(v);
} }
} }
}
impl Walk for Variant { impl Walk for Variant {
#[inline] #[inline]
fn visit_in<'a, V: Visit<'a>>(&'a self, v: &mut V) { fn visit_in<'a, V: Visit<'a>>(&'a self, v: &mut V) {
v.visit_variant(self); v.visit_variant(self);
} }
fn children<'a, V: Visit<'a>>(&'a self, v: &mut V) { 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); name.visit_in(v);
kind.visit_in(v); kind.visit_in(v);
} body.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),
}
} }
} }
impl Walk for Impl { impl Walk for Impl {

View File

@ -153,25 +153,26 @@ impl Interpret for Struct {
} }
impl Interpret for Enum { impl Interpret for Enum {
fn interpret(&self, env: &mut Environment) -> IResult<ConValue> { fn interpret(&self, env: &mut Environment) -> IResult<ConValue> {
let Self { name, gens: _, variants: kind } = self; let Self { name, gens: _, variants } = self;
if let Some(variants) = kind {
env.push_frame(name.to_ref(), Default::default()); env.push_frame(name.to_ref(), Default::default());
for (idx, Variant { name, kind }) in variants.iter().enumerate() { for (idx, Variant { name, kind, body }) in variants.iter().enumerate() {
match kind { match (kind, body) {
VariantKind::Plain => env.insert(*name, Some(ConValue::Int(idx as _))), (StructKind::Empty, None) => env.insert(*name, Some(ConValue::Int(idx as _))),
VariantKind::CLike(idx) => { (StructKind::Empty, Some(idx)) => {
let idx = idx.interpret(env)?; let idx = idx.interpret(env)?;
env.insert(*name, Some(idx)) env.insert(*name, Some(idx))
} }
VariantKind::Tuple(ty) => eprintln!("TODO: Enum-tuple variants: {ty}"), (StructKind::Tuple(_), None) => eprintln!("TODO: Enum-tuple variants: {kind}"),
VariantKind::Struct(_) => eprintln!("TODO: Enum-struct members: {kind}"), (StructKind::Struct(_), None) => {
eprintln!("TODO: Enum-struct members: {kind}")
}
_ => eprintln!("Well-formedness error in {self}"),
} }
} }
let (frame, _) = env let (frame, _) = env
.pop_frame() .pop_frame()
.expect("Frame stack should remain balanced."); .expect("Frame stack should remain balanced.");
env.insert(*name, Some(ConValue::Module(Box::new(frame)))); env.insert(*name, Some(ConValue::Module(Box::new(frame))));
}
Ok(ConValue::Empty) Ok(ConValue::Empty)
} }
} }

View File

@ -529,22 +529,19 @@ impl Parse<'_> for StructKind {
/// Parses the various [kinds of Struct](StructKind) /// Parses the various [kinds of Struct](StructKind)
fn parse(p: &mut Parser<'_>) -> PResult<Self> { fn parse(p: &mut Parser<'_>) -> PResult<Self> {
const P: Parsing = Parsing::StructKind; const P: Parsing = Parsing::StructKind;
Ok(match p.peek_kind(P)? { Ok(match p.peek_kind(P) {
TokenKind::LParen => StructKind::Tuple(delim( Ok(TokenKind::LParen) => StructKind::Tuple(delim(
sep(Ty::parse, TokenKind::Comma, PARENS.1, P), sep(Ty::parse, TokenKind::Comma, PARENS.1, P),
PARENS, PARENS,
P, P,
)(p)?), )(p)?),
TokenKind::LCurly => StructKind::Struct(delim( Ok(TokenKind::LCurly) => StructKind::Struct(delim(
sep(StructMember::parse, TokenKind::Comma, CURLIES.1, P), sep(StructMember::parse, TokenKind::Comma, CURLIES.1, P),
CURLIES, CURLIES,
P, P,
)(p)?), )(p)?),
TokenKind::Semi => { Ok(_) | Err(Error { reason: ErrorKind::EndOfInput, .. }) => StructKind::Empty,
p.consume_peeked(); Err(e) => Err(e)?,
StructKind::Empty
}
got => Err(p.error(ExpectedToken { want: TokenKind::Semi, got }, P))?,
}) })
} }
} }
@ -574,15 +571,11 @@ impl Parse<'_> for Enum {
variants: { variants: {
const P: Parsing = Parsing::EnumKind; const P: Parsing = Parsing::EnumKind;
match p.peek_kind(P)? { match p.peek_kind(P)? {
TokenKind::LCurly => Some(delim( TokenKind::LCurly => delim(
sep(Variant::parse, TokenKind::Comma, TokenKind::RCurly, P), sep(Variant::parse, TokenKind::Comma, TokenKind::RCurly, P),
CURLIES, CURLIES,
P, P,
)(p)?), )(p)?,
TokenKind::Semi => {
p.consume_peeked();
None
}
t => Err(p.error(Unexpected(t), P))?, t => Err(p.error(Unexpected(t), P))?,
} }
}, },
@ -593,34 +586,19 @@ impl Parse<'_> for Enum {
impl Parse<'_> for Variant { impl Parse<'_> for Variant {
/// Parses an [`enum`](Enum) [Variant] /// Parses an [`enum`](Enum) [Variant]
fn parse(p: &mut Parser) -> PResult<Variant> { fn parse(p: &mut Parser) -> PResult<Variant> {
Ok(Variant { name: Sym::parse(p)?, kind: VariantKind::parse(p)? }) let name = Sym::parse(p)?;
} let kind;
let body;
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;
} }
impl Parse<'_> for VariantKind { Ok(Variant { name, kind, body })
/// Parses the various [kinds of Enum Variant](VariantKind)
fn parse(p: &mut Parser<'_>) -> PResult<Self> {
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))?
}
VariantKind::Tuple(tup)
}
_ => VariantKind::Plain,
})
} }
} }

View File

@ -330,34 +330,19 @@ pub mod clangify {
fn print(&self, y: &mut CLangifier) { fn print(&self, y: &mut CLangifier) {
let Self { name, gens: _, variants } = self; let Self { name, gens: _, variants } = self;
y.nest("enum ").p(name).p(" {").endl(); y.nest("enum ").p(name).p(" {").endl();
match variants { for (idx, variant) in variants.iter().enumerate() {
Some(v) => {
for (idx, variant) in v.iter().enumerate() {
if idx > 0 { if idx > 0 {
y.p(",").endl(); y.p(",").endl();
} }
y.p(variant); y.p(variant);
} }
}
None => todo!(),
}
y.endl().p("\n}"); y.endl().p("\n}");
} }
} }
impl CLangify for Variant { impl CLangify for Variant {
fn print(&self, y: &mut CLangifier) { fn print(&self, y: &mut CLangifier) {
let Self { name, kind } = self; let Self { name, kind, body } = self;
y.p(name).p(kind); y.p(name).p(kind).p(body);
}
}
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(" */"),
};
} }
} }
impl CLangify for Impl { impl CLangify for Impl {

View File

@ -293,18 +293,11 @@ pub mod yamlify {
} }
impl Yamlify for Variant { impl Yamlify for Variant {
fn yaml(&self, y: &mut Yamler) { fn yaml(&self, y: &mut Yamler) {
let Self { name, kind } = self; let Self { name, kind, body } = self;
y.key("Variant").pair("name", name).yaml(kind); y.key("Variant")
} .pair("name", name)
} .pair("kind", kind)
impl Yamlify for VariantKind { .pair("body", body);
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),
};
} }
} }
impl Yamlify for Impl { impl Yamlify for Impl {

View File

@ -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<()> { 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()); let parent = table.parent(node).copied().unwrap_or(table.root());
table.add_child(parent, *name, node); table.add_child(parent, *name, node);
match kind { match (kind, body) {
VariantKind::Plain => { (StructKind::Empty, None) => {
table.set_ty(node, TypeKind::Instance(parent)); table.set_ty(node, TypeKind::Adt(Adt::UnitStruct));
Ok(()) Ok(())
} }
VariantKind::CLike(c) => { (StructKind::Empty, Some(c)) => {
table.set_body(node, c); table.set_body(node, c);
table.set_ty(node, TypeKind::Instance(parent)); table.set_ty(node, TypeKind::Adt(Adt::UnitStruct));
Ok(()) Ok(())
} }
VariantKind::Tuple(ty) => { (StructKind::Tuple(ty), None) => {
let ty = ty let ty = TypeKind::Adt(Adt::TupleStruct(
.evaluate(table, node) ty.iter()
.map_err(|e| Error::TypeEval(e, " while categorizing a variant"))?; .map(|ty| ty.evaluate(table, node).map(|ty| (Visibility::Public, ty)))
table.set_ty(node, TypeKind::Instance(ty)); .collect::<Result<_, _>>()?,
));
table.set_ty(node, ty);
Ok(()) Ok(())
} }
VariantKind::Struct(members) => { (StructKind::Struct(members), None) => {
let mut out = vec![]; let mut out = vec![];
for StructMember { vis, name, ty } in members { for StructMember { vis, name, ty } in members {
let ty = ty.evaluate(table, node)?; 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))); table.set_ty(node, TypeKind::Adt(Adt::Struct(out)));
Ok(()) Ok(())
} }
(_, Some(body)) => {
panic!("Unexpected body `{body}` in enum variant `{v}`")
}
} }
} }

View File

@ -4,7 +4,7 @@ use crate::{
handle::Handle, handle::Handle,
source::Source, source::Source,
table::{NodeKind, Table}, table::{NodeKind, Table},
type_kind::{Primitive, TypeKind}, type_kind::TypeKind,
}; };
use cl_ast::{ use cl_ast::{
ItemKind, Sym, ItemKind, Sym,
@ -145,7 +145,7 @@ impl<'a> Visit<'a> for Populator<'_, 'a> {
self.visit(gens); self.visit(gens);
self.visit(variants); self.visit(variants);
let mut children = Vec::new(); let mut children = Vec::new();
for variant in variants.iter().flatten() { for variant in variants.iter() {
let mut entry = self.new_entry(NodeKind::Type); let mut entry = self.new_entry(NodeKind::Type);
variant.visit_in(&mut entry); variant.visit_in(&mut entry);
children.push((variant.name, entry.inner.id())); 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) { 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); let mut entry = self.new_entry(NodeKind::Type);
entry.inner.set_source(Source::Variant(value)); entry.inner.set_source(Source::Variant(value));
entry.visit(kind); entry.visit(kind);
if let Some(body) = body {
entry.inner.set_body(body);
}
let child = entry.inner.id(); let child = entry.inner.id();
self.inner.add_child(*name, child); 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) { fn visit_impl(&mut self, i: &'a cl_ast::Impl) {
let cl_ast::Impl { target, body } = i; let cl_ast::Impl { target, body } = i;
self.inner.set_source(Source::Impl(i)); self.inner.set_source(Source::Impl(i));