From 09fdb14d7911ef32f97db49954d099eb3e3d6a27 Mon Sep 17 00:00:00 2001 From: John Date: Mon, 5 May 2025 04:54:33 -0400 Subject: [PATCH] cl-typeck: Progress population and categorization --- compiler/cl-typeck/src/entry/display.rs | 9 +-- compiler/cl-typeck/src/stage/categorize.rs | 64 ++++++++++---------- compiler/cl-typeck/src/stage/infer/engine.rs | 15 ++--- compiler/cl-typeck/src/stage/populate.rs | 58 ++++++++++++++++-- compiler/cl-typeck/src/type_kind.rs | 2 +- compiler/cl-typeck/src/type_kind/display.rs | 5 +- 6 files changed, 95 insertions(+), 58 deletions(-) diff --git a/compiler/cl-typeck/src/entry/display.rs b/compiler/cl-typeck/src/entry/display.rs index 9e3a393..805393d 100644 --- a/compiler/cl-typeck/src/entry/display.rs +++ b/compiler/cl-typeck/src/entry/display.rs @@ -66,12 +66,9 @@ fn write_adt(adt: &Adt, h: &Entry, f: &mut impl Write) -> fmt::Result { let mut variants = variants.iter(); separate(", ", || { variants.next().map(|(name, def)| { - move |f: &mut Delimit<_>| match def { - Some(def) => { - write!(f, "{name}: ")?; - write_name_or(h.with_id(*def), f) - } - None => write!(f, "{name}"), + move |f: &mut Delimit<_>| { + write!(f, "{name}: ")?; + write_name_or(h.with_id(*def), f) } }) })(f.delimit_with("enum {", "}")) diff --git a/compiler/cl-typeck/src/stage/categorize.rs b/compiler/cl-typeck/src/stage/categorize.rs index 7e5bfcd..8a682b7 100644 --- a/compiler/cl-typeck/src/stage/categorize.rs +++ b/compiler/cl-typeck/src/stage/categorize.rs @@ -31,7 +31,7 @@ pub fn categorize(table: &mut Table, node: Handle) -> CatResult<()> { Source::Module(_) => Ok(()), Source::Alias(a) => cat_alias(table, node, a), Source::Enum(e) => cat_enum(table, node, e), - Source::Variant(_) => Ok(()), + Source::Variant(v) => cat_variant(table, node, v), Source::Struct(s) => cat_struct(table, node, s), Source::Const(c) => cat_const(table, node, c), Source::Static(s) => cat_static(table, node, s), @@ -98,51 +98,51 @@ fn cat_member( Ok((*name, *vis, ty.evaluate(table, node)?)) } -fn cat_enum<'a>(table: &mut Table<'a>, node: Handle, e: &'a Enum) -> CatResult<()> { - let Enum { name: _, gens: _, variants: kind } = e; - // TODO: Genereics - let kind = match kind { - 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)?) - } - TypeKind::Adt(Adt::Enum(out_vars)) - } - }; +fn cat_enum<'a>(_table: &mut Table<'a>, _node: Handle, e: &'a Enum) -> CatResult<()> { + let Enum { name: _, gens: _, variants: _ } = e; - table.set_ty(node, kind); + // table.set_ty(node, kind); Ok(()) } -fn cat_variant<'a>( - table: &mut Table<'a>, - node: Handle, - v: &'a Variant, -) -> CatResult<(Sym, Option)> { +fn cat_variant<'a>(table: &mut Table<'a>, node: Handle, v: &'a Variant) -> CatResult<()> { let Variant { name, kind } = v; + let parent = table.parent(node).copied().unwrap_or(table.root()); + table.add_child(parent, *name, node); match kind { - VariantKind::Plain => Ok((*name, None)), - VariantKind::CLike(c) => todo!("enum-variant constant {c}"), + VariantKind::Plain => { + table.set_ty(node, TypeKind::Instance(parent)); + Ok(()) + } + VariantKind::CLike(c) => { + table.set_body(node, c); + table.set_ty(node, TypeKind::Instance(parent)); + Ok(()) + } VariantKind::Tuple(ty) => { let ty = ty .evaluate(table, node) .map_err(|e| Error::TypeEval(e, " while categorizing a variant"))?; - Ok((*name, Some(ty))) + table.set_ty(node, TypeKind::Instance(ty)); + Ok(()) } VariantKind::Struct(members) => { let mut out = vec![]; - for m in members { - out.push(cat_member(table, node, m)?) - } - let kind = TypeKind::Adt(Adt::Struct(out)); + for StructMember { vis, name, ty } in members { + let ty = ty.evaluate(table, node)?; + out.push((*name, *vis, ty)); - let mut h = node.to_entry_mut(table); - let mut variant = h.new_entry(NodeKind::Type); - variant.set_source(Source::Variant(v)); - variant.set_ty(kind); - Ok((*name, Some(variant.id()))) + let mut this = node.to_entry_mut(table); + let mut child = this.new_entry(NodeKind::Type); + child.set_source(Source::Variant(v)); + child.set_ty(TypeKind::Instance(ty)); + + let child = child.id(); + this.add_child(*name, child); + } + + table.set_ty(node, TypeKind::Adt(Adt::Struct(out))); + Ok(()) } } } diff --git a/compiler/cl-typeck/src/stage/infer/engine.rs b/compiler/cl-typeck/src/stage/infer/engine.rs index bea6477..0fd6101 100644 --- a/compiler/cl-typeck/src/stage/infer/engine.rs +++ b/compiler/cl-typeck/src/stage/infer/engine.rs @@ -274,9 +274,7 @@ impl<'table, 'a> InferenceEngine<'table, 'a> { &TypeKind::Array(h, _) => self.is_generic(h), &TypeKind::Instance(h) => self.is_generic(h), TypeKind::Primitive(_) => false, - TypeKind::Adt(Adt::Enum(tys)) => tys - .iter() - .any(|(_, ty)| ty.is_some_and(|ty| self.is_generic(ty))), + TypeKind::Adt(Adt::Enum(tys)) => tys.iter().any(|(_, ty)| self.is_generic(*ty)), TypeKind::Adt(Adt::Struct(tys)) => tys.iter().any(|&(_, _, ty)| self.is_generic(ty)), TypeKind::Adt(Adt::TupleStruct(tys)) => tys.iter().any(|&(_, ty)| self.is_generic(ty)), TypeKind::Adt(Adt::UnitStruct) => false, @@ -313,7 +311,7 @@ impl<'table, 'a> InferenceEngine<'table, 'a> { TypeKind::Adt(Adt::Enum(tys)) => { let tys = tys .into_iter() - .map(|(name, ty)| (name, ty.map(|ty| self.deep_clone(ty)))) + .map(|(name, ty)| (name, self.deep_clone(ty))) .collect(); self.table.anon_type(TypeKind::Adt(Adt::Enum(tys))) } @@ -385,9 +383,9 @@ impl<'table, 'a> InferenceEngine<'table, 'a> { }; match ty { TypeKind::Instance(other) => self.occurs_in(this, *other), - TypeKind::Adt(Adt::Enum(items)) => items - .iter() - .any(|(_, i)| i.is_some_and(|other| self.occurs_in(this, other))), + TypeKind::Adt(Adt::Enum(items)) => { + items.iter().any(|(_, other)| self.occurs_in(this, *other)) + } TypeKind::Adt(Adt::Struct(items)) => items .iter() .any(|(_, _, other)| self.occurs_in(this, *other)), @@ -462,10 +460,9 @@ impl<'table, 'a> InferenceEngine<'table, 'a> { if ia.len() == ib.len() => { for ((na, a), (nb, b)) in ia.clone().into_iter().zip(ib.clone().into_iter()) { - if na != nb || a.is_some() != b.is_some() { + if na != nb { return Err(InferenceError::Mismatch(ah, bh)); } - let (Some(a), Some(b)) = (a, b) else { continue }; self.unify(a, b)?; } Ok(()) diff --git a/compiler/cl-typeck/src/stage/populate.rs b/compiler/cl-typeck/src/stage/populate.rs index a2ca1df..974cf21 100644 --- a/compiler/cl-typeck/src/stage/populate.rs +++ b/compiler/cl-typeck/src/stage/populate.rs @@ -4,8 +4,12 @@ use crate::{ handle::Handle, source::Source, table::{NodeKind, Table}, + type_kind::{Primitive, TypeKind}, +}; +use cl_ast::{ + ItemKind, Sym, + ast_visitor::{Visit, Walk}, }; -use cl_ast::{ItemKind, Sym, ast_visitor::Visit}; #[derive(Debug)] pub struct Populator<'t, 'a> { @@ -60,6 +64,17 @@ impl<'a> Visit<'a> for Populator<'_, 'a> { } } + fn visit_generics(&mut self, value: &'a cl_ast::Generics) { + let cl_ast::Generics { vars } = value; + for var in vars { + let mut entry = self.inner.new_entry(NodeKind::Type); + entry.set_ty(TypeKind::Variable); + + let id = entry.id(); + self.inner.add_child(*var, id); + } + } + fn visit_alias(&mut self, a: &'a cl_ast::Alias) { let cl_ast::Alias { name, from } = a; self.inner.set_source(Source::Alias(a)); @@ -98,11 +113,12 @@ impl<'a> Visit<'a> for Populator<'_, 'a> { } fn visit_function(&mut self, f: &'a cl_ast::Function) { - let cl_ast::Function { name, gens: _, sign, bind, body } = f; + let cl_ast::Function { name, gens, sign, bind, body } = f; // TODO: populate generics? self.inner.set_source(Source::Function(f)); self.set_name(*name); + self.visit(gens); self.visit(sign); self.visit(bind); @@ -113,21 +129,51 @@ impl<'a> Visit<'a> for Populator<'_, 'a> { } fn visit_struct(&mut self, s: &'a cl_ast::Struct) { - let cl_ast::Struct { name, gens: _, kind } = s; - // TODO: populate generics? + let cl_ast::Struct { name, gens, kind } = s; self.inner.set_source(Source::Struct(s)); self.set_name(*name); + self.visit(gens); self.visit(kind); } fn visit_enum(&mut self, e: &'a cl_ast::Enum) { - let cl_ast::Enum { name, gens: _, variants } = e; - // TODO: populate generics? + let cl_ast::Enum { name, gens, variants } = e; self.inner.set_source(Source::Enum(e)); self.set_name(*name); + self.visit(gens); self.visit(variants); + let mut children = Vec::new(); + for variant in variants.iter().flatten() { + let mut entry = self.new_entry(NodeKind::Type); + variant.visit_in(&mut entry); + children.push((variant.name, entry.inner.id())); + } + self.inner + .set_ty(TypeKind::Adt(crate::type_kind::Adt::Enum(children))); + } + + fn visit_variant(&mut self, value: &'a cl_ast::Variant) { + let cl_ast::Variant { name, kind } = value; + let mut entry = self.new_entry(NodeKind::Type); + entry.inner.set_source(Source::Variant(value)); + entry.visit(kind); + + 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) { diff --git a/compiler/cl-typeck/src/type_kind.rs b/compiler/cl-typeck/src/type_kind.rs index 5563f34..b71ed48 100644 --- a/compiler/cl-typeck/src/type_kind.rs +++ b/compiler/cl-typeck/src/type_kind.rs @@ -42,7 +42,7 @@ pub enum TypeKind { #[derive(Clone, Debug, PartialEq, Eq, Hash)] pub enum Adt { /// A union-like enum type - Enum(Vec<(Sym, Option)>), + Enum(Vec<(Sym, Handle)>), /// A structural product type with named members Struct(Vec<(Sym, Visibility, Handle)>), diff --git a/compiler/cl-typeck/src/type_kind/display.rs b/compiler/cl-typeck/src/type_kind/display.rs index d7741a4..104341f 100644 --- a/compiler/cl-typeck/src/type_kind/display.rs +++ b/compiler/cl-typeck/src/type_kind/display.rs @@ -38,10 +38,7 @@ impl Display for Adt { let mut variants = variants.iter(); separate(", ", || { let (name, def) = variants.next()?; - Some(move |f: &mut Delimit<_>| match def { - Some(def) => write!(f, "{name}: #{def}"), - None => write!(f, "{name}"), - }) + Some(move |f: &mut Delimit<_>| write!(f, "{name}: #{def}")) })(f.delimit_with("enum {", "}")) } Adt::Struct(members) => {