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:
parent
d7ce33e457
commit
7c73fd335c
@ -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");
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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})"),
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
@ -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) })
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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}")),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
);
|
||||
|
||||
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}");
|
||||
""
|
||||
})?)
|
||||
}
|
||||
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))
|
||||
_ => Err("Unexpected TyKind in tuple variant")?,
|
||||
},
|
||||
VariantKind::Struct(members) => {
|
||||
TypeKind::Adt(Adt::Struct(members.resolve_type(prj, parent)?))
|
||||
}
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
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),
|
||||
|
@ -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(())
|
||||
|
Loading…
Reference in New Issue
Block a user