Skip to main content

wolf_resolve/
lib.rs

1//! Name resolution (spec chapter 6): modules, imports, visibility, scopes.
2//!
3//! Resolution runs in two passes over all modules of a project, together with the std modules:
4//!
5//! 1. **Collect**: the top-level names of every module, the members of types (enum variants and
6//!    the functions of inherent `impl` blocks), then the imports and the import graph.
7//! 2. **Resolve**: every name in types, expressions and patterns, with local scopes.
8//!
9//! Section order is layout, not visibility (chapter 2, rule 2.6), which is why the first pass
10//! sees the whole project before anything is resolved. The result is a table from syntax nodes to
11//! what they name, for the type checker (M4), plus the diagnostics of chapter 6.
12
13mod body;
14mod checks;
15mod collect;
16mod names;
17mod targets;
18
19use std::collections::BTreeMap;
20
21use wolf_ast::{File, NodeId};
22use wolf_diag::Diagnostic;
23use wolf_project::{ConfigOverride, Kind};
24use wolf_span::{FileId, Span};
25
26/// What a module is for.
27#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord)]
28pub enum Role {
29    /// The prelude module of std; never imported.
30    Prelude,
31    /// Another std module.
32    Std,
33    /// `src/main.wolf` or `src/lib.wolf`.
34    Entry,
35    /// Another module under `src/`.
36    Src,
37    /// A module under `tests/`.
38    Test,
39    /// A module under `examples/`.
40    Example,
41}
42
43/// One parsed module given to the resolver.
44pub struct ModuleInput<'a> {
45    /// The module path derived from the file path.
46    pub path: Vec<String>,
47    /// What the module is for.
48    pub role: Role,
49    /// The source file.
50    pub file: FileId,
51    /// The syntax tree.
52    pub ast: &'a File,
53}
54
55/// Facts about the project that resolution needs.
56pub struct ProjectInfo<'a> {
57    /// `cli` or `lib`.
58    pub kind: Kind,
59    /// Overrides from `[config.*]`, checked against the constants (E0613).
60    pub config: &'a [ConfigOverride],
61}
62
63/// Identifies a module.
64#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
65pub struct ModuleId(pub u32);
66
67/// Identifies a declaration.
68#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
69pub struct DefId(pub u32);
70
71/// Identifies a local variable, parameter or pattern binding.
72#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
73pub struct LocalId(pub u32);
74
75/// The kinds of declarations.
76#[derive(Clone, Copy, Debug, PartialEq, Eq)]
77pub enum DefKind {
78    /// `struct`
79    Struct,
80    /// `enum`
81    Enum,
82    /// `type A = B`
83    Alias,
84    /// `intrinsic type`
85    IntrinsicType,
86    /// `interface`
87    Interface,
88    /// A free function.
89    Fn,
90    /// A `config` constant.
91    Config,
92    /// A function from `extern`.
93    ExternFn,
94    /// An opaque type from `extern`.
95    ExternType,
96    /// A variant of an enum.
97    Variant {
98        /// The enum.
99        parent: DefId,
100        /// The payload form.
101        payload: Payload,
102    },
103    /// A function in an inherent `impl` block (a method if it takes `self`).
104    Member {
105        /// The type the block is for.
106        owner: DefId,
107        /// Whether it takes `self`.
108        method: bool,
109    },
110}
111
112/// The payload form of a variant.
113#[derive(Clone, Copy, Debug, PartialEq, Eq)]
114pub enum Payload {
115    /// No payload.
116    None,
117    /// Positional payload.
118    Tuple,
119    /// Named fields.
120    Struct,
121}
122
123impl DefKind {
124    /// Whether the declaration names a type.
125    pub fn is_type(self) -> bool {
126        matches!(
127            self,
128            DefKind::Struct
129                | DefKind::Enum
130                | DefKind::Alias
131                | DefKind::IntrinsicType
132                | DefKind::Interface
133                | DefKind::ExternType
134        )
135    }
136
137    fn describe(self) -> &'static str {
138        match self {
139            DefKind::Struct => "struct",
140            DefKind::Enum => "enum",
141            DefKind::Alias => "type alias",
142            DefKind::IntrinsicType => "built-in type",
143            DefKind::Interface => "interface",
144            DefKind::Fn => "function",
145            DefKind::Config => "constant",
146            DefKind::ExternFn => "extern function",
147            DefKind::ExternType => "extern type",
148            DefKind::Variant { .. } => "variant",
149            DefKind::Member { method: true, .. } => "method",
150            DefKind::Member { method: false, .. } => "associated function",
151        }
152    }
153}
154
155/// A declaration.
156#[derive(Clone, Debug)]
157pub struct Def {
158    /// What it is.
159    pub kind: DefKind,
160    /// Its name.
161    pub name: String,
162    /// The module that declares it.
163    pub module: ModuleId,
164    /// `pub` (variants have the visibility of their enum).
165    pub public: bool,
166    /// The span of the name in the declaration.
167    pub span: Span,
168}
169
170/// What a name in the source refers to.
171#[derive(Clone, Copy, Debug, PartialEq, Eq)]
172pub enum Res {
173    /// A declaration.
174    Def(DefId),
175    /// A module (through an import).
176    Module(ModuleId),
177    /// A local variable, parameter or binding.
178    Local(LocalId),
179    /// A type parameter, identified by the span of its declaration.
180    TypeParam(Span),
181    /// `Self` inside an `impl` block or an interface.
182    SelfType,
183}
184
185/// A local variable.
186#[derive(Clone, Debug)]
187pub struct Local {
188    /// Its name.
189    pub name: String,
190    /// Where it is declared.
191    pub span: Span,
192}
193
194/// Facts about a module after resolution.
195#[derive(Clone, Debug)]
196pub struct ModuleInfo {
197    /// The module path.
198    pub path: Vec<String>,
199    /// What the module is for.
200    pub role: Role,
201    /// The source file.
202    pub file: FileId,
203    /// Top-level names declared in the module.
204    pub items: BTreeMap<String, DefId>,
205}
206
207/// The result of name resolution.
208#[derive(Debug, Default)]
209pub struct Resolved {
210    /// All modules, std included.
211    pub modules: Vec<ModuleInfo>,
212    /// All declarations.
213    pub defs: Vec<Def>,
214    /// All locals.
215    pub locals: Vec<Local>,
216    /// What each resolved node names: `Name` and `Field` expressions, types, patterns, struct
217    /// literals and the shorthand fields of struct literals and patterns.
218    pub res: BTreeMap<(FileId, NodeId), Res>,
219    /// The local declared at each name span (`let`, `var`, parameters, loop variables, closure
220    /// parameters, pattern bindings).
221    pub local_decls: BTreeMap<Span, LocalId>,
222    /// Members (variants and inherent functions) of each type.
223    pub members: BTreeMap<DefId, BTreeMap<String, DefId>>,
224    /// The type of each `impl` block, inherent or for an interface, keyed by module, section
225    /// index and item index. Blocks whose type did not resolve are missing.
226    pub impls: BTreeMap<(ModuleId, usize, usize), DefId>,
227    /// Diagnostics of chapter 6.
228    pub diagnostics: Vec<Diagnostic>,
229}
230
231impl Resolved {
232    /// The declaration with this id.
233    pub fn def(&self, id: DefId) -> Option<&Def> {
234        self.defs.get(id.0 as usize)
235    }
236}
237
238/// Resolves a project. `modules` must contain the std modules (`wolf_std::MODULES`, parsed by
239/// the caller, with roles [`Role::Prelude`] and [`Role::Std`]) and every module of the project.
240pub fn resolve(modules: &[ModuleInput<'_>], project: &ProjectInfo<'_>) -> Resolved {
241    let mut resolver = collect::Resolver::new(modules, project);
242    resolver.collect();
243    resolver.resolve_bodies();
244    resolver.finish()
245}
246
247pub use names::{is_pascal_case, is_snake_case, suggest};
248pub use targets::check_target;