1mod budget_arena;
2mod classified_form;
3mod compile_time_check;
4mod context;
5mod defining_call;
6mod documented_terms;
7mod evaluated_forms;
8mod expression;
9mod failed_definition;
10mod field_keyword;
11mod form_budget;
12mod generated_entry;
13mod globals;
14mod host;
15mod introduced;
16mod macro_call;
17mod macro_function;
18mod macro_origins;
19mod misplaced_definition;
20mod module_body;
21mod module_loading;
22mod module_notes;
23mod module_survey;
24mod names;
25mod prelude_state;
26mod problems;
27mod recorded_inputs;
28mod recur_check;
29mod rest_of_body;
30mod result_printer;
31mod returned_arguments;
32mod rust_clauses;
33mod rust_type;
34mod saved_definitions;
35mod saved_index;
36mod saved_notes;
37mod saved_values;
38mod session;
39mod shape;
40mod sourced_items;
41mod spliced_forms;
42mod string_view;
43mod structural_clause;
44mod top_level_form;
45mod try_check;
46mod type_expr;
47mod type_parameters;
48
49use std::rc::Rc;
50
51use rustc_hash::{FxHashMap, FxHashSet};
52
53use crate::core::{
54 BindingArena, BindingId, BindingKind, CoreModule, ModuleId, ModulePath, References,
55};
56use crate::diagnostic::{Diagnostic, Diagnostics};
57use crate::interpret::{Closure, Value};
58use crate::modules::{ModuleRegistry, ModuleSources};
59use crate::reader::Form;
60use crate::scope::{BindingTable, Phase, Scope, ScopeAllocator};
61use crate::source::{SourceId, SourceMap, Span};
62use budget_arena::BudgetArena;
63pub use classified_form::ClassifiedForm;
64use evaluated_forms::EvaluatedForms;
65pub use generated_entry::GeneratedEntry;
66use globals::{GlobalTable, LoweredGlobals};
67pub use macro_call::MacroOrigin;
68use macro_call::MacroTable;
69pub use macro_origins::MacroOrigins;
70use module_notes::ModuleNotes;
71pub use module_survey::ModuleSurvey;
72pub use prelude_state::{PreludeState, UnreadablePrelude};
73pub use problems::{ExpandProblems, SetAsideInput};
74use recorded_inputs::RecordedInputs;
75pub use recorded_inputs::{BoundName, LoadedModule};
76pub use result_printer::{GeneratedFunction, ResultPrinter};
77pub use saved_definitions::PendingDefinitions;
78use saved_definitions::{DefinitionSaver, SavedDefinitions, SavedTables};
79use saved_values::SavedValues;
80pub use session::ExpansionSession;
81use string_view::StringViewSearch;
82
83pub struct Program {
84 pub modules: Vec<CoreModule>,
85 pub entry: ModuleId,
86 pub entry_function: Option<BindingId>,
87 pub bindings: BindingArena,
88 pub macro_origins: Rc<MacroOrigins>,
89 pub macro_helpers: FxHashSet<BindingId>,
90 pub string_view: Option<BindingId>,
91 pub checked_roots: Vec<BindingId>,
92 pub pending_definitions: PendingDefinitions,
93 pub warnings: Diagnostics,
94 pub expansion: ExpansionWork,
95}
96
97#[derive(Clone, Copy, Default)]
98pub struct ExpansionWork {
99 pub lowered_forms: usize,
100}
101
102impl Program {
103 pub(super) const WRITTEN_ENTRY_FUNCTION: &str = "main";
104
105 pub fn entry_module(&self) -> &CoreModule {
106 self.modules
107 .iter()
108 .find(|module| module.id == self.entry)
109 .expect("the entry module is expanded")
110 }
111
112 pub fn prelude_macro_helpers(&self) -> FxHashSet<BindingId> {
113 let prelude: FxHashSet<ModuleId> = self
114 .modules
115 .iter()
116 .filter(|module| ModuleSources::is_prelude(&module.path))
117 .map(|module| module.id)
118 .collect();
119 let is_prelude_global = |binding: BindingId| {
120 matches!(self.bindings.get(binding).kind(),
121 BindingKind::Global(module) if prelude.contains(&module))
122 };
123 self.macro_helpers
124 .iter()
125 .copied()
126 .filter(|binding| self.bindings.is_saved(*binding) || is_prelude_global(*binding))
127 .collect()
128 }
129
130 pub fn check_also(&mut self, binding: BindingId) {
131 self.checked_roots.push(binding);
132 self.pending_definitions
133 .restore(&mut self.modules, vec![binding]);
134 }
135
136 fn restore_reached(&mut self) {
137 let roots = self
138 .modules
139 .iter()
140 .flat_map(CoreModule::definitions)
141 .flat_map(|(_, value)| References::of(value, &self.bindings).into_globals())
142 .collect();
143 self.pending_definitions.restore(&mut self.modules, roots);
144 }
145
146 fn written_entry_function(&self) -> Option<BindingId> {
147 self.entry_module()
148 .definitions()
149 .map(|(binding, _)| binding)
150 .find(|binding| self.bindings.get(*binding).name() == Self::WRITTEN_ENTRY_FUNCTION)
151 }
152}
153
154#[derive(Clone, serde::Serialize, serde::Deserialize)]
155pub struct TraitMethods {
156 pub rust_name: Rc<str>,
157 pub self_variable: crate::core::BindingId,
158 pub associated: Vec<(crate::core::BindingId, Rc<str>)>,
159 pub methods: Vec<(crate::core::BindingId, crate::core::TypeExpr)>,
160 pub defaults: rustc_hash::FxHashSet<crate::core::BindingId>,
161}
162
163pub struct Expander<'s> {
164 sources: &'s mut SourceMap,
165 module_sources: ModuleSources,
166 modules: ModuleRegistry,
167 tables: ExpansionTables,
168 current_module: Option<ModuleId>,
169 diagnostics: Diagnostics,
170 warnings: Diagnostics,
171 reported_hidden_modules: Vec<std::path::PathBuf>,
172 library_modules: Vec<(ModulePath, Rc<str>)>,
173 phase: Phase,
174 expansion_depth: usize,
175 nesting_depth: usize,
176 form_budgets: BudgetArena,
177 recovered_diagnostics: Vec<Diagnostic>,
178 type_note_shown: bool,
179 saved_prelude: Option<PreludeState>,
180 saved_definitions: SavedDefinitions,
181 saved_macros: SavedValues<Closure>,
182 saved_globals: SavedValues<Value>,
183 expansion: ExpansionWork,
184 evaluated_forms: EvaluatedForms,
185 recorded_inputs: RecordedInputs,
186 declared_definitions: Vec<failed_definition::DeclaredName>,
187 failed_body_definitions: Vec<BindingId>,
188 introductions: Vec<Scope>,
189 duplicate_definitions: FxHashSet<(ModuleId, Rc<str>)>,
190}
191
192#[derive(Default, serde::Serialize, serde::Deserialize)]
193struct ExpansionTables {
194 scopes: ScopeAllocator,
195 local_scopes: FxHashSet<Scope>,
196 use_site_scopes: FxHashSet<Scope>,
197 table: BindingTable,
198 bindings: BindingArena,
199 macros: MacroTable,
200 macro_origins: MacroOrigins,
201 introduction_scopes: FxHashSet<Scope>,
202 global_macros: Vec<(crate::core::BindingId, Form)>,
203 trait_paths: FxHashMap<crate::core::BindingId, Rc<str>>,
204 structural_paths: FxHashMap<Rc<str>, (crate::core::BindingId, Span)>,
205 enum_variants: FxHashMap<crate::core::BindingId, Vec<crate::core::BindingId>>,
206 variant_fields: FxHashMap<crate::core::BindingId, Vec<Rc<str>>>,
207 trait_methods: FxHashMap<crate::core::BindingId, TraitMethods>,
208 globals: GlobalTable,
209 module_notes: ModuleNotes,
210 expanded: FxHashMap<ModuleId, CoreModule>,
211 order: Vec<ModuleId>,
212 string_view: Option<BindingId>,
213}
214
215impl ExpansionTables {
216 fn forget_locals(&mut self) {
217 let bindings = &self.bindings;
218 self.table
219 .forget(|binding| matches!(bindings.get(binding).kind(), BindingKind::Local));
220 }
221
222 fn find_string_view(&self) -> Option<BindingId> {
223 let modules = self
224 .order
225 .iter()
226 .filter_map(|id| self.expanded.get(id))
227 .filter(|module| ModuleSources::is_embedded_prelude(&module.path));
228 StringViewSearch::in_modules(modules)
229 }
230
231 fn save_definitions(&mut self) -> SavedTables {
232 let mut saver = DefinitionSaver::new(&self.bindings, self.string_view);
233 let modules = self.expanded.values_mut();
234 for module in modules.filter(|module| ModuleSources::is_embedded_prelude(&module.path)) {
235 saver.take_from(module);
236 }
237 saver.finish()
238 }
239
240 fn take_lowered_globals(&mut self) -> LoweredGlobals {
241 let definitions = self.expanded.values().flat_map(CoreModule::definitions);
242 self.globals.take_lowered(definitions)
243 }
244
245 fn restore_lowered_globals(&mut self, lowered: &LoweredGlobals) {
246 let definitions = self.expanded.values().flat_map(CoreModule::definitions);
247 self.globals.restore_lowered(lowered, definitions);
248 }
249}
250
251impl<'s> Expander<'s> {
252 pub fn new(sources: &'s mut SourceMap, module_sources: ModuleSources) -> Self {
253 Self {
254 sources,
255 module_sources,
256 modules: ModuleRegistry::default(),
257 tables: ExpansionTables::default(),
258 current_module: None,
259 diagnostics: Diagnostics::default(),
260 warnings: Diagnostics::default(),
261 reported_hidden_modules: Vec::new(),
262 library_modules: Vec::new(),
263 phase: Phase::Runtime,
264 expansion_depth: 0,
265 nesting_depth: 0,
266 form_budgets: BudgetArena::default(),
267 recovered_diagnostics: Vec::new(),
268 type_note_shown: false,
269 saved_prelude: None,
270 saved_definitions: SavedDefinitions::default(),
271 saved_macros: SavedValues::default(),
272 saved_globals: SavedValues::default(),
273 expansion: ExpansionWork::default(),
274 evaluated_forms: EvaluatedForms::default(),
275 recorded_inputs: RecordedInputs::default(),
276 declared_definitions: Vec::new(),
277 failed_body_definitions: Vec::new(),
278 introductions: Vec::new(),
279 duplicate_definitions: FxHashSet::default(),
280 }
281 }
282
283 pub fn evaluating(self, spans: impl IntoIterator<Item = Span>) -> Self {
284 Self {
285 evaluated_forms: EvaluatedForms::new(spans),
286 ..self
287 }
288 }
289
290 pub fn with_prelude(
291 sources: &'s mut SourceMap,
292 module_sources: ModuleSources,
293 prelude: PreludeState,
294 ) -> Self {
295 Self {
296 saved_prelude: Some(prelude),
297 ..Self::new(sources, module_sources)
298 }
299 }
300
301 #[inline(never)]
302 pub fn expand(mut self, path: ModulePath, entry: SourceId) -> Result<Program, Diagnostics> {
303 let entry = self.load_source_module(path, &[entry]);
304 self.into_program(entry)
305 }
306
307 fn into_program(mut self, entry: ModuleId) -> Result<Program, Diagnostics> {
308 let diagnostics = self.take_diagnostics();
309 self.tables.macro_origins.forget_introduced_names();
310 let string_view = self
311 .tables
312 .string_view
313 .or_else(|| self.tables.find_string_view());
314 let mut program = Program {
315 modules: self.take_modules(),
316 entry,
317 entry_function: None,
318 bindings: self.tables.bindings,
319 macro_helpers: self.tables.globals.macro_helpers(),
320 string_view,
321 checked_roots: Vec::new(),
322 pending_definitions: PendingDefinitions::new(self.saved_definitions),
323 macro_origins: Rc::new(self.tables.macro_origins),
324 warnings: self.warnings,
325 expansion: self.expansion,
326 };
327 program.restore_reached();
328 program.entry_function = program.written_entry_function();
329 diagnostics.into_result(program)
330 }
331
332 fn take_diagnostics(&mut self) -> Diagnostics {
333 for diagnostic in std::mem::take(&mut self.recovered_diagnostics) {
334 self.diagnostics.push(diagnostic);
335 }
336 std::mem::take(&mut self.diagnostics)
337 }
338
339 fn fresh_local_scope(&mut self) -> Scope {
340 let scope = self.tables.scopes.fresh();
341 self.tables.local_scopes.insert(scope);
342 scope
343 }
344
345 fn quoted(&self, datum: &Form) -> Form {
346 let mut quoted = datum.clone();
347 quoted.retain_scopes(&|scope| {
348 !self.tables.local_scopes.contains(&scope)
349 && !self.tables.use_site_scopes.contains(&scope)
350 });
351 quoted
352 }
353
354 fn take_modules(&mut self) -> Vec<CoreModule> {
355 self.tables
356 .order
357 .iter()
358 .filter_map(|id| self.tables.expanded.remove(id))
359 .collect()
360 }
361}