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