Skip to main content

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::{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}