From 7c73fd335c5d61c3f329b6c431ff13169d7fb5a6 Mon Sep 17 00:00:00 2001 From: John Date: Mon, 29 Apr 2024 15:40:30 -0500 Subject: [PATCH] cl-typeck: Store def metadata in a Node I'm not overly proud of this code, but it currently works. Will refactor later. --- compiler/cl-typeck/examples/typeck.rs | 21 +- compiler/cl-typeck/src/definition.rs | 54 ++-- compiler/cl-typeck/src/definition/display.rs | 17 +- compiler/cl-typeck/src/name_collector.rs | 120 ++++++-- compiler/cl-typeck/src/node.rs | 17 +- compiler/cl-typeck/src/project.rs | 78 ++--- compiler/cl-typeck/src/type_resolver.rs | 288 ++++++++++--------- compiler/cl-typeck/src/use_importer.rs | 9 +- 8 files changed, 351 insertions(+), 253 deletions(-) diff --git a/compiler/cl-typeck/examples/typeck.rs b/compiler/cl-typeck/examples/typeck.rs index 08b6cc9..53a02db 100644 --- a/compiler/cl-typeck/examples/typeck.rs +++ b/compiler/cl-typeck/examples/typeck.rs @@ -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> { 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) { 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"); } diff --git a/compiler/cl-typeck/src/definition.rs b/compiler/cl-typeck/src/definition.rs index e1a9e38..6d882c2 100644 --- a/compiler/cl-typeck/src/definition.rs +++ b/compiler/cl-typeck/src/definition.rs @@ -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 { + 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 diff --git a/compiler/cl-typeck/src/definition/display.rs b/compiler/cl-typeck/src/definition/display.rs index 96eec44..4d46e82 100644 --- a/compiler/cl-typeck/src/definition/display.rs +++ b/compiler/cl-typeck/src/definition/display.rs @@ -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})"), } } diff --git a/compiler/cl-typeck/src/name_collector.rs b/compiler/cl-typeck/src/name_collector.rs index 2f9b831..d10ceef 100644 --- a/compiler/cl-typeck/src/name_collector.rs +++ b/compiler/cl-typeck/src/name_collector.rs @@ -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, @@ -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(&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) + } } diff --git a/compiler/cl-typeck/src/node.rs b/compiler/cl-typeck/src/node.rs index 1da064f..7f907b1 100644 --- a/compiler/cl-typeck/src/node.rs +++ b/compiler/cl-typeck/src/node.rs @@ -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>, +} + +impl<'a> Node<'a> { + pub fn new(path: Path, kind: Option>) -> 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 { 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) }) } } diff --git a/compiler/cl-typeck/src/project.rs b/compiler/cl-typeck/src/project.rs index c16a2f0..432b9ad 100644 --- a/compiler/cl-typeck/src/project.rs +++ b/compiler/cl-typeck/src/project.rs @@ -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 { - 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}")), } } } diff --git a/compiler/cl-typeck/src/type_resolver.rs b/compiler/cl-typeck/src/type_resolver.rs index 63edda4..7513145 100644 --- a/compiler/cl-typeck/src/type_resolver.rs +++ b/compiler/cl-typeck/src/type_resolver.rs @@ -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; + fn resolve_type(self, prj: &mut Prj<'a>, id: DefID) -> Result; } -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 { - 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 { + 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 { - let Self { name: Identifier(name), kind } = self; + fn resolve_type(self, prj: &mut Prj<'a>, id: DefID) -> Result { + 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 { - 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 { + fn resolve_type(self, prj: &mut Prj<'a>, id: DefID) -> Result { 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 { - 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 { - 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 { + fn resolve_type(self, prj: &mut Prj<'a>, id: DefID) -> Result { 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 { - let Self { name: _, kind } = self; + fn resolve_type(self, prj: &mut Prj<'a>, id: DefID) -> Result { + 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; +impl<'a> TypeResolvable<'a> for &'a Variant { + type Out = DefKind; - fn resolve_type(&'a self, prj: &mut Prj<'a>, id: DefID) -> Result { + fn resolve_type(self, prj: &mut Prj<'a>, id: DefID) -> Result { + // 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 { + fn resolve_type(self, prj: &mut Prj<'a>, id: DefID) -> Result { 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 { + fn resolve_type(self, prj: &mut Prj<'a>, id: DefID) -> Result { 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 { - let Self { ty, .. } = self; + fn resolve_type(self, prj: &mut Prj<'a>, id: DefID) -> Result { + 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 { + fn resolve_type(self, prj: &mut Prj<'a>, id: DefID) -> Result { 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 { + fn resolve_type(self, prj: &mut Prj<'a>, id: DefID) -> Result { 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; +impl<'a> TypeResolvable<'a> for &'a Let { + type Out = DefKind; - fn resolve_type(&'a self, prj: &mut Prj<'a>, id: DefID) -> Result { + #[allow(unused)] + fn resolve_type(self, prj: &mut Prj<'a>, id: DefID) -> Result { + 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 { + 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 { + 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 { + 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 { 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 { - type Out = Option; - fn resolve_type(&'a self, prj: &mut Prj<'a>, id: DefID) -> Result { +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 { match self { Some(t) => Some(t.resolve_type(prj, id)).transpose(), None => Ok(None), diff --git a/compiler/cl-typeck/src/use_importer.rs b/compiler/cl-typeck/src/use_importer.rs index 2f17766..d89a2b7 100644 --- a/compiler/cl-typeck/src/use_importer.rs +++ b/compiler/cl-typeck/src/use_importer.rs @@ -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(())