1use crate::AnalyzerError;
2use crate::generic_inference_table;
3use crate::namespace::Namespace;
4use crate::namespace_table;
5use crate::symbol::{Direction, GenericMap, Symbol, SymbolKind};
6use crate::symbol_path::{GenericSymbol, GenericSymbolPath, SymbolPath, SymbolPathNamespace};
7use crate::symbol_table;
8use crate::symbol_table::{ResolveError, ResolveErrorCause};
9use std::cell::RefCell;
10use veryl_parser::token_range::TokenRange;
11use veryl_parser::veryl_grammar_trait::{
12 ExpressionIdentifier, GenericArgIdentifier, HierarchicalIdentifier, Identifier,
13 InstParameterItem, InstPortItem, ModportItem, ScopedIdentifier, StructConstructorItem,
14};
15use veryl_parser::veryl_token::{Token, TokenSource, is_anonymous_text};
16
17#[derive(Clone, Debug)]
18pub enum ReferenceCandidate {
19 Identifier {
20 arg: Identifier,
21 namespace: Namespace,
22 },
23 HierarchicalIdentifier {
24 arg: HierarchicalIdentifier,
25 namespace: Namespace,
26 },
27 ScopedIdentifier {
28 arg: ScopedIdentifier,
29 namespace: Namespace,
30 in_import_declaration: bool,
31 },
32 ExpressionIdentifier {
33 arg: ExpressionIdentifier,
34 namespace: Namespace,
35 },
36 GenericArgIdentifier {
37 arg: GenericArgIdentifier,
38 namespace: Namespace,
39 },
40 ModportItem {
41 arg: ModportItem,
42 namespace: Namespace,
43 },
44 InstParameterItem {
45 arg: InstParameterItem,
46 namespace: Namespace,
47 },
48 InstPortItem {
49 arg: InstPortItem,
50 namespace: Namespace,
51 },
52 StructConstructorItem {
53 arg: StructConstructorItem,
54 r#type: ExpressionIdentifier,
55 },
56 NamedArgument {
57 arg: ExpressionIdentifier,
58 function: ExpressionIdentifier,
59 },
60}
61
62impl From<&Identifier> for ReferenceCandidate {
63 fn from(value: &Identifier) -> Self {
64 Self::Identifier {
65 arg: value.clone(),
66 namespace: namespace_table::get_default(),
67 }
68 }
69}
70
71impl From<&HierarchicalIdentifier> for ReferenceCandidate {
72 fn from(value: &HierarchicalIdentifier) -> Self {
73 Self::HierarchicalIdentifier {
74 arg: value.clone(),
75 namespace: namespace_table::get_default(),
76 }
77 }
78}
79
80impl From<(&ScopedIdentifier, bool)> for ReferenceCandidate {
81 fn from(value: (&ScopedIdentifier, bool)) -> Self {
82 Self::ScopedIdentifier {
83 arg: value.0.clone(),
84 namespace: namespace_table::get_default(),
85 in_import_declaration: value.1,
86 }
87 }
88}
89
90impl From<&ExpressionIdentifier> for ReferenceCandidate {
91 fn from(value: &ExpressionIdentifier) -> Self {
92 Self::ExpressionIdentifier {
93 arg: value.clone(),
94 namespace: namespace_table::get_default(),
95 }
96 }
97}
98
99impl From<&GenericArgIdentifier> for ReferenceCandidate {
100 fn from(value: &GenericArgIdentifier) -> Self {
101 Self::GenericArgIdentifier {
102 arg: value.clone(),
103 namespace: namespace_table::get_default(),
104 }
105 }
106}
107
108impl From<&ModportItem> for ReferenceCandidate {
109 fn from(value: &ModportItem) -> Self {
110 Self::ModportItem {
111 arg: value.clone(),
112 namespace: namespace_table::get_default(),
113 }
114 }
115}
116
117impl From<&InstParameterItem> for ReferenceCandidate {
118 fn from(value: &InstParameterItem) -> Self {
119 Self::InstParameterItem {
120 arg: value.clone(),
121 namespace: namespace_table::get_default(),
122 }
123 }
124}
125
126impl From<&InstPortItem> for ReferenceCandidate {
127 fn from(value: &InstPortItem) -> Self {
128 Self::InstPortItem {
129 arg: value.clone(),
130 namespace: namespace_table::get_default(),
131 }
132 }
133}
134
135#[derive(Default, Debug)]
136pub struct ReferenceTable {
137 candidates: Vec<ReferenceCandidate>,
138 errors: Vec<AnalyzerError>,
139}
140
141impl ReferenceTable {
142 pub fn new() -> Self {
143 Self::default()
144 }
145
146 pub fn add(&mut self, cand: ReferenceCandidate) {
147 self.candidates.push(cand);
148 }
149
150 fn push_resolve_error(
151 &mut self,
152 err: ResolveError,
153 token: &TokenRange,
154 generics_token: Option<&Token>,
155 struct_token: Option<&Token>,
156 ) {
157 if let Some(last_found) = err.last_found {
158 let name = last_found.token.to_string();
159 match err.cause {
160 ResolveErrorCause::NotFound(not_found) => {
161 let is_generic_if = if let SymbolKind::Port(ref port) = last_found.kind {
162 port.direction == Direction::Interface
163 } else {
164 false
165 };
166
167 if !is_generic_if {
168 let member = format!("{not_found}");
169 self.errors
170 .push(AnalyzerError::unknown_member(&name, &member, token));
171 }
172 }
173 ResolveErrorCause::Private => {
174 if matches!(last_found.kind, SymbolKind::Namespace) {
175 self.errors
176 .push(AnalyzerError::private_namespace(&name, token));
177 } else {
178 self.errors
179 .push(AnalyzerError::private_member(&name, token));
180 }
181 }
182 ResolveErrorCause::Invisible => {
183 self.errors
184 .push(AnalyzerError::invisible_identifier(&name, token));
185 }
186 }
187 } else if let ResolveErrorCause::NotFound(not_found) = err.cause {
188 let name = format!("{not_found}");
189 if let Some(generics_token) = generics_token {
190 self.errors
191 .push(AnalyzerError::unresolvable_generic_expression(
192 &name,
193 token,
194 &generics_token.into(),
195 ));
196 } else if is_anonymous_text(not_found) {
197 } else if let Some(struct_token) = struct_token {
199 self.errors.push(AnalyzerError::unknown_member(
200 &struct_token.text.to_string(),
201 &name,
202 token,
203 ));
204 } else {
205 self.errors
206 .push(AnalyzerError::undefined_identifier(&name, token));
207 }
208 } else {
209 unreachable!();
210 }
211 }
212
213 fn check_pacakge_reference(&mut self, symbol: &Symbol, token_range: &TokenRange) {
214 if !matches!(symbol.kind, SymbolKind::Package(_)) {
215 return;
216 }
217
218 let base_token = token_range.end;
219 let package_token = symbol.token;
220 if let (
221 TokenSource::File {
222 path: package_file, ..
223 },
224 TokenSource::File {
225 path: base_file, ..
226 },
227 ) = (package_token.source, base_token.source)
228 {
229 let referecne_before_definition = package_file == base_file
230 && (package_token.line > base_token.line
231 || package_token.line == base_token.line
232 && package_token.column > base_token.column);
233 if referecne_before_definition {
234 self.errors.push(AnalyzerError::referring_before_definition(
235 &package_token.to_string(),
236 token_range,
237 ));
238 }
239 }
240 }
241
242 fn generic_symbol_path(
243 &mut self,
244 path: &GenericSymbolPath,
245 namespace: &Namespace,
246 in_import_declaration: bool,
247 generics_token: Option<&Token>,
248 generic_maps: Option<&Vec<GenericMap>>,
249 ) {
250 let mut path = path.clone();
251 let mut resolved_generic_maps = vec![];
252
253 let orig_len = path.len();
254 path.resolve_imported(namespace, generic_maps);
255
256 let prefix_len = path.len() - orig_len;
259 for i in prefix_len..path.len() {
260 let base_path = path.base_path(i);
261 match symbol_table::resolve((&base_path, namespace)) {
262 Ok(symbol) => {
263 self.check_pacakge_reference(&symbol.found, &path.range);
264 symbol_table::add_reference(symbol.found.id, &path.paths[0].base);
265
266 let params = symbol.found.generic_parameters();
268
269 let mut inference_attempted_failed = false;
270 if i + 1 == path.paths.len() {
271 use generic_inference_table::InferredApply;
272 match generic_inference_table::apply_inferred_args(&mut path, &symbol.found)
273 {
274 InferredApply::Missing => inference_attempted_failed = true,
275 InferredApply::Applied | InferredApply::NotApplicable => {}
276 }
277 }
278
279 let n_args = path.paths[i].arguments.len();
280
281 if in_import_declaration
282 && !params.is_empty()
283 && matches!(
284 symbol.found.kind,
285 SymbolKind::Function(_) | SymbolKind::Struct(_) | SymbolKind::Union(_)
286 )
287 {
288 if n_args != 0 {
292 self.errors.push(AnalyzerError::invalid_import(&path.range))
293 }
294 continue;
295 }
296
297 let match_artiy = if params.len() > n_args {
298 params[n_args].1.default_value.is_some()
299 } else {
300 params.len() == n_args
301 };
302 if !match_artiy {
303 if inference_attempted_failed {
304 self.errors.push(AnalyzerError::generic_inference_failed(
305 &path.paths[i].base.to_string(),
306 &path.range,
307 ));
308 } else {
309 self.errors.push(AnalyzerError::mismatch_generics_arity(
310 &path.paths[i].base.to_string(),
311 params.len(),
312 n_args,
313 &path.range,
314 ));
315 }
316 continue;
317 }
318
319 if (params.len() + n_args) == 0 {
320 continue;
321 }
322
323 let target_symbol = symbol.found;
324
325 let mut args: Vec<_> = path.paths[i].arguments.drain(0..).collect();
326 for param in params.iter().skip(n_args) {
327 args.push(param.1.default_value.as_ref().unwrap().clone());
329 }
330
331 for arg in args.iter_mut() {
332 arg.unalias();
333 if !target_symbol.is_global_function() {
336 arg.append_namespace_path(namespace, &target_symbol.namespace);
337 }
338 }
339
340 path.paths[i].arguments.append(&mut args);
341
342 for arg in &path.paths[i].arguments {
345 self.generic_symbol_path(arg, namespace, false, None, None);
346 }
347
348 if path.is_generic_reference() {
349 Self::add_generic_reference(&target_symbol, namespace, &path, i);
350 } else {
351 Self::insert_generic_instance(
352 &path,
353 i,
354 namespace,
355 &target_symbol,
356 &mut resolved_generic_maps,
357 None,
358 );
359 }
360 }
361 Err(err) => {
362 let single_path = path.paths.len() == 1;
363 if single_path && !path.is_resolvable() {
364 return;
365 }
366
367 self.push_resolve_error(err, &path.range, generics_token, None);
368 }
369 }
370 }
371 }
372
373 fn insert_generic_instance(
374 path: &GenericSymbolPath,
375 ith: usize,
376 namespace: &Namespace,
377 target: &Symbol,
378 generic_maps: &mut Vec<GenericMap>,
379 affiliation_symbol: Option<&Symbol>,
380 ) {
381 let instance_path = &path.paths[ith];
382 let Some((token, symbol)) =
383 Self::create_generic_instance(instance_path, target, namespace, affiliation_symbol)
384 else {
385 return;
386 };
387
388 if let Some(ref id) = symbol_table::insert(&token, symbol.clone()) {
389 symbol_table::add_generic_instance(target.id, *id);
390 }
391
392 generic_maps.push(GenericMap {
393 id: None,
394 map: target.generic_table(&instance_path.arguments),
395 });
396 Self::insert_subordinate_generic_instances(namespace, target, &symbol, generic_maps);
397 }
398
399 fn create_generic_instance(
400 symbol: &GenericSymbol,
401 target: &Symbol,
402 namespace: &Namespace,
403 affiliation_symbol: Option<&Symbol>,
404 ) -> Option<(Token, Symbol)> {
405 if !target.is_global_function() {
406 symbol.get_generic_instance(target, affiliation_symbol)
407 } else if let Some(affiliation_symbol) = affiliation_symbol {
408 if affiliation_symbol.is_component(true) {
409 symbol.get_generic_instance(target, Some(affiliation_symbol))
410 } else {
411 symbol.get_generic_instance(
412 target,
413 affiliation_symbol.get_parent_component().as_ref(),
414 )
415 }
416 } else if let Some(namespace_symbol) = namespace.get_symbol() {
417 if namespace_symbol.is_component(true) {
418 symbol.get_generic_instance(target, Some(&namespace_symbol))
419 } else {
420 symbol
421 .get_generic_instance(target, namespace_symbol.get_parent_component().as_ref())
422 }
423 } else {
424 symbol.get_generic_instance(target, None)
425 }
426 }
427
428 fn insert_subordinate_generic_instances(
429 namespace: &Namespace,
430 target: &Symbol,
431 inst_symbol: &Symbol,
432 generic_maps: &[GenericMap],
433 ) {
434 let is_global_func = target.is_global_function();
435 let mut subordinate_paths = if !is_global_func {
436 target.generic_references()
437 } else if let Some(paths) = symbol_table::get_reference_functions(target.id) {
438 paths
439 } else {
440 return;
441 };
442
443 if subordinate_paths.is_empty() {
444 return;
445 }
446
447 let target_namespace = &target.inner_namespace();
448 for path in &mut subordinate_paths {
449 if path.paths[0].base.text == target.token.text {
451 continue;
452 }
453
454 path.apply_map(generic_maps);
455 path.unalias();
456 path.append_namespace_path(namespace, &target.namespace);
457
458 if let Ok(path_symbol) = symbol_table::resolve((&path.generic_path(), target_namespace))
459 {
460 let ith = path.len() - 1;
461 if is_global_func {
462 Self::insert_generic_instance(
463 path,
464 ith,
465 namespace,
466 &path_symbol.found,
467 &mut generic_maps.to_vec(),
468 None,
469 );
470 } else {
471 Self::insert_generic_instance(
472 path,
473 ith,
474 target_namespace,
475 &path_symbol.found,
476 &mut generic_maps.to_vec(),
477 Some(inst_symbol),
478 );
479 }
480 }
481 }
482 }
483
484 fn add_generic_reference(
485 symbol: &Symbol,
486 namespace: &Namespace,
487 path: &GenericSymbolPath,
488 ith: usize,
489 ) {
490 fn get_parent_generic_component(namespace: &Namespace) -> Option<Symbol> {
491 let target = namespace.get_symbol()?;
492 if target.has_generic_paramters() {
493 Some(target)
494 } else {
495 get_parent_generic_component(&target.namespace)
496 }
497 }
498
499 let mut namespace = namespace.clone();
500 namespace.strip_anonymous_path();
501
502 let mut target = if let Some(target) = get_parent_generic_component(&namespace)
503 && !target.is_global_function()
504 {
505 target
506 } else {
507 return;
508 };
509 let path = path.slice(ith);
510
511 let generic_maps = target.generic_maps();
516 for map in generic_maps {
517 let affiliation_symbol = map.id.map(|id| symbol_table::get(id).unwrap());
518 let mut path = path.clone();
519 let ith = path.len() - 1;
520
521 let mut maps = vec![map];
522 path.apply_map(&maps);
523 path.append_namespace_path(&namespace, &symbol.namespace);
524
525 Self::insert_generic_instance(
526 &path,
527 ith,
528 &namespace,
529 symbol,
530 &mut maps,
531 affiliation_symbol.as_ref(),
532 );
533 }
534
535 let kind = match target.kind {
536 SymbolKind::Function(mut x) => {
537 x.generic_references.push(path);
538 SymbolKind::Function(x)
539 }
540 SymbolKind::Module(mut x) => {
541 x.generic_references.push(path);
542 SymbolKind::Module(x)
543 }
544 SymbolKind::Interface(mut x) => {
545 x.generic_references.push(path);
546 SymbolKind::Interface(x)
547 }
548 SymbolKind::Package(mut x) => {
549 x.generic_references.push(path);
550 SymbolKind::Package(x)
551 }
552 SymbolKind::Struct(mut x) => {
553 x.generic_references.push(path);
554 SymbolKind::Struct(x)
555 }
556 SymbolKind::Union(mut x) => {
557 x.generic_references.push(path);
558 SymbolKind::Union(x)
559 }
560 _ => return,
561 };
562
563 target.kind = kind;
564 symbol_table::update(target);
565 }
566
567 fn check_simple_identifier(
568 &mut self,
569 path: &SymbolPathNamespace,
570 default_namespace: Option<&Namespace>,
571 token: &TokenRange,
572 struct_token: Option<&Token>,
573 ) {
574 if let Some(default_namespace) = default_namespace {
575 namespace_table::set_default(&default_namespace.paths);
576 }
577
578 match symbol_table::resolve(path) {
579 Ok(symbol) => {
580 for id in symbol.full_path {
581 symbol_table::add_reference(id, &token.beg);
582 }
583 }
584 Err(err) => {
585 self.push_resolve_error(err, token, None, struct_token);
586 }
587 }
588 }
589
590 fn check_array_member_access(
591 &mut self,
592 path: &GenericSymbolPath,
593 namespace: &Namespace,
594 selects_per_component: &[usize],
595 ) {
596 for i in 0..path.len().saturating_sub(1) {
597 let base_path = path.base_path(i);
598 if let Ok(symbol) = symbol_table::resolve((&base_path, namespace))
599 && let Some(r#type) = symbol.found.kind.get_type()
600 {
601 let array_dims = r#type.array.len();
602 let applied_selects = selects_per_component.get(i).copied().unwrap_or(0);
603 if applied_selects < array_dims {
604 let member_name = if i + 1 < path.len() {
605 path.paths[i + 1].base.to_string()
606 } else {
607 String::new()
608 };
609 self.errors.push(AnalyzerError::member_access_on_array(
610 &symbol.found.token.to_string(),
611 &member_name,
612 array_dims,
613 &path.range,
614 ));
615 return;
616 }
617 }
618 }
619 }
620
621 fn check_complex_identifier(
622 &mut self,
623 path: &GenericSymbolPath,
624 default_namespace: &Namespace,
625 token: &Token,
626 in_import_declaration: bool,
627 ) {
628 namespace_table::set_default(&default_namespace.paths);
629 let namespace = namespace_table::get(token.id).unwrap();
630 self.generic_symbol_path(path, &namespace, in_import_declaration, None, None);
631 }
632
633 pub fn apply(&mut self) -> Vec<AnalyzerError> {
634 symbol_table::suppress_cache_clear();
635 let candidates: Vec<_> = self.candidates.drain(0..).collect();
636
637 for x in &candidates {
638 match x {
639 ReferenceCandidate::Identifier { arg, namespace } => {
640 self.check_simple_identifier(&arg.into(), Some(namespace), &arg.into(), None);
641 }
642 ReferenceCandidate::HierarchicalIdentifier { arg, namespace } => {
643 let token = arg.identifier.identifier_token.token;
644 let path: GenericSymbolPath = arg.into();
645 self.check_complex_identifier(&path, namespace, &token, false);
646 if !arg.hierarchical_identifier_list0.is_empty() {
647 let ns = namespace_table::get(token.id).unwrap_or(namespace.clone());
648 let mut selects = vec![0usize; path.len()];
649 selects[0] = arg.hierarchical_identifier_list.len();
650 for (j, member) in arg.hierarchical_identifier_list0.iter().enumerate() {
651 if 1 + j < selects.len() {
652 selects[1 + j] = member.hierarchical_identifier_list0_list.len();
653 }
654 }
655 self.check_array_member_access(&path, &ns, &selects);
656 }
657 }
658 ReferenceCandidate::ScopedIdentifier {
659 arg,
660 namespace,
661 in_import_declaration,
662 } => {
663 let token = arg.identifier().token;
664 self.check_complex_identifier(
665 &arg.into(),
666 namespace,
667 &token,
668 *in_import_declaration,
669 );
670 }
671 ReferenceCandidate::ExpressionIdentifier { arg, namespace } => {
672 let token = arg.scoped_identifier.identifier().token;
673 let path: GenericSymbolPath = arg.into();
674 self.check_complex_identifier(&path, namespace, &token, false);
675 if !arg.expression_identifier_list0.is_empty() {
676 let ns = namespace_table::get(token.id).unwrap_or(namespace.clone());
677 let scoped_len = arg.scoped_identifier.scoped_identifier_list.len() + 1;
678 let mut selects = vec![0usize; path.len()];
679 if scoped_len <= selects.len() {
680 selects[scoped_len - 1] = arg.expression_identifier_list.len();
681 }
682 for (j, member) in arg.expression_identifier_list0.iter().enumerate() {
683 if scoped_len + j < selects.len() {
684 selects[scoped_len + j] =
685 member.expression_identifier_list0_list.len();
686 }
687 }
688 self.check_array_member_access(&path, &ns, &selects);
689 }
690 }
691 ReferenceCandidate::GenericArgIdentifier { arg, namespace } => {
692 let token = arg.scoped_identifier.identifier().token;
693 self.check_complex_identifier(&arg.into(), namespace, &token, false);
694 }
695 ReferenceCandidate::ModportItem { arg, namespace } => {
696 let mut path: SymbolPathNamespace = arg.identifier.as_ref().into();
697 path.pop_namespace();
698 self.check_simple_identifier(&path, Some(namespace), &arg.into(), None);
699 }
700 ReferenceCandidate::InstParameterItem { arg, namespace } => {
701 if arg.inst_parameter_item_opt.is_none() {
702 let identifier = arg.identifier.as_ref();
704 self.check_simple_identifier(
705 &identifier.into(),
706 Some(namespace),
707 &identifier.into(),
708 None,
709 );
710 }
711 }
712 ReferenceCandidate::InstPortItem { arg, namespace } => {
713 if arg.inst_port_item_opt.is_none() {
714 let identifier = arg.identifier.as_ref();
716 self.check_simple_identifier(
717 &identifier.into(),
718 Some(namespace),
719 &identifier.into(),
720 None,
721 );
722 }
723 }
724 ReferenceCandidate::StructConstructorItem { arg, r#type } => {
725 if let Ok(symbol) = symbol_table::resolve(r#type)
726 && !matches!(symbol.found.kind, SymbolKind::SystemVerilog)
727 {
728 let identifier = arg.identifier.as_ref();
729
730 let namespace = Self::get_struct_namespace(&symbol.found);
731 let path: SymbolPathNamespace = (identifier, &namespace).into();
732
733 self.check_simple_identifier(
734 &path,
735 None,
736 &identifier.into(),
737 Some(&symbol.found.token),
738 );
739 }
740 }
741 ReferenceCandidate::NamedArgument { arg, function } => {
742 if let Ok(symbol) = symbol_table::resolve(function) {
743 let func_symbol =
744 if let SymbolKind::ModportFunctionMember(x) = &symbol.found.kind {
745 symbol_table::get(x.function).unwrap()
746 } else {
747 (*symbol.found).clone()
748 };
749 let namespace = func_symbol.inner_namespace();
750 let path: SymbolPath = arg.into();
751 let path: SymbolPathNamespace = (&path, &namespace).into();
752 self.check_simple_identifier(
753 &path,
754 None,
755 &arg.into(),
756 Some(&func_symbol.token),
757 );
758 }
759 }
760 }
761 }
762
763 symbol_table::resume_cache_clear();
764 self.errors.drain(0..).collect()
765 }
766
767 fn get_struct_namespace(symbol: &Symbol) -> Namespace {
768 match &symbol.kind {
769 SymbolKind::TypeDef(x) => {
770 let namespace = Some(&symbol.namespace);
771 if let Some((_, Some(symbol))) = x.r#type.trace_user_defined(namespace) {
772 return Self::get_struct_namespace(&symbol);
773 }
774 }
775 SymbolKind::ProtoTypeDef(x) => {
776 if let Some(r#type) = &x.r#type {
777 let namespace = Some(&symbol.namespace);
778 if let Some((_, Some(symbol))) = r#type.trace_user_defined(namespace) {
779 return Self::get_struct_namespace(&symbol);
780 }
781 }
782 }
783 _ => {}
784 }
785 symbol.inner_namespace()
786 }
787}
788
789thread_local!(static REFERENCE_TABLE: RefCell<ReferenceTable> = RefCell::new(ReferenceTable::new()));
790
791pub fn add(cand: ReferenceCandidate) {
792 REFERENCE_TABLE.with(|f| f.borrow_mut().add(cand))
793}
794
795pub fn apply() -> Vec<AnalyzerError> {
796 REFERENCE_TABLE.with(|f| f.borrow_mut().apply())
797}