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;