1use std::{
2 cmp::Reverse,
3 collections::{HashMap, HashSet},
4 mem,
5 ops::{Deref, DerefMut, Range},
6 sync::Arc,
7};
8
9use rowan::{TextRange, TextSize};
10use rue_ast::AstNode;
11use rue_diagnostic::{Diagnostic, DiagnosticKind, Name, Source, SourceKind, SrcLoc};
12use rue_hir::{
13 Builtins, Constraint, Database, Declaration, ImportId, Scope, ScopeId, Symbol, SymbolId,
14 TypePath, Value, replace_type,
15};
16use rue_options::CompilerOptions;
17use rue_parser::{SyntaxNode, SyntaxToken};
18use rue_types::{Check, CheckError, Comparison, Type, TypeId};
19
20use crate::{FileTree, SyntaxItem, SyntaxItemKind, SyntaxMap};
21
22#[derive(Debug, Clone)]
23pub struct Compiler {
24 options: CompilerOptions,
25 source: Source,
26 diagnostics: Vec<Diagnostic>,
27 db: Database,
28 syntax_map: SyntaxMap,
29 scope_stack: Vec<(TextSize, ScopeId)>,
30 module_stack: Vec<SymbolId>,
31 builtins: Builtins,
32 defaults: HashMap<TypeId, HashMap<String, Value>>,
33 declaration_stack: Vec<Declaration>,
34 registered_scopes: HashSet<ScopeId>,
35}
36
37impl Deref for Compiler {
38 type Target = Database;
39
40 fn deref(&self) -> &Self::Target {
41 &self.db
42 }
43}
44
45impl DerefMut for Compiler {
46 fn deref_mut(&mut self) -> &mut Self::Target {
47 &mut self.db
48 }
49}
50
51impl Compiler {
52 pub fn new(options: CompilerOptions) -> Self {
53 let mut db = Database::new();
54
55 let builtins = Builtins::new(&mut db);
56
57 let mut ctx = Self {
58 options,
59 source: Source::new(Arc::from(""), SourceKind::Std("<placeholder>".to_string())),
60 diagnostics: Vec::new(),
61 db,
62 syntax_map: SyntaxMap::new(),
63 scope_stack: vec![(TextSize::from(0), builtins.scope)],
64 module_stack: Vec::new(),
65 builtins,
66 defaults: HashMap::new(),
67 declaration_stack: Vec::new(),
68 registered_scopes: HashSet::new(),
69 };
70
71 if options.std {
72 let tree = FileTree::load_std(&mut ctx).unwrap();
73 tree.compile_impl(&mut ctx, false);
74 let prelude_file = tree
75 .find(&SourceKind::Std("prelude.rue".to_string()))
76 .unwrap();
77 let prelude_scope = ctx.module(prelude_file.module).scope;
78
79 let prelude = ctx.alloc_child_scope();
80
81 for (name, symbol) in ctx
82 .scope(prelude_scope)
83 .exported_symbols()
84 .map(|(name, symbol)| (name.to_string(), symbol))
85 .collect::<Vec<_>>()
86 {
87 ctx.scope_mut(prelude).insert_symbol(name, symbol, false);
88 }
89
90 for (name, ty) in ctx
91 .scope(prelude_scope)
92 .exported_types()
93 .map(|(name, ty)| (name.to_string(), ty))
94 .collect::<Vec<_>>()
95 {
96 ctx.scope_mut(prelude).insert_type(name, ty, false);
97 }
98
99 ctx.push_scope(prelude, prelude_file.document.syntax().text_range().start());
100 }
101
102 ctx
103 }
104
105 pub fn source(&self) -> &Source {
106 &self.source
107 }
108
109 pub fn options(&self) -> &CompilerOptions {
110 &self.options
111 }
112
113 pub fn set_source(&mut self, source: Source) {
114 self.source = source;
115 }
116
117 pub fn scope_stack(&self) -> Vec<ScopeId> {
118 self.scope_stack.iter().map(|(_, scope)| *scope).collect()
119 }
120
121 pub fn syntax_map(&self) -> &SyntaxMap {
122 &self.syntax_map
123 }
124
125 pub fn add_syntax(&mut self, kind: SyntaxItemKind, span: TextRange) {
126 self.add_syntax_for_source(kind, span, self.source.kind.clone());
127 }
128
129 pub fn add_syntax_for_source(
130 &mut self,
131 kind: SyntaxItemKind,
132 span: TextRange,
133 source_kind: SourceKind,
134 ) {
135 self.syntax_map
136 .add_item(SyntaxItem::new(kind, span, source_kind));
137 }
138
139 pub fn take_diagnostics(&mut self) -> Vec<Diagnostic> {
140 mem::take(&mut self.diagnostics)
141 }
142
143 pub fn builtins(&self) -> &Builtins {
144 &self.builtins
145 }
146
147 pub fn diagnostic(&mut self, node: &impl GetTextRange, kind: DiagnosticKind) {
148 let srcloc = self.srcloc(node);
149 self.diagnostic_at(srcloc, kind);
150 }
151
152 pub fn diagnostic_name(&mut self, name: &Name, kind: DiagnosticKind) {
153 if let Some(srcloc) = name.srcloc().cloned() {
154 self.diagnostic_at(srcloc, kind);
155 }
156 }
157
158 pub fn diagnostic_at(&mut self, srcloc: SrcLoc, kind: DiagnosticKind) {
159 self.diagnostics.push(Diagnostic::new(srcloc, kind));
160 }
161
162 pub fn srcloc(&self, node: &impl GetTextRange) -> SrcLoc {
163 let range = node.text_range();
164 let span: Range<usize> = range.start().into()..range.end().into();
165 SrcLoc::new(self.source.clone(), span)
166 }
167
168 pub fn local_name(&self, token: &SyntaxToken) -> Name {
169 let srcloc = self.srcloc(token);
170 Name::new(token.text().to_string(), Some(srcloc))
171 }
172
173 pub fn extend_diagnostics(&mut self, diagnostics: Vec<Diagnostic>) {
174 self.diagnostics.extend(diagnostics);
175 }
176
177 pub fn alloc_child_scope(&mut self) -> ScopeId {
178 let parent_scope = self.last_scope_id();
179 self.alloc_scope(Scope::new(Some(parent_scope)))
180 }
181
182 pub fn push_scope(&mut self, scope: ScopeId, start: TextSize) {
183 self.scope_stack.push((start, scope));
184 }
185
186 pub fn pop_scope(&mut self, end: TextSize) {
187 let (start, scope) = self.scope_stack.pop().unwrap();
188
189 if !self.registered_scopes.insert(scope) {
190 return;
191 }
192
193 self.add_syntax(SyntaxItemKind::Scope(scope), TextRange::new(start, end));
194 }
195
196 pub fn last_scope(&self) -> &Scope {
197 let scope = *self.scope_stack.last().unwrap();
198 self.scope(scope.1)
199 }
200
201 pub fn last_scope_mut(&mut self) -> &mut Scope {
202 let scope = *self.scope_stack.last().unwrap();
203 self.scope_mut(scope.1)
204 }
205
206 pub fn last_scope_id(&self) -> ScopeId {
207 self.scope_stack.last().unwrap().1
208 }
209
210 pub fn push_module(&mut self, module: SymbolId) {
211 self.module_stack.push(module);
212 }
213
214 pub fn pop_module(&mut self) {
215 self.module_stack.pop().unwrap();
216 }
217
218 pub fn parent_module_stack(&self) -> &[SymbolId] {
219 if self.module_stack.is_empty() {
220 return &[];
221 }
222
223 &self.module_stack[..self.module_stack.len() - 1]
224 }
225
226 pub fn resolve_symbol_in(
227 &self,
228 scope: ScopeId,
229 name: &str,
230 ) -> Option<(SymbolId, Option<ImportId>)> {
231 let mut current = Some(scope);
232
233 while let Some(scope) = current {
234 if let Some(symbol) = self.scope(scope).symbol(name) {
235 return Some((symbol, self.scope(scope).symbol_import(symbol)));
236 }
237 current = self.scope(scope).parent();
238 }
239
240 None
241 }
242
243 pub fn resolve_type_in(
244 &self,
245 scope: ScopeId,
246 name: &str,
247 ) -> Option<(TypeId, Option<ImportId>)> {
248 let mut current = Some(scope);
249
250 while let Some(scope) = current {
251 if let Some(ty) = self.scope(scope).ty(name) {
252 return Some((ty, self.scope(scope).type_import(ty)));
253 }
254 current = self.scope(scope).parent();
255 }
256
257 None
258 }
259
260 pub fn type_name(&mut self, ty: TypeId) -> String {
261 let current = self.last_scope_id();
262 self.type_name_in(current, ty)
263 }
264
265 pub fn type_name_in(&mut self, scope: ScopeId, ty: TypeId) -> String {
266 let mut current = Some(scope);
267
268 while let Some(scope) = current {
269 if let Some(name) = self.scope(scope).type_name(ty) {
270 return name.to_string();
271 }
272 current = self.scope(scope).parent();
273 }
274
275 rue_types::stringify(self.db.types_mut(), ty)
276 }
277
278 pub fn symbol_name(&self, symbol: SymbolId) -> String {
279 let mut current = Some(self.last_scope_id());
280
281 while let Some(scope) = current {
282 if let Some(name) = self.scope(scope).symbol_name(symbol) {
283 return name.to_string();
284 }
285 current = self.scope(scope).parent();
286 }
287
288 self.symbol(symbol)
289 .name()
290 .map_or_else(|| "{unknown}".to_string(), |name| name.text().to_string())
291 }
292
293 pub fn symbol_type(&self, symbol: SymbolId) -> TypeId {
294 let current = self.last_scope_id();
295 self.symbol_type_in(current, symbol)
296 }
297
298 pub fn symbol_type_in(&self, scope: ScopeId, symbol: SymbolId) -> TypeId {
299 let mut current = Some(scope);
300
301 while let Some(scope) = current {
302 if let Some(ty) = self.scope(scope).symbol_override_type(symbol) {
303 return ty;
304 }
305 current = self.scope(scope).parent();
306 }
307
308 match self.symbol(symbol) {
309 Symbol::Unresolved | Symbol::Module(_) | Symbol::Builtin(_) => {
310 self.builtins().unresolved.ty
311 }
312 Symbol::Function(function) => function.ty,
313 Symbol::Parameter(parameter) => parameter.ty,
314 Symbol::Constant(constant) => constant.value.ty,
315 Symbol::Binding(binding) => binding.value.ty,
316 }
317 }
318
319 pub fn push_mappings(
320 &mut self,
321 mappings: HashMap<SymbolId, HashMap<Vec<TypePath>, TypeId>>,
322 start: TextSize,
323 ) -> usize {
324 let scope = self.alloc_child_scope();
325
326 for (symbol, paths) in mappings {
327 let mut ty = self.symbol_type(symbol);
328
329 let mut paths = paths.into_iter().collect::<Vec<_>>();
330 paths.sort_by_key(|(path, _)| (Reverse(path.len()), path.last().copied()));
331
332 for (path, replacement) in paths {
333 ty = replace_type(&mut self.db, ty, replacement, &path);
334 }
335
336 self.scope_mut(scope).override_symbol_type(symbol, ty);
337 }
338
339 let index = self.scope_stack.len();
340 self.push_scope(scope, start);
341 index
342 }
343
344 pub fn mapping_checkpoint(&self) -> usize {
345 self.scope_stack.len()
346 }
347
348 pub fn revert_mappings(&mut self, index: usize, end: TextSize) {
349 while self.scope_stack.len() > index {
350 self.pop_scope(end);
351 }
352 }
353
354 pub fn is_assignable(&mut self, from: TypeId, to: TypeId) -> bool {
355 let comparison = rue_types::compare(self.db.types_mut(), &self.builtins.types, from, to);
356 comparison == Comparison::Assign
357 }
358
359 pub fn is_castable(&mut self, from: TypeId, to: TypeId) -> bool {
360 let comparison = rue_types::compare(self.db.types_mut(), &self.builtins.types, from, to);
361 matches!(comparison, Comparison::Assign | Comparison::Cast)
362 }
363
364 pub fn assign_type(&mut self, node: &impl GetTextRange, from: TypeId, to: TypeId) {
365 self.compare_type(node, from, to, false, None);
366 }
367
368 pub fn cast_type(&mut self, node: &impl GetTextRange, from: TypeId, to: TypeId) {
369 self.compare_type(node, from, to, true, None);
370 }
371
372 pub fn guard_type(&mut self, node: &impl GetTextRange, from: TypeId, to: TypeId) -> Constraint {
373 let check = match rue_types::check(self.db.types_mut(), &self.builtins.types, from, to) {
374 Ok(check) => check,
375 Err(CheckError::DepthExceeded) => {
376 self.diagnostic(node, DiagnosticKind::TypeCheckDepthExceeded);
377 return Constraint::new(Check::Impossible);
378 }
379 Err(CheckError::FunctionType) => {
380 self.diagnostic(node, DiagnosticKind::FunctionTypeCheck);
381 return Constraint::new(Check::Impossible);
382 }
383 };
384
385 let from_name = self.type_name(from);
386 let to_name = self.type_name(to);
387
388 if check == Check::None {
389 self.diagnostic(node, DiagnosticKind::UnnecessaryGuard(from_name, to_name));
390 } else if check == Check::Impossible {
391 self.diagnostic(node, DiagnosticKind::IncompatibleGuard(from_name, to_name));
392 }
393
394 let else_id = rue_types::subtract(self.db.types_mut(), &self.builtins.types, from, to);
395
396 Constraint::new(check).with_else(else_id)
397 }
398
399 pub fn check_condition(&mut self, node: &impl GetTextRange, ty: TypeId) {
400 if self.is_castable(ty, self.builtins().types.bool_true) {
401 self.diagnostic(node, DiagnosticKind::AlwaysTrueCondition);
402 } else if self.is_castable(ty, self.builtins().types.bool_false) {
403 self.diagnostic(node, DiagnosticKind::AlwaysFalseCondition);
404 } else {
405 self.assign_type(node, ty, self.builtins().types.bool);
406 }
407 }
408
409 pub fn infer_type(
410 &mut self,
411 node: &impl GetTextRange,
412 from: TypeId,
413 to: TypeId,
414 infer: &mut HashMap<TypeId, Vec<TypeId>>,
415 ) {
416 self.compare_type(node, from, to, false, Some(infer));
417 }
418
419 fn compare_type(
420 &mut self,
421 node: &impl GetTextRange,
422 from: TypeId,
423 to: TypeId,
424 cast: bool,
425 infer: Option<&mut HashMap<TypeId, Vec<TypeId>>>,
426 ) {
427 let comparison = rue_types::compare_with_inference(
428 self.db.types_mut(),
429 &self.builtins.types,
430 from,
431 to,
432 infer,
433 );
434
435 match comparison {
436 Comparison::Assign => {
437 if cast
438 && rue_types::compare_with_inference(
439 self.db.types_mut(),
440 &self.builtins.types,
441 to,
442 from,
443 None,
444 ) == Comparison::Assign
445 {
446 let from = self.type_name(from);
447 let to = self.type_name(to);
448
449 self.diagnostic(node, DiagnosticKind::UnnecessaryCast(from, to));
450 }
451 }
452 Comparison::Cast => {
453 if !cast {
454 let from = self.type_name(from);
455 let to = self.type_name(to);
456 self.diagnostic(node, DiagnosticKind::UnassignableType(from, to));
457 }
458 }
459 Comparison::Invalid => {
460 let check =
461 match rue_types::check(self.db.types_mut(), &self.builtins.types, from, to) {
462 Ok(check) => check,
463 Err(CheckError::DepthExceeded | CheckError::FunctionType) => {
464 Check::Impossible
465 }
466 };
467
468 let from = self.type_name(from);
469 let to = self.type_name(to);
470
471 if check != Check::Impossible {
472 self.diagnostic(node, DiagnosticKind::UnconstrainableComparison(from, to));
473 } else if cast {
474 self.diagnostic(node, DiagnosticKind::IncompatibleCast(from, to));
475 } else {
476 self.diagnostic(node, DiagnosticKind::IncompatibleType(from, to));
477 }
478 }
479 }
480 }
481
482 pub fn insert_default_field(&mut self, ty: TypeId, name: String, value: Value) {
483 self.defaults.entry(ty).or_default().insert(name, value);
484 }
485
486 pub fn default_field(&self, ty: TypeId, name: &str) -> Option<Value> {
487 self.defaults
488 .get(&ty)
489 .and_then(|map| map.get(name).cloned())
490 }
491
492 pub fn push_declaration(&mut self, declaration: Declaration) {
493 if let Some(last) = self.declaration_stack.last() {
494 self.db.add_declaration(*last, declaration);
495 }
496
497 self.declaration_stack.push(declaration);
498
499 if self.source.kind.check_unused() {
500 self.db.add_relevant_declaration(declaration);
501 }
502 }
503
504 pub fn pop_declaration(&mut self) {
505 self.declaration_stack.pop().unwrap();
506 }
507
508 pub fn reference(&mut self, reference: Declaration, import: Option<ImportId>) {
509 if let Some(last) = self.declaration_stack.last() {
510 self.db.add_reference(*last, reference);
511 }
512
513 if let Some(import) = import {
514 self.db.add_import_reference(import, reference);
515 }
516 }
517
518 pub fn declaration_span(&mut self, declaration: Declaration, span: TextRange) {
519 self.add_syntax(
520 match declaration {
521 Declaration::Symbol(symbol) => SyntaxItemKind::SymbolDeclaration(symbol),
522 Declaration::Type(ty) => SyntaxItemKind::TypeDeclaration(ty),
523 },
524 span,
525 );
526 }
527
528 pub fn reference_span(&mut self, reference: Declaration, span: TextRange) {
529 self.add_syntax(
530 match reference {
531 Declaration::Symbol(symbol) => SyntaxItemKind::SymbolReference(symbol),
532 Declaration::Type(ty) => SyntaxItemKind::TypeReference(ty),
533 },
534 span,
535 );
536 }
537
538 pub fn is_unresolved(&mut self, ty: TypeId) -> bool {
539 let semantic = rue_types::unwrap_semantic(self.db.types_mut(), ty, true);
540 matches!(self.ty(semantic), Type::Unresolved)
541 }
542}
543
544pub trait GetTextRange {
545 fn text_range(&self) -> TextRange;
546}
547
548impl GetTextRange for TextRange {
549 fn text_range(&self) -> TextRange {
550 *self
551 }
552}
553
554impl GetTextRange for SyntaxNode {
555 fn text_range(&self) -> TextRange {
556 self.text_range()
557 }
558}
559
560impl GetTextRange for SyntaxToken {
561 fn text_range(&self) -> TextRange {
562 self.text_range()
563 }
564}