rue_compiler/
compiler.rs

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}