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 name: Sym,
pub gens: Generics,
pub variants: Option<Vec<Variant>>,
pub variants: Vec<Variant>,
}
/// 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<Expr>),
Tuple(Ty),
Struct(Vec<StructMember>),
pub kind: StructKind,
pub body: Option<Box<Expr>>,
}
/// Sub-[items](Item) (associated functions, etc.) for a [Ty]

View File

@ -39,10 +39,6 @@ impl_from! {
Vec<Ty> => 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,

View File

@ -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(()),
}
}
}

View File

@ -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<T: WeightOf> WeightOf for Option<T> {
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),
}
}

View File

@ -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<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]
/// Folds an [ImplKind] in the default way
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) {
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)
}

View File

@ -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 {

View File

@ -153,25 +153,26 @@ impl Interpret for Struct {
}
impl Interpret for Enum {
fn interpret(&self, env: &mut Environment) -> IResult<ConValue> {
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)
}
}

View File

@ -529,22 +529,19 @@ impl Parse<'_> for StructKind {
/// Parses the various [kinds of Struct](StructKind)
fn parse(p: &mut Parser<'_>) -> PResult<Self> {
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<Variant> {
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<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))?
}
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 })
}
}

View File

@ -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 {

View File

@ -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 {

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<()> {
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::<Result<_, _>>()?,
));
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}`")
}
}
}

View File

@ -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));