1use crate::ast::*;
7use crate::data::*;
8
9use fnv::{FnvHashMap, FnvHashSet};
10use std::collections::hash_map::Entry;
11use std::sync::Arc;
12
13#[derive(Clone)]
14pub enum NamedEntityKind {
15 AliasOf(Box<NamedEntityKind>),
16 Other,
17 Overloaded,
18 TypeDeclaration(Option<Arc<Region<'static>>>),
20 IncompleteType,
21 Constant,
22 DeferredConstant,
23 ProtectedType(Arc<Region<'static>>),
25 Library(Symbol),
26 Entity(UnitId, Arc<Region<'static>>),
27 Configuration(UnitId, Arc<Region<'static>>),
28 Package(UnitId, Arc<Region<'static>>),
29 UninstPackage(UnitId, Arc<Region<'static>>),
30 PackageInstance(UnitId, Arc<Region<'static>>),
31 Context(UnitId, Arc<Region<'static>>),
32 LocalPackageInstance(Symbol, Arc<Region<'static>>),
33}
34
35impl NamedEntityKind {
36 pub fn from_object_declaration(decl: &ObjectDeclaration) -> NamedEntityKind {
37 match decl {
38 ObjectDeclaration {
39 class: ObjectClass::Constant,
40 ref expression,
41 ..
42 } => {
43 if expression.is_none() {
44 NamedEntityKind::DeferredConstant
45 } else {
46 NamedEntityKind::Constant
47 }
48 }
49 _ => NamedEntityKind::Other,
50 }
51 }
52
53 fn is_deferred_constant(&self) -> bool {
54 if let NamedEntityKind::DeferredConstant = self {
55 true
56 } else {
57 false
58 }
59 }
60
61 fn is_non_deferred_constant(&self) -> bool {
62 if let NamedEntityKind::Constant = self {
63 true
64 } else {
65 false
66 }
67 }
68
69 fn is_protected_type(&self) -> bool {
70 if let NamedEntityKind::ProtectedType(..) = self {
71 true
72 } else {
73 false
74 }
75 }
76
77 fn is_incomplete_type(&self) -> bool {
78 if let NamedEntityKind::IncompleteType = self {
79 true
80 } else {
81 false
82 }
83 }
84
85 fn is_type_declaration(&self) -> bool {
86 if let NamedEntityKind::TypeDeclaration(..) = self {
87 true
88 } else {
89 false
90 }
91 }
92}
93
94#[derive(Clone)]
95pub struct NamedEntity {
96 decl_pos: Option<SrcPos>,
99 kind: NamedEntityKind,
100}
101
102impl NamedEntity {
103 pub fn new(kind: NamedEntityKind, decl_pos: Option<&SrcPos>) -> NamedEntity {
104 NamedEntity {
105 kind,
106 decl_pos: decl_pos.cloned(),
107 }
108 }
109
110 pub fn decl_pos(&self) -> Option<&SrcPos> {
111 self.decl_pos.as_ref()
112 }
113
114 pub fn kind(&self) -> &NamedEntityKind {
115 &self.kind
116 }
117
118 fn error(&self, diagnostics: &mut dyn DiagnosticHandler, message: impl Into<String>) {
119 if let Some(ref pos) = self.decl_pos {
120 diagnostics.push(Diagnostic::error(pos, message));
121 }
122 }
123
124 fn hint(&self, diagnostics: &mut dyn DiagnosticHandler, message: impl Into<String>) {
125 if let Some(ref pos) = self.decl_pos {
126 diagnostics.push(Diagnostic::hint(pos, message));
127 }
128 }
129
130 fn is_overloaded(&self) -> bool {
131 if let NamedEntityKind::Overloaded = self.kind {
132 true
133 } else {
134 false
135 }
136 }
137
138 fn is_duplicate_of<'a>(&self, prev: &'a Self) -> bool {
140 if self.is_overloaded() && prev.is_overloaded() {
141 return false;
142 }
143
144 match prev.kind {
145 NamedEntityKind::DeferredConstant if self.kind.is_non_deferred_constant() => {}
147 NamedEntityKind::IncompleteType if self.kind.is_type_declaration() => {}
148 _ => {
149 return true;
150 }
151 }
152
153 false
154 }
155}
156
157#[derive(Clone)]
158pub struct VisibleDeclaration {
159 designator: Designator,
160 named_entities: Vec<NamedEntity>,
161}
162
163impl VisibleDeclaration {
164 pub fn new(designator: Designator, named_entity: NamedEntity) -> VisibleDeclaration {
165 VisibleDeclaration {
166 designator,
167 named_entities: vec![named_entity],
168 }
169 }
170
171 pub fn as_unique(&self) -> Option<&NamedEntity> {
173 if self.named_entities.len() == 1 {
174 self.named_entities.first()
175 } else {
176 None
177 }
178 }
179
180 pub fn to_unique(mut self) -> Option<NamedEntity> {
181 if self.named_entities.len() == 1 {
182 self.named_entities.pop()
183 } else {
184 None
185 }
186 }
187
188 fn first(&self) -> &NamedEntity {
189 self.named_entities
190 .first()
191 .expect("Declaration always contains one entry")
192 }
193
194 pub fn first_kind(&self) -> &NamedEntityKind {
195 &self.first().kind
196 }
197
198 pub fn first_pos(&self) -> Option<&SrcPos> {
199 self.first().decl_pos.as_ref()
200 }
201
202 fn second(&self) -> Option<&NamedEntityKind> {
203 self.named_entities.get(1).map(|ent| &ent.kind)
204 }
205
206 fn named_entities(&self) -> impl Iterator<Item = &NamedEntity> {
207 self.named_entities.iter()
208 }
209
210 fn is_overloaded(&self) -> bool {
211 self.first().is_overloaded()
212 }
213
214 fn push(&mut self, ent: NamedEntity) {
215 self.named_entities.push(ent);
216 }
217
218 pub fn make_potentially_visible_in(&self, region: &mut Region<'_>) {
219 for ent in self.named_entities.iter() {
220 region.make_potentially_visible(self.designator.clone(), ent.clone());
221 }
222 }
223}
224#[derive(Copy, Clone, PartialEq)]
225#[cfg_attr(test, derive(Debug))]
226enum RegionKind {
227 PackageDeclaration,
228 PackageBody,
229 Other,
230}
231
232impl Default for RegionKind {
233 fn default() -> RegionKind {
234 RegionKind::Other
235 }
236}
237
238#[derive(Clone, Default)]
239pub struct Region<'a> {
240 parent: Option<&'a Region<'a>>,
241 extends: Option<&'a Region<'a>>,
242 hidden: FnvHashSet<Designator>,
243 visible: FnvHashMap<Designator, VisibleDeclaration>,
244 decls: FnvHashMap<Designator, VisibleDeclaration>,
245 protected_bodies: FnvHashMap<Symbol, SrcPos>,
246 kind: RegionKind,
247}
248
249impl<'a> Region<'a> {
250 pub fn default() -> Region<'static> {
251 Region {
252 parent: None,
253 extends: None,
254 hidden: FnvHashSet::default(),
255 visible: FnvHashMap::default(),
256 decls: FnvHashMap::default(),
257 protected_bodies: FnvHashMap::default(),
258 kind: RegionKind::Other,
259 }
260 }
261
262 pub fn nested(&'a self) -> Region<'a> {
263 Region {
264 parent: Some(self),
265 extends: None,
266 ..Region::default()
267 }
268 }
269
270 pub fn without_parent(self) -> Region<'static> {
271 Region {
272 parent: None,
273 extends: None,
274 hidden: self.hidden,
275 visible: self.visible,
276 decls: self.decls,
277 protected_bodies: self.protected_bodies,
278 kind: self.kind,
279 }
280 }
281
282 pub fn in_package_declaration(mut self) -> Region<'a> {
283 self.kind = RegionKind::PackageDeclaration;
284 self
285 }
286
287 pub fn extend(region: &'a Region<'a>, parent: Option<&'a Region<'a>>) -> Region<'a> {
288 let kind = match region.kind {
289 RegionKind::PackageDeclaration => RegionKind::PackageBody,
290 _ => RegionKind::Other,
291 };
292
293 Region {
294 parent: parent,
295 extends: Some(region),
296 kind,
297 ..Region::default()
298 }
299 }
300
301 pub fn close_immediate(&mut self, diagnostics: &mut dyn DiagnosticHandler) {
302 assert!(self.extends.is_none());
303 self.check_incomplete_types_are_defined(diagnostics);
304 }
305
306 fn check_incomplete_types_are_defined(&self, diagnostics: &mut dyn DiagnosticHandler) {
308 for decl in self.decls.values() {
309 if decl.first_kind().is_incomplete_type() {
310 let mut check_ok = false;
311 if let Some(second) = decl.second() {
312 if second.is_type_declaration() {
313 check_ok = true;
314 }
315 }
316
317 if !check_ok {
318 decl.first().error(
319 diagnostics,
320 format!(
321 "Missing full type declaration of incomplete type '{}'",
322 &decl.designator
323 ),
324 );
325 decl.first().hint(diagnostics, "The full type declaration shall occur immediately within the same declarative part");
326 }
327 }
328 }
329 }
330
331 fn check_deferred_constant_pairs(&self, diagnostics: &mut dyn DiagnosticHandler) {
332 match self.kind {
333 RegionKind::PackageDeclaration => {
335 for decl in self.decls.values() {
336 match decl.first_kind() {
337 NamedEntityKind::DeferredConstant => {
338 decl.first().error(diagnostics, format!("Deferred constant '{}' lacks corresponding full constant declaration in package body", &decl.designator));
339 }
340 _ => {}
341 }
342 }
343 }
344 RegionKind::PackageBody => {
345 let ref extends = self
346 .extends
347 .as_ref()
348 .expect("Package body must extend package");
349 for ext_decl in extends.decls.values() {
350 match ext_decl.first_kind() {
351 NamedEntityKind::DeferredConstant => {
352 let mut found = false;
355 let decl = self.decls.get(&ext_decl.designator);
356
357 if let Some(decl) = decl {
358 if let NamedEntityKind::Constant = decl.first_kind() {
359 found = true;
360 }
361 }
362
363 if !found {
364 ext_decl.first().error(diagnostics, format!("Deferred constant '{}' lacks corresponding full constant declaration in package body", &ext_decl.designator));
365 }
366 }
367 _ => {}
368 }
369 }
370 }
371 RegionKind::Other => {}
372 }
373 }
374
375 fn get_protected_body(&self, name: &Symbol) -> Option<&SrcPos> {
376 self.protected_bodies.get(name).or_else(|| {
377 self.extends
378 .and_then(|extends| extends.get_protected_body(name))
379 })
380 }
381
382 fn has_protected_body(&self, name: &Symbol) -> bool {
383 self.get_protected_body(name).is_some()
384 }
385
386 fn check_protected_types_have_body(&self, diagnostics: &mut dyn DiagnosticHandler) {
387 for decl in self.decls.values() {
388 if decl.first_kind().is_protected_type() {
389 if !self.has_protected_body(&decl.designator.expect_identifier()) {
390 decl.first().error(
391 diagnostics,
392 format!("Missing body for protected type '{}'", &decl.designator),
393 );
394 }
395 }
396 }
397
398 if let Some(ref extends) = self.extends {
399 for ext_decl in extends.decls.values() {
400 if ext_decl.first_kind().is_protected_type() {
401 if !self.has_protected_body(&ext_decl.designator.expect_identifier()) {
402 ext_decl.first().error(
403 diagnostics,
404 format!("Missing body for protected type '{}'", &ext_decl.designator),
405 );
406 }
407 }
408 }
409 }
410 }
411
412 #[must_use]
413 fn check_deferred_constant_only_in_package(
414 &self,
415 ent: &NamedEntity,
416 diagnostics: &mut dyn DiagnosticHandler,
417 ) -> bool {
418 if self.kind != RegionKind::PackageDeclaration && ent.kind.is_deferred_constant() {
419 ent.error(
420 diagnostics,
421 "Deferred constants are only allowed in package declarations (not body)",
422 );
423 false
424 } else {
425 true
426 }
427 }
428
429 #[must_use]
430 fn check_full_constand_of_deferred_only_in_body(
431 &self,
432 ent: &NamedEntity,
433 prev_decl: &VisibleDeclaration,
434 diagnostics: &mut dyn DiagnosticHandler,
435 ) -> bool {
436 if self.kind != RegionKind::PackageBody && ent.kind.is_non_deferred_constant() {
437 if prev_decl.first_kind().is_deferred_constant() {
438 ent.error(
439 diagnostics,
440 "Full declaration of deferred constant is only allowed in a package body",
441 );
442 return false;
443 }
444 }
445 true
446 }
447
448 pub fn close_both(&mut self, diagnostics: &mut dyn DiagnosticHandler) {
449 self.check_incomplete_types_are_defined(diagnostics);
450 self.check_deferred_constant_pairs(diagnostics);
451 self.check_protected_types_have_body(diagnostics);
452 }
453
454 #[must_use]
458 fn check_duplicate(
459 ent: &NamedEntity,
460 prev_decl: &VisibleDeclaration,
461 diagnostics: &mut dyn DiagnosticHandler,
462 ) -> bool {
463 for prev_ent in prev_decl.named_entities() {
464 if ent.is_duplicate_of(&prev_ent) {
465 if let Some(ref pos) = ent.decl_pos {
466 diagnostics.push(duplicate_error(
467 &prev_decl.designator,
468 pos,
469 prev_ent.decl_pos.as_ref(),
470 ));
471 }
472 return false;
473 }
474 }
475
476 true
477 }
478
479 fn check_add(
481 ent: &NamedEntity,
483 prev_decl: Option<&VisibleDeclaration>,
485 ext_decl: Option<&VisibleDeclaration>,
487 diagnostics: &mut dyn DiagnosticHandler,
488 ) -> bool {
489 let mut check_ok = true;
490
491 if let Some(prev_decl) = prev_decl {
492 if !Self::check_duplicate(&ent, &prev_decl, diagnostics) {
493 check_ok = false;
494 }
495 }
496
497 if let Some(ext_decl) = ext_decl {
498 if !Self::check_duplicate(&ent, &ext_decl, diagnostics) {
499 check_ok = false;
500 }
501 }
502
503 check_ok
504 }
505
506 pub fn add_protected_body(&mut self, ident: Ident, diagnostics: &mut dyn DiagnosticHandler) {
507 if let Some(prev_pos) = self.get_protected_body(&ident.item) {
508 diagnostics.push(duplicate_error(&ident.item, &ident.pos, Some(prev_pos)));
509 } else {
510 self.protected_bodies.insert(ident.item, ident.pos);
511 }
512 }
513
514 fn add_named_entity(
515 &mut self,
516 designator: Designator,
517 ent: NamedEntity,
518 diagnostics: &mut dyn DiagnosticHandler,
519 ) {
520 let ext_decl = self
521 .extends
522 .as_ref()
523 .and_then(|extends| extends.decls.get(&designator));
524
525 if !self.check_deferred_constant_only_in_package(&ent, diagnostics) {
526 return;
527 }
528
529 if let Some(ext_decl) = ext_decl {
530 if !self.check_full_constand_of_deferred_only_in_body(&ent, ext_decl, diagnostics) {
531 return;
532 }
533 }
534
535 if let Some(prev_decl) = self.decls.get(&designator) {
537 if !self.check_full_constand_of_deferred_only_in_body(&ent, prev_decl, diagnostics) {
538 return;
539 }
540 }
541
542 match self.decls.entry(designator.clone()) {
543 Entry::Occupied(ref mut entry) => {
544 let prev_decl = entry.get_mut();
545
546 if Self::check_add(&ent, Some(&prev_decl), ext_decl, diagnostics) {
547 prev_decl.push(ent);
548 }
549 }
550 Entry::Vacant(entry) => {
551 if Self::check_add(&ent, None, ext_decl, diagnostics) {
552 entry.insert(VisibleDeclaration::new(designator, ent));
553 }
554 }
555 }
556 }
557
558 pub fn add(
559 &mut self,
560 designator: impl Into<WithPos<Designator>>,
561 kind: NamedEntityKind,
562 diagnostics: &mut dyn DiagnosticHandler,
563 ) {
564 let designator = designator.into();
565 self.add_named_entity(
566 designator.item,
567 NamedEntity::new(kind, Some(&designator.pos)),
568 diagnostics,
569 );
570 }
571
572 pub fn overwrite(&mut self, designator: impl Into<WithPos<Designator>>, kind: NamedEntityKind) {
573 let designator = designator.into();
574 let decl = VisibleDeclaration::new(
575 designator.item,
576 NamedEntity::new(kind, Some(&designator.pos)),
577 );
578 self.decls.insert(decl.designator.clone(), decl);
579 }
580
581 pub fn add_implicit(
582 &mut self,
583 designator: impl Into<Designator>,
584 decl_pos: Option<&SrcPos>,
585 kind: NamedEntityKind,
586 diagnostics: &mut dyn DiagnosticHandler,
587 ) {
588 self.add_named_entity(
589 designator.into(),
590 NamedEntity {
591 decl_pos: decl_pos.cloned(),
592 kind,
593 },
594 diagnostics,
595 );
596 }
597
598 pub fn make_library_visible(
599 &mut self,
600 designator: impl Into<Designator>,
601 library_name: &Symbol,
602 decl_pos: Option<SrcPos>,
603 ) {
604 let ent = NamedEntity {
605 decl_pos: decl_pos.clone(),
606 kind: NamedEntityKind::Library(library_name.clone()),
607 };
608 self.make_potentially_visible(designator.into(), ent);
609 }
610
611 fn add_implicit_declarations(&mut self, kind: &NamedEntityKind) {
614 match kind {
615 NamedEntityKind::TypeDeclaration(ref implicit) => {
616 if let Some(implicit) = implicit {
618 self.make_all_potentially_visible(&implicit);
619 }
620 }
621 NamedEntityKind::AliasOf(ref kind) => {
622 self.add_implicit_declarations(kind);
623 }
624 _ => {}
625 }
626 }
627
628 fn has_duplicate(&self, designator: &Designator, ent: &NamedEntity) -> bool {
629 if let Some(prev) = self.visible.get(&designator) {
630 if !ent.is_overloaded() && !prev.is_overloaded() {
631 if ent.decl_pos() != prev.first_pos() {
634 if let NamedEntityKind::Library(..) = ent.kind() {
635 } else if let NamedEntityKind::Library(..) = prev.first_kind() {
636 } else if let NamedEntityKind::AliasOf(..) = ent.kind() {
638 } else if let NamedEntityKind::AliasOf(..) = prev.first_kind() {
639 } else {
640 return true;
641 }
642 }
643 }
644 }
645
646 if let Some(parent) = self.parent {
647 parent.has_duplicate(designator, ent)
648 } else {
649 false
650 }
651 }
652
653 pub fn make_potentially_visible(&mut self, designator: Designator, ent: NamedEntity) {
654 if self.has_duplicate(&designator, &ent) {
655 self.hidden.insert(designator);
657 } else {
658 self.add_implicit_declarations(&ent.kind);
659 match self.visible.entry(designator.clone()) {
660 Entry::Vacant(entry) => {
661 entry.insert(VisibleDeclaration::new(designator, ent));
662 }
663 Entry::Occupied(mut entry) => {
664 entry.get_mut().push(ent);
665 }
666 }
667 }
668 }
669
670 pub fn make_all_potentially_visible(&mut self, region: &Region<'a>) {
671 for visible in region.decls.values() {
672 for ent in visible.named_entities() {
673 self.make_potentially_visible(visible.designator.clone(), ent.clone());
674 }
675 }
676 }
677
678 pub fn copy_visibility_from(&mut self, region: &Region<'a>) {
680 for visible in region.visible.values() {
681 for ent in visible.named_entities() {
682 self.make_potentially_visible(visible.designator.clone(), ent.clone());
683 }
684 }
685 }
686
687 fn lookup(&self, designator: &Designator, is_selected: bool) -> Option<&VisibleDeclaration> {
689 self.decls
690 .get(designator)
691 .or_else(|| {
692 self.extends
693 .as_ref()
694 .and_then(|region| region.lookup(designator, is_selected))
695 })
696 .or_else(|| {
697 if is_selected || self.hidden.contains(designator) {
698 None
699 } else {
700 self.visible.get(designator)
701 }
702 })
703 .or_else(|| {
704 if is_selected || self.hidden.contains(designator) {
705 None
706 } else {
707 self.parent
708 .as_ref()
709 .and_then(|region| region.lookup_within(designator))
710 }
711 })
712 }
713
714 pub fn lookup_selected(&self, designator: &Designator) -> Option<&VisibleDeclaration> {
717 self.lookup(designator, true)
718 }
719
720 pub fn lookup_within(&self, designator: &Designator) -> Option<&VisibleDeclaration> {
723 self.lookup(designator, false)
724 }
725}
726
727pub trait SetReference {
728 fn set_unique_reference(&mut self, ent: &NamedEntity) {
729 if !ent.is_overloaded() {
732 self.set_reference_pos(ent.decl_pos.as_ref());
735 } else {
736 self.clear_reference();
737 }
738 }
739
740 fn set_reference(&mut self, visible: &VisibleDeclaration) {
741 if let Some(ent) = visible.as_unique() {
742 self.set_unique_reference(ent);
745 } else {
746 self.clear_reference();
747 }
748 }
749
750 fn clear_reference(&mut self) {
751 self.set_reference_pos(None);
752 }
753
754 fn set_reference_pos(&mut self, pos: Option<&SrcPos>);
755}
756
757impl<T> SetReference for WithRef<T> {
758 fn set_reference_pos(&mut self, pos: Option<&SrcPos>) {
759 self.reference = pos.cloned();
760 }
761}
762
763impl<T: SetReference> SetReference for WithPos<T> {
764 fn set_reference_pos(&mut self, pos: Option<&SrcPos>) {
765 self.item.set_reference_pos(pos);
766 }
767}
768
769fn duplicate_error(
770 name: &impl std::fmt::Display,
771 pos: &SrcPos,
772 prev_pos: Option<&SrcPos>,
773) -> Diagnostic {
774 let mut diagnostic = Diagnostic::error(pos, format!("Duplicate declaration of '{}'", name));
775
776 if let Some(prev_pos) = prev_pos {
777 diagnostic.add_related(prev_pos, "Previously defined here");
778 }
779
780 diagnostic
781}