cl-ast: Remove Option-like "*Kind"s

This commit is contained in:
John 2025-03-11 23:32:58 -05:00
parent 2fc847fff2
commit fdf076c272
12 changed files with 105 additions and 190 deletions

View File

@ -31,16 +31,6 @@ pub enum Visibility {
Public, Public,
} }
/// A [Literal]: 0x42, 1e123, 2.4, "Hello"
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub enum Literal {
Bool(bool),
Char(char),
Int(u128),
Float(u64),
String(String),
}
/// A list of [Item]s /// A list of [Item]s
#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)] #[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
pub struct File { pub struct File {
@ -102,6 +92,13 @@ pub enum ItemKind {
Use(Use), Use(Use),
} }
/// An ordered collection of [Items](Item)
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct Module {
pub name: Sym,
pub kind: Option<File>,
}
/// An alias to another [Ty] /// An alias to another [Ty]
#[derive(Clone, Debug, PartialEq, Eq, Hash)] #[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct Alias { pub struct Alias {
@ -126,20 +123,6 @@ pub struct Static {
pub init: Box<Expr>, pub init: Box<Expr>,
} }
/// An ordered collection of [Items](Item)
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct Module {
pub name: Sym,
pub kind: ModuleKind,
}
/// The contents of a [Module], if they're in the same file
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub enum ModuleKind {
Inline(File),
Outline,
}
/// Code, and the interface to that code /// Code, and the interface to that code
#[derive(Clone, Debug, PartialEq, Eq, Hash)] #[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct Function { pub struct Function {
@ -176,15 +159,7 @@ pub struct StructMember {
#[derive(Clone, Debug, PartialEq, Eq, Hash)] #[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct Enum { pub struct Enum {
pub name: Sym, pub name: Sym,
pub kind: EnumKind, pub variants: Option<Vec<Variant>>,
}
/// An [Enum]'s [Variant]s, if it has a variant block
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub enum EnumKind {
/// Represents an enum with no variants
NoVariants,
Variants(Vec<Variant>),
} }
/// A single [Enum] variant /// A single [Enum] variant
@ -545,6 +520,16 @@ pub struct Index {
pub indices: Vec<Expr>, pub indices: Vec<Expr>,
} }
/// A [Literal]: 0x42, 1e123, 2.4, "Hello"
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub enum Literal {
Bool(bool),
Char(char),
Int(u128),
Float(u64),
String(String),
}
/// A [Struct creation](Structor) expression: [Path] `{` ([Fielder] `,`)* [Fielder]? `}` /// A [Struct creation](Structor) expression: [Path] `{` ([Fielder] `,`)* [Fielder]? `}`
#[derive(Clone, Debug, PartialEq, Eq, Hash)] #[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct Structor { pub struct Structor {

View File

