cl-ast: Remove variantkind, as it was redundant
This commit is contained in:
parent
a023551d9f
commit
6c6d2d04a7
@ -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]
|
||||
|
@ -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,
|
||||
|
@ -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(()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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),
|
||||
}
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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 })
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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 {
|
||||
|
@ -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}`")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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));
|
||||
|
Loading…
x
Reference in New Issue
Block a user