-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathpath_expr.rs
88 lines (78 loc) · 3.12 KB
/
path_expr.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
use rowan::TextRange;
use rue_parser::SyntaxToken;
use crate::{
compiler::{
path::{PathItem, PathKind},
Compiler,
},
hir::Hir,
symbol::{Function, Symbol},
value::{GuardPath, Type, Value},
ErrorKind,
};
impl Compiler<'_> {
pub fn compile_path_expr(&mut self, idents: &[SyntaxToken], text_range: TextRange) -> Value {
let Some(mut item) =
self.resolve_base_path(&idents[0], PathKind::Symbol, idents.len() == 1)
else {
return self.unknown();
};
for (i, name) in idents.iter().enumerate().skip(1) {
let Some(next_item) =
self.resolve_next_path(item, name, PathKind::Symbol, i == idents.len() - 1)
else {
return self.unknown();
};
item = next_item;
}
let symbol_id = match item {
PathItem::Symbol(symbol_id) => symbol_id,
PathItem::Type(type_id) => {
if let Type::EnumVariant(variant_type) = self.db.ty(type_id).clone() {
let Type::Enum(enum_type) = self.db.ty(variant_type.enum_type) else {
unreachable!();
};
if enum_type.has_fields {
self.db.error(ErrorKind::EnumVariantWithFields, text_range);
}
return Value::new(variant_type.discriminant, type_id);
}
self.db.error(ErrorKind::ExpectedSymbolPath, text_range);
return self.unknown();
}
};
if matches!(self.db.symbol(symbol_id), Symbol::Module(..)) {
self.db.error(ErrorKind::ModuleReference, text_range);
return self.unknown();
}
if !self.is_callee && matches!(self.db.symbol(symbol_id), Symbol::InlineFunction(..)) {
self.db
.error(ErrorKind::InlineFunctionReference, text_range);
return self.unknown();
}
let override_type_id = self.symbol_type(&GuardPath::new(symbol_id));
let mut value = match self.db.symbol(symbol_id).clone() {
Symbol::Unknown | Symbol::Module(..) => unreachable!(),
Symbol::Function(Function { ty, .. }) | Symbol::InlineFunction(Function { ty, .. }) => {
let type_id = self.db.alloc_type(Type::Function(ty.clone()));
Value::new(
self.db.alloc_hir(Hir::Reference(symbol_id)),
override_type_id.unwrap_or(type_id),
)
}
Symbol::Parameter(type_id) => Value::new(
self.db.alloc_hir(Hir::Reference(symbol_id)),
override_type_id.unwrap_or(type_id),
),
Symbol::Let(mut value) | Symbol::Const(mut value) | Symbol::InlineConst(mut value) => {
if let Some(type_id) = override_type_id {
value.type_id = type_id;
}
value.hir_id = self.db.alloc_hir(Hir::Reference(symbol_id));
value
}
};
value.guard_path = Some(GuardPath::new(symbol_id));
value
}
}