cl-typeck: Progress population and categorization
This commit is contained in:
parent
4228324ab3
commit
09fdb14d79
@ -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 {", "}"))
|
||||
|
@ -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<Handle>)> {
|
||||
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(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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(())
|
||||
|
@ -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) {
|
||||
|
@ -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<Handle>)>),
|
||||
Enum(Vec<(Sym, Handle)>),
|
||||
|
||||
/// A structural product type with named members
|
||||
Struct(Vec<(Sym, Visibility, Handle)>),
|
||||
|
@ -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) => {
|
||||
|
Loading…
x
Reference in New Issue
Block a user