cl-typeck: Store def metadata in a Node

I'm not overly proud of this code, but it currently works. Will refactor later.
This commit is contained in:
John 2024-04-29 15:40:30 -05:00
parent d7ce33e457
commit 7c73fd335c
8 changed files with 351 additions and 253 deletions

View File

@ -5,7 +5,11 @@ use cl_ast::{
use cl_lexer::Lexer;
use cl_parser::{inliner::ModuleInliner, Parser};
use cl_typeck::{
definition::Def, name_collector::NameCollector, project::Project, type_resolver::resolve,
definition::Def,
name_collector::NameCollector,
node::{Node, NodeSource},
project::Project,
type_resolver::resolve,
};
use repline::{error::Error as RlError, prebaked::*};
use std::{error::Error, path};
@ -128,19 +132,26 @@ fn resolve_all(prj: &mut Project) -> Result<(), Box<dyn Error>> {
fn list_types(prj: &mut Project) {
println!(" name\x1b[30G type");
for (idx, Def { name, vis, kind, .. }) in prj.pool.iter().enumerate() {
for (idx, Def { kind, node: Node { vis, kind: source, .. }, .. }) in prj.pool.iter().enumerate()
{
print!("{idx:3}: {vis}");
println!("{name}\x1b[30G| {kind}");
if let Some(Some(name)) = source.as_ref().map(NodeSource::name) {
print!("{name}");
}
println!("\x1b[30G| {kind}")
}
}
fn pretty_def(def: &Def, id: impl Into<usize>) {
let id = id.into();
let Def { vis, name, kind, module, meta, source } = def;
let Def { module, kind, node: Node { meta, vis, kind: source, .. } } = def;
for meta in *meta {
println!("#[{meta}]")
}
println!("{vis}{name} [id: {id}] = {kind}");
if let Some(Some(name)) = source.as_ref().map(NodeSource::name) {
print!("{vis}{name} ");
}
println!("[id: {id}] = {kind}");
if let Some(source) = source {
println!("Source:\n{C_LISTING}{source}\x1b[0m");
}

View File

@ -1,41 +1,53 @@
use crate::{key::DefID, module::Module};
use cl_ast::{Item, Meta, Sym, Visibility};
use crate::{
key::DefID,
module::Module,
node::{Node, NodeSource},
};
use cl_ast::{Meta, Sym, Visibility};
use std::{fmt::Debug, str::FromStr};
mod display;
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Def<'a> {
pub name: Sym,
pub vis: Visibility,
pub meta: &'a [Meta],
pub node: Node<'a>,
pub kind: DefKind,
pub source: Option<&'a Item>,
pub module: Module,
}
impl<'a> Def<'a> {
pub fn with_node(node: Node<'a>) -> Self {
Self { node, kind: DefKind::Undecided, module: Default::default() }
}
}
impl Def<'_> {
pub fn name(&self) -> Option<Sym> {
match self.node.kind {
Some(source) => source.name(),
None => None,
}
}
}
mod builder_functions {
use super::*;
impl<'a> Def<'a> {
pub fn set_name(&mut self, name: Sym) -> &mut Self {
self.name = name;
self
}
pub fn set_vis(&mut self, vis: Visibility) -> &mut Self {
self.vis = vis;
self.node.vis = vis;
self
}
pub fn set_meta(&mut self, meta: &'a [Meta]) -> &mut Self {
self.meta = meta;
self.node.meta = meta;
self
}
pub fn set_kind(&mut self, kind: DefKind) -> &mut Self {
self.kind = kind;
self
}
pub fn set_source(&mut self, source: &'a Item) -> &mut Self {
self.source = Some(source);
pub fn set_source(&mut self, source: NodeSource<'a>) -> &mut Self {
self.node.kind = Some(source);
self
}
pub fn set_module(&mut self, module: Module) -> &mut Self {
@ -45,19 +57,6 @@ mod builder_functions {
}
}
impl Default for Def<'_> {
fn default() -> Self {
Self {
name: "".into(),
vis: Visibility::Public,
meta: Default::default(),
kind: Default::default(),
source: Default::default(),
module: Default::default(),
}
}
}
#[derive(Clone, Default, Debug, PartialEq, Eq)]
pub enum DefKind {
/// An unevaluated definition
@ -79,6 +78,7 @@ pub enum DefKind {
pub enum ValueKind {
Const(DefID),
Static(DefID),
Local(DefID),
Fn(DefID),
}
/// A [TypeKind] represents an item in the Type Namespace

View File

@ -1,5 +1,7 @@
//! [Display] implementations for [TypeKind], [Adt], and [Intrinsic]
use crate::node::Node;
use super::{Adt, Def, DefKind, Intrinsic, TypeKind, ValueKind};
use cl_ast::format::FmtAdapter;
use std::{
@ -30,16 +32,20 @@ where
impl Display for Def<'_> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let Self { name, vis, meta, kind, source, module } = self;
let Self { module, node: Node { in_path: _, span: _, meta, vis, kind: source }, kind } =
self;
if !meta.is_empty() {
writeln!(f, "#{meta:?}")?;
}
writeln!(f, "{vis}{name}: ")?;
writeln!(f, "kind: {kind}")?;
if let Some(source) = source {
writeln!(f, "source:")?;
writeln!(f.indent(), "\n{source}")?;
if let Some(name) = source.name() {
writeln!(f, "{vis}{name}:")?;
}
writeln!(f.indent(), "source:\n{source}")?;
} else {
writeln!(f, "{vis}: ")?;
}
writeln!(f, "kind: {kind}")?;
write!(f, "module: {module}")
}
}
@ -61,6 +67,7 @@ impl std::fmt::Display for ValueKind {
match self {
ValueKind::Const(id) => write!(f, "const ({id})"),
ValueKind::Static(id) => write!(f, "static ({id})"),
ValueKind::Local(id) => write!(f, "let ({id})"),
ValueKind::Fn(id) => write!(f, "fn def ({id})"),
}
}

View File

@ -3,6 +3,7 @@ use crate::{
definition::{Def, DefKind},
key::DefID,
module::Module as Mod,
node::{Node, NodeSource},
project::Project as Prj,
};
use cl_ast::{ast_visitor::Visit, *};
@ -10,6 +11,7 @@ use std::mem;
#[derive(Debug)]
pub struct NameCollector<'prj, 'a> {
path: cl_ast::Path,
prj: &'prj mut Prj<'a>,
parent: DefID,
retval: Option<DefID>,
@ -18,11 +20,11 @@ pub struct NameCollector<'prj, 'a> {
impl<'prj, 'a> NameCollector<'prj, 'a> {
/// Constructs a new [NameCollector] out of a [Project](Prj)
pub fn new(prj: &'prj mut Prj<'a>) -> Self {
Self { parent: prj.root, prj, retval: None }
Self { parent: prj.root, prj, path: Default::default(), retval: None }
}
/// Constructs a new [NameCollector] out of a [Project](Prj) and a parent [DefID]
pub fn with_root(prj: &'prj mut Prj<'a>, parent: DefID) -> Self {
Self { prj, parent, retval: None }
Self { prj, parent, path: Default::default(), retval: None }
}
/// Runs the provided function with the given parent
pub fn with_parent<F, N>(&mut self, parent: DefID, node: N, f: F)
@ -44,49 +46,78 @@ impl<'prj, 'a> Visit<'a> for NameCollector<'prj, 'a> {
fn visit_item(&mut self, i: &'a Item) {
let Item { extents: _, attrs, vis, kind } = i;
if let Some(def) = self.returns(kind, Self::visit_item_kind) {
self.prj[def]
.set_meta(&attrs.meta)
.set_vis(*vis)
.set_source(i);
self.prj[def].set_meta(&attrs.meta).set_vis(*vis);
}
}
fn visit_module(&mut self, m: &'a Module) {
let Self { prj, parent, retval: _ } = self;
let Self { prj, parent, path, retval: _ } = self;
let Module { name: Identifier(name), kind } = m;
let def = Def { name: *name, module: Mod::new(*parent), ..Default::default() };
let def = Def {
module: Mod::new(*parent),
kind: DefKind::Undecided,
node: Node::new(path.clone(), Some(NodeSource::Module(m))),
};
let id = prj.pool.insert(def);
prj[*parent].module.insert_type(*name, id);
self.path.push(PathPart::Ident(Identifier(*name)));
self.with_parent(id, kind, Self::visit_module_kind);
self.path.pop();
self.retval = Some(id);
}
fn visit_alias(&mut self, a: &'a Alias) {
let Self { prj, parent, retval: _ } = self;
let Self { prj, parent, path, retval: _ } = self;
let Alias { to: Identifier(name), from: _ } = a;
let def = Def { name: *name, module: Mod::new(*parent), ..Default::default() };
let def = Def {
module: Mod::new(*parent),
kind: DefKind::Undecided,
node: Node::new(path.clone(), Some(NodeSource::Alias(a))),
};
let id = prj.pool.insert(def);
prj[*parent].module.insert_type(*name, id);
self.retval = Some(id);
}
fn visit_enum(&mut self, e: &'a Enum) {
let Self { prj, parent, retval: _ } = self;
let Self { prj, parent, path, retval: _ } = self;
let Enum { name: Identifier(name), kind } = e;
let def = Def { name: *name, module: Mod::new(*parent), ..Default::default() };
let def = Def {
module: Mod::new(*parent),
kind: DefKind::Undecided,
node: Node::new(path.clone(), Some(NodeSource::Enum(e))),
};
let id = prj.pool.insert(def);
prj[*parent].module.insert_type(*name, id);
self.with_parent(id, kind, Self::visit_enum_kind);
self.retval = Some(id);
}
fn visit_variant(&mut self, v: &'a Variant) {
let Self { path, prj, parent, retval: _ } = self;
let Variant { name: Identifier(name), kind } = v;
let def = Def {
module: Mod::new(*parent),
kind: DefKind::Undecided,
node: Node::new(path.clone(), Some(NodeSource::Variant(v))),
};
let id = prj.pool.insert(def);
prj[*parent].module.insert_type(*name, id);
self.with_parent(id, kind, Self::visit_variant_kind);
self.retval = Some(id);
}
fn visit_struct(&mut self, s: &'a Struct) {
let Self { prj, parent, retval: _ } = self;
let Self { prj, parent, path, retval: _ } = self;
let Struct { name: Identifier(name), kind } = s;
let def = Def { name: *name, module: Mod::new(*parent), ..Default::default() };
let def = Def {
module: Mod::new(*parent),
kind: DefKind::Undecided,
node: Node::new(path.clone(), Some(NodeSource::Struct(s))),
};
let id = prj.pool.insert(def);
prj[*parent].module.insert_type(*name, id);
@ -94,10 +125,14 @@ impl<'prj, 'a> Visit<'a> for NameCollector<'prj, 'a> {
self.retval = Some(id);
}
fn visit_const(&mut self, c: &'a Const) {
let Self { prj, parent, retval: _ } = self;
let Self { prj, parent, path, retval: _ } = self;
let Const { name: Identifier(name), ty: _, init } = c;
let def = Def { name: *name, module: Mod::new(*parent), ..Default::default() };
let def = Def {
module: Mod::new(*parent),
kind: DefKind::Undecided,
node: Node::new(path.clone(), Some(NodeSource::Const(c))),
};
let id = prj.pool.insert(def);
prj[*parent].module.insert_value(*name, id);
@ -105,10 +140,14 @@ impl<'prj, 'a> Visit<'a> for NameCollector<'prj, 'a> {
self.retval = Some(id);
}
fn visit_static(&mut self, s: &'a Static) {
let Self { prj, parent, retval: _ } = self;
let Self { prj, parent, path, retval: _ } = self;
let Static { name: Identifier(name), mutable: _, ty: _, init } = s;
let def = Def { name: *name, module: Mod::new(*parent), ..Default::default() };
let def = Def {
module: Mod::new(*parent),
kind: DefKind::Undecided,
node: Node::new(path.clone(), Some(NodeSource::Static(s))),
};
let id = prj.pool.insert(def);
prj[*parent].module.insert_value(*name, id);
@ -116,10 +155,14 @@ impl<'prj, 'a> Visit<'a> for NameCollector<'prj, 'a> {
self.retval = Some(id);
}
fn visit_function(&mut self, f: &'a Function) {
let Self { prj, parent, retval: _ } = self;
let Self { prj, parent, path, retval: _ } = self;
let Function { name: Identifier(name), body, .. } = f;
let def = Def { name: *name, module: Mod::new(*parent), ..Default::default() };
let def = Def {
module: Mod::new(*parent),
kind: DefKind::Undecided,
node: Node::new(path.clone(), Some(NodeSource::Function(f))),
};
let id = prj.pool.insert(def);
prj[*parent].module.insert_value(*name, id);
@ -129,9 +172,13 @@ impl<'prj, 'a> Visit<'a> for NameCollector<'prj, 'a> {
self.retval = Some(id);
}
fn visit_impl(&mut self, i: &'a Impl) {
let Self { prj, parent, retval: _ } = self;
let Self { prj, parent, path, retval: _ } = self;
let Impl { target: _, body } = i;
let def = Def { module: Mod::new(*parent), ..Default::default() };
let def = Def {
module: Mod::new(*parent),
kind: DefKind::Undecided,
node: Node::new(path.clone(), Some(NodeSource::Impl(i))),
};
let id = prj.pool.insert(def);
// items will get reparented after name collection, when target is available
@ -139,14 +186,33 @@ impl<'prj, 'a> Visit<'a> for NameCollector<'prj, 'a> {
self.retval = Some(id);
}
fn visit_use(&mut self, _u: &'a Use) {
let Self { prj, parent, retval } = self;
let def =
Def { module: Mod::new(*parent), kind: DefKind::Use(*parent), ..Default::default() };
fn visit_use(&mut self, u: &'a Use) {
let Self { prj, parent, path, retval } = self;
let def = Def {
module: Mod::new(*parent),
kind: DefKind::Use(*parent),
node: Node::new(path.clone(), Some(NodeSource::Use(u))),
};
let id = prj.pool.insert(def);
prj[*parent].module.imports.push(id);
*retval = Some(id);
}
fn visit_let(&mut self, l: &'a Let) {
let Self { prj, parent, path, retval: _ } = self;
let Let { name: Identifier(name), init, .. } = l;
let def = Def {
module: Mod::new(*parent),
kind: DefKind::Undecided,
node: Node::new(path.clone(), Some(NodeSource::Local(l))),
};
let id = prj.pool.insert(def);
prj[*parent].module.insert_value(*name, id);
if let Some(expr) = init {
self.visit_expr(expr)
}
self.retval = Some(id)
}
}

View File

@ -16,14 +16,23 @@ pub struct Node<'a> {
pub span: &'a Span,
pub meta: &'a [Meta],
pub vis: Visibility,
pub kind: NodeSource<'a>,
pub kind: Option<NodeSource<'a>>,
}
impl<'a> Node<'a> {
pub fn new(path: Path, kind: Option<NodeSource<'a>>) -> Self {
const DUMMY_SPAN: Span = Span::dummy();
Self { in_path: path, span: &DUMMY_SPAN, meta: &[], vis: Visibility::Public, kind }
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum NodeSource<'a> {
Root,
Module(&'a Module),
Alias(&'a Alias),
Enum(&'a Enum),
Variant(&'a Variant),
Struct(&'a Struct),
Const(&'a Const),
Static(&'a Static),
@ -37,9 +46,11 @@ pub enum NodeSource<'a> {
impl<'a> NodeSource<'a> {
pub fn name(&self) -> Option<Sym> {
match self {
NodeSource::Root => None,
NodeSource::Module(v) => Some(v.name.0),
NodeSource::Alias(v) => Some(v.to.0),
NodeSource::Enum(v) => Some(v.name.0),
NodeSource::Variant(v) => Some(v.name.0),
NodeSource::Struct(v) => Some(v.name.0),
NodeSource::Const(v) => Some(v.name.0),
NodeSource::Static(v) => Some(v.name.0),
@ -81,9 +92,11 @@ impl<'a> NodeSource<'a> {
impl fmt::Display for NodeSource<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::Root => "🌳 root 🌳".fmt(f),
Self::Module(arg0) => arg0.fmt(f),
Self::Alias(arg0) => arg0.fmt(f),
Self::Enum(arg0) => arg0.fmt(f),
Self::Variant(arg0) => arg0.fmt(f),
Self::Struct(arg0) => arg0.fmt(f),
Self::Const(arg0) => arg0.fmt(f),
Self::Static(arg0) => arg0.fmt(f),
@ -135,7 +148,7 @@ pub mod sorcerer {
let Self { path, parts, defs } = self;
let (span, meta, vis) = *parts;
defs.push(Node { in_path: path.clone(), span, meta, vis, kind })
defs.push(Node { in_path: path.clone(), span, meta, vis, kind: Some(kind) })
}
}

View File

@ -3,9 +3,10 @@ use crate::{
definition::{Def, DefKind, TypeKind},
key::DefID,
module,
node::{Node, NodeSource},
path::Path,
};
use cl_ast::{Identifier, PathPart, TyFn, TyKind, TyRef, TyTuple, Visibility};
use cl_ast::{Identifier, PathPart};
use cl_structures::deprecated_intern_pool::Pool;
use std::{
collections::HashMap,
@ -30,35 +31,28 @@ impl Project<'_> {
impl Default for Project<'_> {
fn default() -> Self {
const ROOT_PATH: cl_ast::Path = cl_ast::Path { absolute: true, parts: Vec::new() };
let mut pool = Pool::default();
let root = pool.insert(Def {
name: "🌳 root 🌳".into(),
module: Default::default(),
kind: DefKind::Type(TypeKind::Module),
..Default::default()
node: Node::new(ROOT_PATH, Some(NodeSource::Root)),
});
// Insert the Never(!) type
let never = pool.insert(Def {
name: "!".into(),
vis: Visibility::Public,
kind: DefKind::Type(TypeKind::Never),
module: module::Module::new(root),
..Default::default()
kind: DefKind::Type(TypeKind::Never),
node: Node::new(ROOT_PATH, None),
});
let empty = pool.insert(Def {
name: "()".into(),
vis: Visibility::Public,
module: module::Module::new(root),
kind: DefKind::Type(TypeKind::Empty),
module: module::Module::new(root),
..Default::default()
node: Node::new(ROOT_PATH, None),
});
// TODO: Self is not a real type!
let selfty = pool.insert(Def {
name: "Self".into(),
vis: Visibility::Public,
kind: DefKind::Type(TypeKind::SelfTy),
module: module::Module::new(root),
..Default::default()
kind: DefKind::Type(TypeKind::SelfTy),
node: Node::new(ROOT_PATH, None),
});
let mut anon_types = HashMap::new();
@ -171,7 +165,8 @@ pub mod evaluate {
//! or an intermediate result of expression evaluation.
use super::*;
use cl_ast::{Sym, Ty};
use crate::module;
use cl_ast::{Sym, Ty, TyFn, TyKind, TyRef, TyTuple};
/// Things that can be evaluated as a type expression
pub trait EvaluableTypeExpression {
@ -196,19 +191,7 @@ pub mod evaluate {
TyKind::Empty => prj.anon_types[&TypeKind::Empty],
TyKind::SelfTy => prj.anon_types[&TypeKind::SelfTy],
// TyKind::Path must be looked up explicitly
TyKind::Path(path) => {
let (id, path) = prj
.get_type(path.into(), parent)
.ok_or("Failed to get type")?;
if path.is_empty() {
id
} else {
let (id, path) = prj.get_value(path, id).ok_or("Failed to get value")?;
path.is_empty()
.then_some(id)
.ok_or("Path not fully resolved")?
}
}
TyKind::Path(path) => path.evaluate(prj, parent)?,
TyKind::Tuple(tup) => tup.evaluate(prj, parent)?,
TyKind::Ref(tyref) => tyref.evaluate(prj, parent)?,
TyKind::Fn(tyfn) => tyfn.evaluate(prj, parent)?,
@ -228,7 +211,7 @@ pub mod evaluate {
.types
.get(self)
.copied()
.ok_or_else(|| format!("{self} is not a member of {}", prj[parent].name))
.ok_or_else(|| format!("{self} is not a member of {:?}", prj[parent].name()))
}
}
@ -238,9 +221,9 @@ pub mod evaluate {
let types = self.types.evaluate(prj, parent)?;
let root = prj.root;
let id = prj.insert_anonymous_type(TypeKind::Tuple(types.clone()), move || Def {
kind: DefKind::Type(TypeKind::Tuple(types)),
module: module::Module::new(root),
..Default::default()
node: Node::new(Default::default(), None),
kind: DefKind::Type(TypeKind::Tuple(types)),
});
Ok(id)
@ -254,9 +237,9 @@ pub mod evaluate {
let root = prj.root;
let id = prj.insert_anonymous_type(TypeKind::Ref(*count, to), move || Def {
kind: DefKind::Type(TypeKind::Ref(*count, to)),
module: module::Module::new(root),
..Default::default()
node: Node::new(Default::default(), None),
kind: DefKind::Type(TypeKind::Ref(*count, to)),
});
Ok(id)
}
@ -274,9 +257,9 @@ pub mod evaluate {
let root = prj.root;
let id = prj.insert_anonymous_type(TypeKind::FnSig { args, rety }, || Def {
kind: DefKind::Type(TypeKind::FnSig { args, rety }),
module: module::Module::new(root),
..Default::default()
node: Node::new(Default::default(), None),
kind: DefKind::Type(TypeKind::FnSig { args, rety }),
});
Ok(id)
}
@ -304,15 +287,14 @@ pub mod evaluate {
impl<'a> EvaluableTypeExpression for Path<'a> {
type Out = DefID;
fn evaluate(&self, prj: &mut Project, parent: DefID) -> Result<Self::Out, String> {
let (id, path) = prj.get_type(*self, parent).ok_or("Failed to get type")?;
if path.is_empty() {
Ok(id)
} else {
let (id, path) = prj.get_value(path, id).ok_or("Failed to get value")?;
path.is_empty()
.then_some(id)
.ok_or(String::from("Path not fully resolved"))
let (tid, vid, path) = prj.get(*self, parent).ok_or("Failed to traverse path")?;
if !path.is_empty() {
Err(format!("Could not traverse past boundary: {path}"))?;
}
match (tid, vid) {
(Some(ty), _) => Ok(ty),
(None, Some(val)) => Ok(val),
(None, None) => Err(format!("No type or value found at path {self}")),
}
}
}

View File

@ -3,33 +3,47 @@
use crate::{
definition::{Adt, Def, DefKind, TypeKind, ValueKind},
key::DefID,
module,
node::{Node, NodeSource},
project::{evaluate::EvaluableTypeExpression, Project as Prj},
};
use cl_ast::*;
/// Evaluate a single ID
pub fn resolve(prj: &mut Prj, id: DefID) -> Result<(), &'static str> {
let (DefKind::Undecided, Some(source)) = (&prj[id].kind, prj[id].source) else {
let Def { node: Node { kind: Some(source), meta, .. }, kind: DefKind::Undecided, .. } = prj[id]
else {
return Ok(());
};
let kind = match &source.kind {
ItemKind::Alias(_) => "type",
ItemKind::Module(_) => "mod",
ItemKind::Enum(_) => "enum",
ItemKind::Struct(_) => "struct",
ItemKind::Const(_) => "const",
ItemKind::Static(_) => "static",
ItemKind::Function(_) => "fn",
ItemKind::Impl(_) => "impl",
ItemKind::Use(_) => "use",
};
eprintln!(
"Resolver: \x1b[32mEvaluating\x1b[0m \"\x1b[36m{kind} {}\x1b[0m\" (`{id:?}`)",
prj[id].name
);
prj[id].kind = source.resolve_type(prj, id)?;
let kind = match &source {
NodeSource::Root => "root",
NodeSource::Alias(_) => "type",
NodeSource::Module(_) => "mod",
NodeSource::Enum(_) => "enum",
NodeSource::Variant(_) => "variant",
NodeSource::Struct(_) => "struct",
NodeSource::Const(_) => "const",
NodeSource::Static(_) => "static",
NodeSource::Function(_) => "fn",
NodeSource::Impl(_) => "impl",
NodeSource::Use(_) => "use",
NodeSource::Local(_) => "let",
NodeSource::Ty(_) => "ty",
};
let name = prj[id].name().unwrap_or("".into());
eprintln!("Resolver: \x1b[32mEvaluating\x1b[0m \"\x1b[36m{kind} {name}\x1b[0m\" (`{id:?}`)");
for Meta { name: Identifier(name), kind } in meta {
if let ("intrinsic", MetaKind::Equals(Literal::String(s))) = (&**name, kind) {
prj[id].kind = DefKind::Type(TypeKind::Intrinsic(
s.parse().map_err(|_| "Failed to parse intrinsic")?,
));
}
}
if DefKind::Undecided == prj[id].kind {
prj[id].kind = source.resolve_type(prj, id)?;
}
eprintln!("\x1b[33m=> {}\x1b[0m", prj[id].kind);
@ -41,28 +55,37 @@ pub trait TypeResolvable<'a> {
/// The return type upon success
type Out;
/// Resolves type expressions within this node
fn resolve_type(&'a self, prj: &mut Prj<'a>, id: DefID) -> Result<Self::Out, &'static str>;
fn resolve_type(self, prj: &mut Prj<'a>, id: DefID) -> Result<Self::Out, &'static str>;
}
impl<'a> TypeResolvable<'a> for Item {
impl<'a> TypeResolvable<'a> for NodeSource<'a> {
type Out = DefKind;
fn resolve_type(&'a self, prj: &mut Prj<'a>, id: DefID) -> Result<Self::Out, &'static str> {
let Self { attrs: Attrs { meta }, kind, .. } = self;
for meta in meta {
if let Ok(def) = meta.resolve_type(prj, id) {
return Ok(def);
}
fn resolve_type(self, prj: &mut Prj<'a>, id: DefID) -> Result<Self::Out, &'static str> {
match self {
NodeSource::Root => Ok(DefKind::Type(TypeKind::Module)),
NodeSource::Module(v) => v.resolve_type(prj, id),
NodeSource::Alias(v) => v.resolve_type(prj, id),
NodeSource::Enum(v) => v.resolve_type(prj, id),
NodeSource::Variant(v) => v.resolve_type(prj, id),
NodeSource::Struct(v) => v.resolve_type(prj, id),
NodeSource::Const(v) => v.resolve_type(prj, id),
NodeSource::Static(v) => v.resolve_type(prj, id),
NodeSource::Function(v) => v.resolve_type(prj, id),
NodeSource::Local(v) => v.resolve_type(prj, id),
NodeSource::Impl(v) => v.resolve_type(prj, id),
NodeSource::Use(v) => v.resolve_type(prj, id),
NodeSource::Ty(v) => v.resolve_type(prj, id),
}
kind.resolve_type(prj, id)
}
}
impl<'a> TypeResolvable<'a> for Meta {
impl<'a> TypeResolvable<'a> for &'a Meta {
type Out = DefKind;
#[allow(unused_variables)]
fn resolve_type(&'a self, prj: &mut Prj<'a>, id: DefID) -> Result<Self::Out, &'static str> {
let Self { name: Identifier(name), kind } = self;
fn resolve_type(self, prj: &mut Prj<'a>, id: DefID) -> Result<Self::Out, &'static str> {
let Meta { name: Identifier(name), kind } = self;
match (name.as_ref(), kind) {
("intrinsic", MetaKind::Equals(Literal::String(intrinsic))) => Ok(DefKind::Type(
TypeKind::Intrinsic(intrinsic.parse().map_err(|_| "unknown intrinsic type")?),
@ -75,64 +98,18 @@ impl<'a> TypeResolvable<'a> for Meta {
}
}
impl<'a> TypeResolvable<'a> for ItemKind {
type Out = DefKind;
fn resolve_type(&'a self, prj: &mut Prj<'a>, id: DefID) -> Result<Self::Out, &'static str> {
if prj[id].source.map(|s| &s.kind as *const _) != Some(self as *const _) {
return Err("id is not self!");
}
match self {
ItemKind::Module(i) => i.resolve_type(prj, id),
ItemKind::Impl(i) => i.resolve_type(prj, id),
ItemKind::Alias(i) => i.resolve_type(prj, id),
ItemKind::Enum(i) => i.resolve_type(prj, id),
ItemKind::Struct(i) => i.resolve_type(prj, id),
ItemKind::Const(i) => i.resolve_type(prj, id),
ItemKind::Static(i) => i.resolve_type(prj, id),
ItemKind::Function(i) => i.resolve_type(prj, id),
ItemKind::Use(i) => i.resolve_type(prj, id),
}
}
}
impl<'a> TypeResolvable<'a> for Module {
impl<'a> TypeResolvable<'a> for &'a Module {
type Out = DefKind;
#[allow(unused_variables)]
fn resolve_type(&'a self, prj: &mut Prj<'a>, id: DefID) -> Result<Self::Out, &'static str> {
fn resolve_type(self, prj: &mut Prj<'a>, id: DefID) -> Result<Self::Out, &'static str> {
Ok(DefKind::Type(TypeKind::Module))
}
}
impl<'a> TypeResolvable<'a> for Impl {
impl<'a> TypeResolvable<'a> for &'a Alias {
type Out = DefKind;
fn resolve_type(&'a self, prj: &mut Prj<'a>, id: DefID) -> Result<Self::Out, &'static str> {
let parent = prj.parent_of(id).unwrap_or(id);
let target = match &self.target {
ImplKind::Type(t) => t.evaluate(prj, parent),
ImplKind::Trait { for_type, .. } => for_type.evaluate(prj, parent),
}
.map_err(|_| "Unresolved type in impl target")?;
prj[id].module.parent = Some(target);
Ok(DefKind::Impl(target))
}
}
impl<'a> TypeResolvable<'a> for Use {
type Out = DefKind;
fn resolve_type(&'a self, prj: &mut Prj<'a>, id: DefID) -> Result<Self::Out, &'static str> {
todo!("Resolve types for {self} with ID {id} in {prj:?}")
}
}
impl<'a> TypeResolvable<'a> for Alias {
type Out = DefKind;
fn resolve_type(&'a self, prj: &mut Prj<'a>, id: DefID) -> Result<Self::Out, &'static str> {
fn resolve_type(self, prj: &mut Prj<'a>, id: DefID) -> Result<Self::Out, &'static str> {
let parent = prj.parent_of(id).unwrap_or(id);
let alias = if let Some(ty) = &self.from {
Some(
@ -148,62 +125,57 @@ impl<'a> TypeResolvable<'a> for Alias {
}
}
impl<'a> TypeResolvable<'a> for Enum {
impl<'a> TypeResolvable<'a> for &'a Enum {
type Out = DefKind;
fn resolve_type(&'a self, prj: &mut Prj<'a>, id: DefID) -> Result<Self::Out, &'static str> {
let Self { name: _, kind } = self;
fn resolve_type(self, prj: &mut Prj<'a>, id: DefID) -> Result<Self::Out, &'static str> {
let Enum { name: _, kind } = self;
let EnumKind::Variants(v) = kind else {
return Ok(DefKind::Type(TypeKind::Adt(Adt::FieldlessEnum)));
};
let mut fields = vec![];
for v @ Variant { name: Identifier(name), kind: _ } in v {
let id = v.resolve_type(prj, id)?;
for Variant { name: Identifier(name), kind: _ } in v {
let id = prj[id].module.get_type(*name);
fields.push((*name, id))
}
Ok(DefKind::Type(TypeKind::Adt(Adt::Enum(fields))))
}
}
impl<'a> TypeResolvable<'a> for Variant {
type Out = Option<DefID>;
impl<'a> TypeResolvable<'a> for &'a Variant {
type Out = DefKind;
fn resolve_type(&'a self, prj: &mut Prj<'a>, id: DefID) -> Result<Self::Out, &'static str> {
fn resolve_type(self, prj: &mut Prj<'a>, id: DefID) -> Result<Self::Out, &'static str> {
// Get the grandparent of this node, for name resolution
let parent = prj.parent_of(id).unwrap_or(id);
let Self { name: Identifier(name), kind } = self;
let grandparent = prj.parent_of(parent).unwrap_or(parent);
let Variant { name: _, kind } = self;
let adt = match kind {
VariantKind::Plain => return Ok(None),
VariantKind::CLike(_) => todo!("Resolve variant info for C-like enums"),
VariantKind::Tuple(ty) => {
return ty
.evaluate(prj, parent)
.map_err(|_| "Unresolved type in enum tuple variant")
.map(Some)
Ok(DefKind::Type(match kind {
VariantKind::Plain => return Ok(DefKind::Type(TypeKind::Empty)),
VariantKind::CLike(_) => return Ok(DefKind::Undecided),
VariantKind::Tuple(ty) => match &ty.kind {
TyKind::Empty => TypeKind::Tuple(vec![]),
TyKind::Tuple(TyTuple { types }) => {
TypeKind::Tuple(types.evaluate(prj, grandparent).map_err(|e| {
eprintln!("{e}");
""
})?)
}
_ => Err("Unexpected TyKind in tuple variant")?,
},
VariantKind::Struct(members) => {
TypeKind::Adt(Adt::Struct(members.resolve_type(prj, parent)?))
}
VariantKind::Struct(members) => Adt::Struct(members.resolve_type(prj, id)?),
};
let def = Def {
name: *name,
kind: DefKind::Type(TypeKind::Adt(adt)),
module: module::Module::new(id),
..Default::default()
};
let new_id = prj.pool.insert(def);
// Insert the struct variant type into the enum's namespace
prj[id].module.insert_type(*name, new_id);
Ok(Some(new_id))
}))
}
}
impl<'a> TypeResolvable<'a> for Struct {
impl<'a> TypeResolvable<'a> for &'a Struct {
type Out = DefKind;
fn resolve_type(&'a self, prj: &mut Prj<'a>, id: DefID) -> Result<Self::Out, &'static str> {
fn resolve_type(self, prj: &mut Prj<'a>, id: DefID) -> Result<Self::Out, &'static str> {
let parent = prj.parent_of(id).unwrap_or(id);
let Self { name: _, kind } = self;
let Struct { name: _, kind } = self;
Ok(match kind {
StructKind::Empty => DefKind::Type(TypeKind::Empty),
StructKind::Tuple(types) => DefKind::Type(TypeKind::Adt(Adt::TupleStruct({
@ -224,12 +196,12 @@ impl<'a> TypeResolvable<'a> for Struct {
}
}
impl<'a> TypeResolvable<'a> for StructMember {
impl<'a> TypeResolvable<'a> for &'a StructMember {
type Out = (Sym, Visibility, DefID);
fn resolve_type(&'a self, prj: &mut Prj<'a>, id: DefID) -> Result<Self::Out, &'static str> {
fn resolve_type(self, prj: &mut Prj<'a>, id: DefID) -> Result<Self::Out, &'static str> {
let parent = prj.parent_of(id).unwrap_or(id);
let Self { name: Identifier(name), vis, ty } = self;
let StructMember { name: Identifier(name), vis, ty } = self;
let ty = ty
.evaluate(prj, parent)
@ -239,23 +211,24 @@ impl<'a> TypeResolvable<'a> for StructMember {
}
}
impl<'a> TypeResolvable<'a> for Const {
impl<'a> TypeResolvable<'a> for &'a Const {
type Out = DefKind;
fn resolve_type(&'a self, prj: &mut Prj<'a>, id: DefID) -> Result<Self::Out, &'static str> {
let Self { ty, .. } = self;
fn resolve_type(self, prj: &mut Prj<'a>, id: DefID) -> Result<Self::Out, &'static str> {
let Const { ty, .. } = self;
let ty = ty
.evaluate(prj, id)
.map_err(|_| "Invalid type while resolving const")?;
Ok(DefKind::Value(ValueKind::Const(ty)))
}
}
impl<'a> TypeResolvable<'a> for Static {
impl<'a> TypeResolvable<'a> for &'a Static {
type Out = DefKind;
fn resolve_type(&'a self, prj: &mut Prj<'a>, id: DefID) -> Result<Self::Out, &'static str> {
fn resolve_type(self, prj: &mut Prj<'a>, id: DefID) -> Result<Self::Out, &'static str> {
let parent = prj.parent_of(id).unwrap_or(id);
let Self { ty, .. } = self;
let Static { ty, .. } = self;
let ty = ty
.evaluate(prj, parent)
.map_err(|_| "Invalid type while resolving static")?;
@ -263,12 +236,12 @@ impl<'a> TypeResolvable<'a> for Static {
}
}
impl<'a> TypeResolvable<'a> for Function {
impl<'a> TypeResolvable<'a> for &'a Function {
type Out = DefKind;
fn resolve_type(&'a self, prj: &mut Prj<'a>, id: DefID) -> Result<Self::Out, &'static str> {
fn resolve_type(self, prj: &mut Prj<'a>, id: DefID) -> Result<Self::Out, &'static str> {
let parent = prj.parent_of(id).unwrap_or(id);
let Self { sign, .. } = self;
let Function { sign, .. } = self;
let sign = sign
.evaluate(prj, parent)
.map_err(|_| "Invalid type in function signature")?;
@ -276,10 +249,57 @@ impl<'a> TypeResolvable<'a> for Function {
}
}
impl<'a, T: TypeResolvable<'a>> TypeResolvable<'a> for [T] {
type Out = Vec<T::Out>;
impl<'a> TypeResolvable<'a> for &'a Let {
type Out = DefKind;
fn resolve_type(&'a self, prj: &mut Prj<'a>, id: DefID) -> Result<Self::Out, &'static str> {
#[allow(unused)]
fn resolve_type(self, prj: &mut Prj<'a>, id: DefID) -> Result<Self::Out, &'static str> {
let Let { mutable, name, ty, init } = self;
Ok(DefKind::Undecided)
}
}
impl<'a> TypeResolvable<'a> for &'a Impl {
type Out = DefKind;
fn resolve_type(self, prj: &mut Prj<'a>, id: DefID) -> Result<Self::Out, &'static str> {
let parent = prj.parent_of(id).unwrap_or(id);
let target = match &self.target {
ImplKind::Type(t) => t.evaluate(prj, parent),
ImplKind::Trait { for_type, .. } => for_type.evaluate(prj, parent),
}
.map_err(|_| "Unresolved type in impl target")?;
prj[id].module.parent = Some(target);
Ok(DefKind::Impl(target))
}
}
impl<'a> TypeResolvable<'a> for &'a Use {
type Out = DefKind;
fn resolve_type(self, prj: &mut Prj<'a>, id: DefID) -> Result<Self::Out, &'static str> {
todo!("Resolve types for {self} with ID {id} in {prj:?}")
}
}
impl<'a> TypeResolvable<'a> for &'a TyKind {
type Out = DefKind;
#[allow(unused)]
fn resolve_type(self, prj: &mut Prj<'a>, id: DefID) -> Result<Self::Out, &'static str> {
todo!()
}
}
impl<'a, T> TypeResolvable<'a> for &'a [T]
where &'a T: TypeResolvable<'a>
{
type Out = Vec<<&'a T as TypeResolvable<'a>>::Out>;
fn resolve_type(self, prj: &mut Prj<'a>, id: DefID) -> Result<Self::Out, &'static str> {
let mut members = vec![];
for member in self {
members.push(member.resolve_type(prj, id)?);
@ -287,10 +307,12 @@ impl<'a, T: TypeResolvable<'a>> TypeResolvable<'a> for [T] {
Ok(members)
}
}
impl<'a, T: TypeResolvable<'a>> TypeResolvable<'a> for Option<T> {
type Out = Option<T::Out>;
fn resolve_type(&'a self, prj: &mut Prj<'a>, id: DefID) -> Result<Self::Out, &'static str> {
impl<'a, T> TypeResolvable<'a> for Option<&'a T>
where &'a T: TypeResolvable<'a>
{
type Out = Option<<&'a T as TypeResolvable<'a>>::Out>;
fn resolve_type(self, prj: &mut Prj<'a>, id: DefID) -> Result<Self::Out, &'static str> {
match self {
Some(t) => Some(t.resolve_type(prj, id)).transpose(),
None => Ok(None),

View File

@ -16,6 +16,7 @@ use cl_ast::*;
use crate::{
definition::{Def, DefKind},
key::DefID,
node::NodeSource,
project::Project,
};
@ -30,13 +31,9 @@ impl<'a> Project<'a> {
}
pub fn visit_def(&mut self, id: DefID) -> UseResult {
let Def { name, vis, meta, kind, source, module } = &self.pool[id];
if let (DefKind::Use(parent), Some(source)) = (kind, source) {
let Item { kind: ItemKind::Use(u), .. } = source else {
Err(format!("Not a use item: {source}"))?
};
let Def { kind, node, module } = &self.pool[id];
if let (DefKind::Use(parent), Some(NodeSource::Use(u))) = (kind, node.kind) {
println!("Importing use item {u}");
self.visit_use(u, *parent);
}
Ok(())