@ -143,18 +143,13 @@ mod display {
impl Display for Module { impl Display for Module {
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 } = self;
write!(f, "mod {name}{kind}") write!(f, "mod {name}")?;
} match kind {
} Some(items) => {
impl Display for ModuleKind {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
ModuleKind::Inline(items) => {
' '.fmt(f)?; ' '.fmt(f)?;
write!(f.delimit(BRACES), "{items}") write!(f.delimit(BRACES), "{items}")
} }
ModuleKind::Outline => ';'.fmt(f), None => Ok(())
} }
} }
} }
@ -218,16 +213,11 @@ mod display {
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, kind } = self; let Self { name, variants: kind } = self;
write!(f, "enum {name}{kind}") write!(f, "enum {name}")?;
} match kind {
} Some(v) => separate(v, ",\n")(f.delimit(SPACED_BRACES)),
None => ";".fmt(f),
impl Display for EnumKind {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
EnumKind::NoVariants => ';'.fmt(f),
EnumKind::Variants(v) => separate(v, ",\n")(f.delimit(SPACED_BRACES)),
} }
} }
} }
@ -795,9 +785,6 @@ mod convert {
Vec<Ty> => StructKind::Tuple, Vec<Ty> => StructKind::Tuple,
// TODO: Struct members in struct // TODO: Struct members in struct
} }
impl From for EnumKind {
Vec<Variant> => EnumKind::Variants,
}
impl From for VariantKind { impl From for VariantKind {
u128 => VariantKind::CLike, u128 => VariantKind::CLike,
Ty => VariantKind::Tuple, Ty => VariantKind::Tuple,

View File

@ -93,13 +93,7 @@ pub trait Fold {
} }
fn fold_module(&mut self, m: Module) -> Module { fn fold_module(&mut self, m: Module) -> Module {
let Module { name, kind } = m; let Module { name, kind } = m;
Module { name: self.fold_sym(name), kind: self.fold_module_kind(kind) } Module { name: self.fold_sym(name), kind: kind.map(|v| self.fold_file(v)) }
}
fn fold_module_kind(&mut self, m: ModuleKind) -> ModuleKind {
match m {
ModuleKind::Inline(f) => ModuleKind::Inline(self.fold_file(f)),
ModuleKind::Outline => ModuleKind::Outline,
}
} }
fn fold_function(&mut self, f: Function) -> Function { fn fold_function(&mut self, f: Function) -> Function {
let Function { name, sign, bind, body } = f; let Function { name, sign, bind, body } = f;
@ -136,11 +130,11 @@ pub trait Fold {
} }
} }
fn fold_enum(&mut self, e: Enum) -> Enum { fn fold_enum(&mut self, e: Enum) -> Enum {
let Enum { name, kind } = e; let Enum { name, variants: kind } = e;
Enum { name: self.fold_sym(name), kind: self.fold_enum_kind(kind) } Enum {
} name: self.fold_sym(name),
fn fold_enum_kind(&mut self, kind: EnumKind) -> EnumKind { variants: kind.map(|v| v.into_iter().map(|v| self.fold_variant(v)).collect()),
or_fold_enum_kind(self, kind) }
} }
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 } = v;
@ -369,10 +363,7 @@ pub trait Fold {
} }
fn fold_addrof(&mut self, a: AddrOf) -> AddrOf { fn fold_addrof(&mut self, a: AddrOf) -> AddrOf {
let AddrOf { mutable, expr } = a; let AddrOf { mutable, expr } = a;
AddrOf { AddrOf { mutable: self.fold_mutability(mutable), expr: Box::new(self.fold_expr(*expr)) }
mutable: self.fold_mutability(mutable),
expr: Box::new(self.fold_expr(*expr)),
}
} }
fn fold_block(&mut self, b: Block) -> Block { fn fold_block(&mut self, b: Block) -> Block {
let Block { stmts } = b; let Block { stmts } = b;
@ -465,15 +456,6 @@ pub fn or_fold_item_kind<F: Fold + ?Sized>(folder: &mut F, kind: ItemKind) -> It
} }
} }
#[inline]
/// Folds a [ModuleKind] in the default way
pub fn or_fold_module_kind<F: Fold + ?Sized>(folder: &mut F, kind: ModuleKind) -> ModuleKind {
match kind {
ModuleKind::Inline(f) => ModuleKind::Inline(folder.fold_file(f)),
ModuleKind::Outline => ModuleKind::Outline,
}
}
#[inline] #[inline]
/// Folds a [StructKind] in the default way /// Folds a [StructKind] in the default way
pub fn or_fold_struct_kind<F: Fold + ?Sized>(folder: &mut F, kind: StructKind) -> StructKind { pub fn or_fold_struct_kind<F: Fold + ?Sized>(folder: &mut F, kind: StructKind) -> StructKind {
@ -490,17 +472,6 @@ pub fn or_fold_struct_kind<F: Fold + ?Sized>(folder: &mut F, kind: StructKind) -
} }
} }
#[inline]
/// Folds an [EnumKind] in the default way
pub fn or_fold_enum_kind<F: Fold + ?Sized>(folder: &mut F, kind: EnumKind) -> EnumKind {
match kind {
EnumKind::NoVariants => EnumKind::NoVariants,
EnumKind::Variants(v) => {
EnumKind::Variants(v.into_iter().map(|v| folder.fold_variant(v)).collect())
}
}
}
#[inline] #[inline]
/// Folds a [VariantKind] in the default way /// Folds a [VariantKind] in the default way
pub fn or_fold_variant_kind<F: Fold + ?Sized>(folder: &mut F, kind: VariantKind) -> VariantKind { pub fn or_fold_variant_kind<F: Fold + ?Sized>(folder: &mut F, kind: VariantKind) -> VariantKind {

View File

@ -74,10 +74,9 @@ pub trait Visit<'a>: Sized {
fn visit_module(&mut self, m: &'a Module) { fn visit_module(&mut self, m: &'a Module) {
let Module { name, kind } = m; let Module { name, kind } = m;
self.visit_sym(name); self.visit_sym(name);
self.visit_module_kind(kind); if let Some(f) = kind {
} self.visit_file(f)
fn visit_module_kind(&mut self, kind: &'a ModuleKind) { }
or_visit_module_kind(self, kind)
} }
fn visit_function(&mut self, f: &'a Function) { fn visit_function(&mut self, f: &'a Function) {
let Function { name, sign, bind, body } = f; let Function { name, sign, bind, body } = f;
@ -103,12 +102,11 @@ pub trait Visit<'a>: Sized {
self.visit_ty(ty); self.visit_ty(ty);
} }
fn visit_enum(&mut self, e: &'a Enum) { fn visit_enum(&mut self, e: &'a Enum) {
let Enum { name, kind } = e; let Enum { name, variants: kind } = e;
self.visit_sym(name); self.visit_sym(name);
self.visit_enum_kind(kind); if let Some(variants) = kind {
} variants.iter().for_each(|v| self.visit_variant(v))
fn visit_enum_kind(&mut self, kind: &'a EnumKind) { }
or_visit_enum_kind(self, kind)
} }
fn visit_variant(&mut self, v: &'a Variant) { fn visit_variant(&mut self, v: &'a Variant) {
let Variant { name, kind } = v; let Variant { name, kind } = v;
@ -406,13 +404,6 @@ pub fn or_visit_item_kind<'a, V: Visit<'a>>(visitor: &mut V, kind: &'a ItemKind)
} }
} }
pub fn or_visit_module_kind<'a, V: Visit<'a>>(visitor: &mut V, kind: &'a ModuleKind) {
match kind {
ModuleKind::Inline(f) => visitor.visit_file(f),
ModuleKind::Outline => {}
}
}
pub fn or_visit_struct_kind<'a, V: Visit<'a>>(visitor: &mut V, kind: &'a StructKind) { pub fn or_visit_struct_kind<'a, V: Visit<'a>>(visitor: &mut V, kind: &'a StructKind) {
match kind { match kind {
StructKind::Empty => {} StructKind::Empty => {}
@ -421,13 +412,6 @@ pub fn or_visit_struct_kind<'a, V: Visit<'a>>(visitor: &mut V, kind: &'a StructK
} }
} }
pub fn or_visit_enum_kind<'a, V: Visit<'a>>(visitor: &mut V, kind: &'a EnumKind) {
match kind {
EnumKind::NoVariants => {}
EnumKind::Variants(variants) => variants.iter().for_each(|v| visitor.visit_variant(v)),
}
}
pub fn or_visit_variant_kind<'a, V: Visit<'a>>(visitor: &mut V, kind: &'a VariantKind) { pub fn or_visit_variant_kind<'a, V: Visit<'a>>(visitor: &mut V, kind: &'a VariantKind) {
match kind { match kind {
VariantKind::Plain => {} VariantKind::Plain => {}

View File

@ -26,7 +26,8 @@ impl Fold for NormalizePaths {
let Module { name, kind } = m; let Module { name, kind } = m;
self.path.push(PathPart::Ident(name)); self.path.push(PathPart::Ident(name));
let (name, kind) = (self.fold_sym(name), self.fold_module_kind(kind)); let name = self.fold_sym(name);
let kind = kind.map(|f| self.fold_file(f));
self.path.pop(); self.path.pop();
Module { name, kind } Module { name, kind }

View File

@ -3,6 +3,8 @@
//! The most permanent fix is a temporary one. //! The most permanent fix is a temporary one.
use cl_ast::{format::FmtAdapter, Expr, Sym}; use cl_ast::{format::FmtAdapter, Expr, Sym};
use crate::env::Place;
use super::{ use super::{
builtin::Builtin, builtin::Builtin,
error::{Error, IResult}, error::{Error, IResult},
@ -52,9 +54,9 @@ pub enum ConValue {
/// A string /// A string
String(Sym), String(Sym),
/// A reference /// A reference
Ref(usize), Ref(Place),
/// A reference to an array /// A reference to an array
Slice(usize, usize), Slice(Place, usize),
/// An Array /// An Array
Array(Box<[ConValue]>), Array(Box<[ConValue]>),
/// A tuple /// A tuple

View File

@ -91,8 +91,8 @@ impl Interpret for Module {
let Self { name, kind } = self; let Self { name, kind } = self;
env.push_frame(Interned::to_ref(name), Default::default()); env.push_frame(Interned::to_ref(name), Default::default());
let out = match kind { let out = match kind {
ModuleKind::Inline(file) => file.interpret(env), Some(file) => file.interpret(env),
ModuleKind::Outline => { None => {
eprintln!("Module {name} specified, but not imported."); eprintln!("Module {name} specified, but not imported.");
Ok(ConValue::Empty) Ok(ConValue::Empty)
} }
@ -152,8 +152,8 @@ 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, kind } = self; let Self { name, variants: kind } = self;
if let EnumKind::Variants(variants) = kind { if let Some(variants) = kind {
env.push_frame(Sym::to_ref(name), Default::default()); env.push_frame(Sym::to_ref(name), Default::default());
for (idx, Variant { name, kind }) in variants.iter().enumerate() { for (idx, Variant { name, kind }) in variants.iter().enumerate() {
match kind { match kind {

View File

@ -48,15 +48,15 @@ impl ModuleInliner {
} }
/// Records an [I/O error](std::io::Error) for later /// Records an [I/O error](std::io::Error) for later
fn handle_io_error(&mut self, error: std::io::Error) -> ModuleKind { fn handle_io_error(&mut self, error: std::io::Error) -> Option<File> {
self.io_errs.push((self.path.clone(), error)); self.io_errs.push((self.path.clone(), error));
ModuleKind::Outline None
} }
/// Records a [parse error](crate::error::Error) for later /// Records a [parse error](crate::error::Error) for later
fn handle_parse_error(&mut self, error: crate::error::Error) -> ModuleKind { fn handle_parse_error(&mut self, error: crate::error::Error) -> Option<File> {
self.parse_errs.push((self.path.clone(), error)); self.parse_errs.push((self.path.clone(), error));
ModuleKind::Outline None
} }
} }
@ -71,11 +71,13 @@ impl Fold for ModuleInliner {
self.path.pop(); // cd .. self.path.pop(); // cd ..
Module { name, kind } Module { name, kind }
} }
}
impl ModuleInliner {
/// Attempts to read and parse a file for every module in the tree /// Attempts to read and parse a file for every module in the tree
fn fold_module_kind(&mut self, m: ModuleKind) -> ModuleKind { fn fold_module_kind(&mut self, m: Option<File>) -> Option<File> {
if let ModuleKind::Inline(f) = m { if let Some(f) = m {
return ModuleKind::Inline(self.fold_file(f)); return Some(self.fold_file(f));
} }
// cd path/mod.cl // cd path/mod.cl
self.path.set_extension("cl"); self.path.set_extension("cl");
@ -105,7 +107,7 @@ impl Fold for ModuleInliner {
Ok(file) => { Ok(file) => {
self.path.set_extension(""); self.path.set_extension("");
// The newly loaded module may need further inlining // The newly loaded module may need further inlining
ModuleKind::Inline(self.fold_file(file)) Some(self.fold_file(file))
} }
} }
} }

View File

@ -414,24 +414,22 @@ impl Parse<'_> for Module {
fn parse(p: &mut Parser<'_>) -> PResult<Self> { fn parse(p: &mut Parser<'_>) -> PResult<Self> {
p.consume_peeked(); p.consume_peeked();
Ok(Module { name: Sym::parse(p)?, kind: ModuleKind::parse(p)? }) Ok(Module {
} name: Sym::parse(p)?,
} kind: {
const P: Parsing = Parsing::ModuleKind;
let inline = delim(Parse::parse, CURLIES, P);
impl Parse<'_> for ModuleKind { match p.peek_kind(P)? {
/// Parses the item list associated with a [Module], if present TokenKind::LCurly => Some(inline(p)?),
fn parse(p: &mut Parser) -> PResult<ModuleKind> { TokenKind::Semi => {
const P: Parsing = Parsing::ModuleKind; p.consume_peeked();
let inline = delim(Parse::parse, CURLIES, P); None
}
match p.peek_kind(P)? { got => Err(p.error(ExpectedToken { want: TokenKind::Semi, got }, P))?,
TokenKind::LCurly => Ok(ModuleKind::Inline(inline(p)?)), }
TokenKind::Semi => { },
p.consume_peeked(); })
Ok(ModuleKind::Outline)
}
got => Err(p.error(ExpectedToken { want: TokenKind::Semi, got }, P)),
}
} }
} }
@ -555,26 +553,23 @@ impl Parse<'_> for Enum {
/// Parses an [`enum`](Enum) definition /// Parses an [`enum`](Enum) definition
fn parse(p: &mut Parser) -> PResult<Enum> { fn parse(p: &mut Parser) -> PResult<Enum> {
p.match_type(TokenKind::Enum, Parsing::Enum)?; p.match_type(TokenKind::Enum, Parsing::Enum)?;
Ok(Enum {
Ok(Enum { name: Sym::parse(p)?, kind: EnumKind::parse(p)? }) name: Sym::parse(p)?,
} variants: {
} const P: Parsing = Parsing::EnumKind;
match p.peek_kind(P)? {
impl Parse<'_> for EnumKind { TokenKind::LCurly => Some(delim(
/// Parses the various [kinds of Enum](EnumKind) sep(Variant::parse, TokenKind::Comma, TokenKind::RCurly, P),
fn parse(p: &mut Parser<'_>) -> PResult<EnumKind> { CURLIES,
const P: Parsing = Parsing::EnumKind; P,
Ok(match p.peek_kind(P)? { )(p)?),
TokenKind::LCurly => EnumKind::Variants(delim( TokenKind::Semi => {
sep(Variant::parse, TokenKind::Comma, TokenKind::RCurly, P), p.consume_peeked();
CURLIES, None
P, }
)(p)?), t => Err(p.error(Unexpected(t), P))?,
TokenKind::Semi => { }
p.consume_peeked(); },
EnumKind::NoVariants
}
t => Err(p.error(Unexpected(t), P))?,
}) })
} }
} }

