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,
}
/// 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
#[derive(Clone, Debug, Default, PartialEq, Eq, Hash)]
pub struct File {
@ -102,6 +92,13 @@ pub enum ItemKind {
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]
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct Alias {
@ -126,20 +123,6 @@ pub struct Static {
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
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct Function {
@ -176,15 +159,7 @@ pub struct StructMember {
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct Enum {
pub name: Sym,
pub kind: EnumKind,
}
/// 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>),
pub variants: Option<Vec<Variant>>,
}
/// A single [Enum] variant
@ -545,6 +520,16 @@ pub struct Index {
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]? `}`
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub struct Structor {

View File

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

View File

@ -93,13 +93,7 @@ pub trait Fold {
}
fn fold_module(&mut self, m: Module) -> Module {
let Module { name, kind } = m;
Module { name: self.fold_sym(name), kind: self.fold_module_kind(kind) }
}
fn fold_module_kind(&mut self, m: ModuleKind) -> ModuleKind {
match m {
ModuleKind::Inline(f) => ModuleKind::Inline(self.fold_file(f)),
ModuleKind::Outline => ModuleKind::Outline,
}
Module { name: self.fold_sym(name), kind: kind.map(|v| self.fold_file(v)) }
}
fn fold_function(&mut self, f: Function) -> Function {
let Function { name, sign, bind, body } = f;
@ -136,11 +130,11 @@ pub trait Fold {
}
}
fn fold_enum(&mut self, e: Enum) -> Enum {
let Enum { name, kind } = e;
Enum { name: self.fold_sym(name), kind: self.fold_enum_kind(kind) }
}
fn fold_enum_kind(&mut self, kind: EnumKind) -> EnumKind {
or_fold_enum_kind(self, kind)
let Enum { name, variants: kind } = e;
Enum {
name: self.fold_sym(name),
variants: kind.map(|v| v.into_iter().map(|v| self.fold_variant(v)).collect()),
}
}
fn fold_variant(&mut self, v: Variant) -> Variant {
let Variant { name, kind } = v;
@ -369,10 +363,7 @@ pub trait Fold {
}
fn fold_addrof(&mut self, a: AddrOf) -> AddrOf {
let AddrOf { mutable, expr } = a;
AddrOf {
mutable: self.fold_mutability(mutable),
expr: Box::new(self.fold_expr(*expr)),
}
AddrOf { mutable: self.fold_mutability(mutable), expr: Box::new(self.fold_expr(*expr)) }
}
fn fold_block(&mut self, b: Block) -> Block {
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]
/// Folds a [StructKind] in the default way
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]
/// Folds a [VariantKind] in the default way
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) {
let Module { name, kind } = m;
self.visit_sym(name);
self.visit_module_kind(kind);
}
fn visit_module_kind(&mut self, kind: &'a ModuleKind) {
or_visit_module_kind(self, kind)
if let Some(f) = kind {
self.visit_file(f)
}
}
fn visit_function(&mut self, f: &'a Function) {
let Function { name, sign, bind, body } = f;
@ -103,12 +102,11 @@ pub trait Visit<'a>: Sized {
self.visit_ty(ty);
}
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_enum_kind(kind);
}
fn visit_enum_kind(&mut self, kind: &'a EnumKind) {
or_visit_enum_kind(self, kind)
if let Some(variants) = kind {
variants.iter().for_each(|v| self.visit_variant(v))
}
}
fn visit_variant(&mut self, v: &'a Variant) {
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) {
match kind {
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) {
match kind {
VariantKind::Plain => {}

View File

@ -25,8 +25,9 @@ impl Fold for NormalizePaths {
fn fold_module(&mut self, m: Module) -> Module {
let Module { name, kind } = m;
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();
Module { name, kind }

View File

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

View File

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

View File

@ -48,15 +48,15 @@ impl ModuleInliner {
}
/// 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));
ModuleKind::Outline
None
}
/// 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));
ModuleKind::Outline
None
}
}
@ -71,11 +71,13 @@ impl Fold for ModuleInliner {
self.path.pop(); // cd ..
Module { name, kind }
}
}
impl ModuleInliner {
/// Attempts to read and parse a file for every module in the tree
fn fold_module_kind(&mut self, m: ModuleKind) -> ModuleKind {
if let ModuleKind::Inline(f) = m {
return ModuleKind::Inline(self.fold_file(f));
fn fold_module_kind(&mut self, m: Option<File>) -> Option<File> {
if let Some(f) = m {
return Some(self.fold_file(f));
}
// cd path/mod.cl
self.path.set_extension("cl");
@ -105,7 +107,7 @@ impl Fold for ModuleInliner {
Ok(file) => {
self.path.set_extension("");
// 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> {
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 {
/// Parses the item list associated with a [Module], if present
fn parse(p: &mut Parser) -> PResult<ModuleKind> {
const P: Parsing = Parsing::ModuleKind;
let inline = delim(Parse::parse, CURLIES, P);
match p.peek_kind(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)),
}
match p.peek_kind(P)? {
TokenKind::LCurly => Some(inline(p)?),
TokenKind::Semi => {
p.consume_peeked();
None
}
got => Err(p.error(ExpectedToken { want: TokenKind::Semi, got }, P))?,
}
},
})
}
}
@ -555,26 +553,23 @@ impl Parse<'_> for Enum {
/// Parses an [`enum`](Enum) definition
fn parse(p: &mut Parser) -> PResult<Enum> {
p.match_type(TokenKind::Enum, Parsing::Enum)?;
Ok(Enum { name: Sym::parse(p)?, kind: EnumKind::parse(p)? })
}
}
impl Parse<'_> for EnumKind {
/// Parses the various [kinds of Enum](EnumKind)
fn parse(p: &mut Parser<'_>) -> PResult<EnumKind> {
const P: Parsing = Parsing::EnumKind;
Ok(match p.peek_kind(P)? {
TokenKind::LCurly => EnumKind::Variants(delim(
sep(Variant::parse, TokenKind::Comma, TokenKind::RCurly, P),
CURLIES,
P,
)(p)?),
TokenKind::Semi => {
p.consume_peeked();
EnumKind::NoVariants
}
t => Err(p.error(Unexpected(t), P))?,
Ok(Enum {
name: Sym::parse(p)?,
variants: {
const P: Parsing = Parsing::EnumKind;
match p.peek_kind(P)? {
TokenKind::LCurly => Some(delim(
sep(Variant::parse, TokenKind::Comma, TokenKind::RCurly, P),
CURLIES,
P,
)(p)?),
TokenKind::Semi => {
p.consume_peeked();
None
}
t => Err(p.error(Unexpected(t), P))?,
}
},
})
}
}

View File

@ -239,14 +239,6 @@ pub mod yamlify {
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 {
fn yaml(&self, y: &mut Yamler) {
let Self { name, sign, bind, body } = self;
@ -280,18 +272,10 @@ pub mod yamlify {
}
impl Yamlify for Enum {
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);
}
}
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 {
fn yaml(&self, y: &mut Yamler) {
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<()> {
let Enum { name: _, kind } = e;
let Enum { name: _, variants: kind } = e;
let kind = match kind {
EnumKind::NoVariants => TypeKind::Adt(Adt::Enum(vec![])),
EnumKind::Variants(variants) => {
None => TypeKind::Adt(Adt::Enum(vec![])),
Some(variants) => {
let mut out_vars = vec![];
for v in variants {
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.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) {
@ -121,11 +123,13 @@ impl<'a> Visit<'a> for Populator<'_, 'a> {
}
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.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) {