View File

@ -239,14 +239,6 @@ pub mod yamlify {
y.key("Module").pair("name", name).yaml(kind); y.key("Module").pair("name", name).yaml(kind);
} }
} }
impl Yamlify for ModuleKind {
fn yaml(&self, y: &mut Yamler) {
match self {
ModuleKind::Inline(f) => y.yaml(f),
ModuleKind::Outline => y,
};
}
}
impl Yamlify for Function { impl Yamlify for Function {
fn yaml(&self, y: &mut Yamler) { fn yaml(&self, y: &mut Yamler) {
let Self { name, sign, bind, body } = self; let Self { name, sign, bind, body } = self;
@ -280,18 +272,10 @@ pub mod yamlify {
} }
impl Yamlify for Enum { impl Yamlify for Enum {
fn yaml(&self, y: &mut Yamler) { fn yaml(&self, y: &mut Yamler) {
let Self { name, kind } = self; let Self { name, variants: kind } = self;
y.key("Enum").pair("name", name).yaml(kind); y.key("Enum").pair("name", name).yaml(kind);
} }
} }
impl Yamlify for EnumKind {
fn yaml(&self, y: &mut Yamler) {
match self {
EnumKind::NoVariants => y,
EnumKind::Variants(v) => y.yaml(v),
};
}
}
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 } = self;

View File

@ -99,10 +99,10 @@ fn cat_member(
} }
fn cat_enum<'a>(table: &mut Table<'a>, node: Handle, e: &'a Enum) -> CatResult<()> { fn cat_enum<'a>(table: &mut Table<'a>, node: Handle, e: &'a Enum) -> CatResult<()> {
let Enum { name: _, kind } = e; let Enum { name: _, variants: kind } = e;
let kind = match kind { let kind = match kind {
EnumKind::NoVariants => TypeKind::Adt(Adt::Enum(vec![])), None => TypeKind::Adt(Adt::Enum(vec![])),
EnumKind::Variants(variants) => { Some(variants) => {
let mut out_vars = vec![]; let mut out_vars = vec![];
for v in variants { for v in variants {
out_vars.push(cat_variant(table, node, v)?) out_vars.push(cat_variant(table, node, v)?)

View File

@ -97,7 +97,9 @@ impl<'a> Visit<'a> for Populator<'_, 'a> {
self.inner.set_source(Source::Module(m)); self.inner.set_source(Source::Module(m));
self.set_name(*name); self.set_name(*name);
self.visit_module_kind(kind); if let Some(file) = kind {
self.visit_file(file);
}
} }
fn visit_function(&mut self, f: &'a cl_ast::Function) { fn visit_function(&mut self, f: &'a cl_ast::Function) {
@ -121,11 +123,13 @@ impl<'a> Visit<'a> for Populator<'_, 'a> {
} }
fn visit_enum(&mut self, e: &'a cl_ast::Enum) { fn visit_enum(&mut self, e: &'a cl_ast::Enum) {
let cl_ast::Enum { name, kind } = e; let cl_ast::Enum { name, variants } = e;
self.inner.set_source(Source::Enum(e)); self.inner.set_source(Source::Enum(e));
self.set_name(*name); self.set_name(*name);
self.visit_enum_kind(kind); if let Some(variants) = variants {
variants.iter().for_each(|v| self.visit_variant(v));
}
} }
fn visit_impl(&mut self, i: &'a cl_ast::Impl) { fn visit_impl(&mut self, i: &'a cl_ast::Impl) {