1use super::*;
9use crate::data::error_codes::ErrorCode;
10use crate::data::*;
11use crate::named_entity::{Concurrent, Sequential};
12use crate::TokenSpan;
13
14impl WithTokenSpan<Name> {
15 pub fn suffix_pos(&self) -> TokenSpan {
16 match self.item {
17 Name::Designator(..) => self.span,
18 Name::Selected(_, ref suffix) => suffix.token.into(),
19 Name::SelectedAll(ref prefix) => prefix.span,
21 Name::CallOrIndexed(ref fcall) => fcall.name.span,
22 Name::Slice(ref prefix, ..) => prefix.span,
23 Name::Attribute(ref attr, ..) => attr.name.span,
24 Name::External(..) => self.span,
25 }
26 }
27}
28
29pub fn to_simple_name(ctx: &dyn TokenAccess, name: WithTokenSpan<Name>) -> DiagnosticResult<Ident> {
30 match name.item {
31 Name::Designator(WithRef {
32 item: Designator::Identifier(ident),
33 ..
34 }) => Ok(WithToken {
35 item: ident,
36 token: name.span.start_token,
37 }),
38 _ => Err(Diagnostic::new(
39 name.span.pos(ctx),
40 "Expected simple name",
41 ErrorCode::SyntaxError,
42 )),
43 }
44}
45
46pub fn as_simple_name_mut(name: &mut Name) -> Option<&mut WithRef<Designator>> {
47 match name {
48 Name::Designator(
49 des @ WithRef {
50 item: Designator::Identifier(_),
51 ..
52 },
53 ) => Some(des),
54 _ => None,
55 }
56}
57
58pub fn as_name_mut(expr: &mut Expression) -> Option<&mut Name> {
59 match expr {
60 Expression::Name(name) => Some(name.as_mut()),
61 _ => None,
62 }
63}
64
65pub trait HasDesignator {
66 fn designator(&self) -> &Designator;
67}
68
69impl<T: HasDesignator> HasDesignator for WithTokenSpan<T> {
70 fn designator(&self) -> &Designator {
71 self.item.designator()
72 }
73}
74
75impl HasDesignator for Designator {
76 fn designator(&self) -> &Designator {
77 self
78 }
79}
80
81impl<T: HasDesignator> HasDesignator for WithRef<T> {
82 fn designator(&self) -> &Designator {
83 self.item.designator()
84 }
85}
86
87impl HasIdent for WithRef<Ident> {
88 fn ident(&self) -> &Ident {
89 &self.item
90 }
91}
92
93impl Designator {
94 pub fn into_ref(self) -> WithRef<Designator> {
95 WithRef::new(self)
96 }
97}
98
99impl Ident {
100 pub fn into_ref(self) -> WithRef<Ident> {
101 WithRef::new(self)
102 }
103}
104
105impl WithTokenSpan<Designator> {
106 pub fn into_ref(self) -> WithTokenSpan<WithRef<Designator>> {
107 self.map_into(|name| name.into_ref())
108 }
109}
110
111impl WithToken<Designator> {
112 pub fn into_ref(self) -> WithToken<WithRef<Designator>> {
113 self.map_into(|name| name.into_ref())
114 }
115}
116
117pub trait HasIdent {
118 fn ident(&self) -> &Ident;
119 fn name(&self) -> &Symbol {
120 &self.ident().item
121 }
122
123 fn ident_pos<'a>(&'a self, ctx: &'a dyn TokenAccess) -> &'a SrcPos {
124 self.ident().pos(ctx)
125 }
126}
127
128impl HasIdent for Ident {
129 fn ident(&self) -> &Ident {
130 self
131 }
132}
133
134impl<T: HasIdent> HasIdent for WithDecl<T> {
135 fn ident(&self) -> &Ident {
136 self.tree.ident()
137 }
138}
139
140impl HasIdent for EntityDeclaration {
141 fn ident(&self) -> &Ident {
142 self.ident.ident()
143 }
144}
145
146impl HasIdent for PackageDeclaration {
147 fn ident(&self) -> &Ident {
148 self.ident.ident()
149 }
150}
151
152impl HasIdent for PackageBody {
153 fn ident(&self) -> &Ident {
154 &self.ident.tree
155 }
156}
157
158impl HasIdent for ArchitectureBody {
159 fn ident(&self) -> &Ident {
160 self.ident.ident()
161 }
162}
163
164impl HasIdent for PackageInstantiation {
165 fn ident(&self) -> &Ident {
166 self.ident.ident()
167 }
168}
169
170impl HasIdent for ContextDeclaration {
171 fn ident(&self) -> &Ident {
172 self.ident.ident()
173 }
174}
175
176impl HasIdent for ConfigurationDeclaration {
177 fn ident(&self) -> &Ident {
178 self.ident.ident()
179 }
180}
181
182impl HasIdent for AnyPrimaryUnit {
183 fn ident(&self) -> &Ident {
184 match self {
185 AnyPrimaryUnit::Entity(ref unit) => unit.ident(),
186 AnyPrimaryUnit::Configuration(ref unit) => unit.ident(),
187 AnyPrimaryUnit::Package(ref unit) => unit.ident(),
188 AnyPrimaryUnit::PackageInstance(ref unit) => unit.ident(),
189 AnyPrimaryUnit::Context(ref unit) => unit.ident(),
190 }
191 }
192}
193
194impl HasIdent for AnySecondaryUnit {
195 fn ident(&self) -> &Ident {
196 match self {
197 AnySecondaryUnit::PackageBody(ref unit) => unit.ident(),
198 AnySecondaryUnit::Architecture(ref unit) => unit.ident(),
199 }
200 }
201}
202
203impl HasIdent for AnyDesignUnit {
204 fn ident(&self) -> &Ident {
205 match self {
206 AnyDesignUnit::Primary(ref unit) => unit.ident(),
207 AnyDesignUnit::Secondary(ref unit) => unit.ident(),
208 }
209 }
210}
211
212impl<'a, T: HasIdent> From<&'a T> for WithToken<Designator> {
213 fn from(other: &'a T) -> WithToken<Designator> {
214 other.ident().to_owned().map_into(Designator::Identifier)
215 }
216}
217
218pub trait HasPrimaryIdent {
220 fn primary_ident(&self) -> &Ident;
221 fn primary_name(&self) -> &Symbol {
222 &self.primary_ident().item
223 }
224}
225
226impl HasPrimaryIdent for ArchitectureBody {
227 fn primary_ident(&self) -> &Ident {
228 &self.entity_name.item
229 }
230}
231
232impl HasPrimaryIdent for PackageBody {
233 fn primary_ident(&self) -> &Ident {
234 &self.ident.tree
235 }
236}
237
238impl HasPrimaryIdent for AnySecondaryUnit {
239 fn primary_ident(&self) -> &Ident {
240 match self {
241 AnySecondaryUnit::Architecture(unit) => unit.primary_ident(),
242 AnySecondaryUnit::PackageBody(unit) => unit.primary_ident(),
243 }
244 }
245}
246
247impl From<EnumerationLiteral> for Designator {
248 fn from(other: EnumerationLiteral) -> Designator {
249 match other {
250 EnumerationLiteral::Identifier(ident) => Designator::Identifier(ident),
251 EnumerationLiteral::Character(byte) => Designator::Character(byte),
252 }
253 }
254}
255
256impl From<Symbol> for Designator {
257 fn from(other: Symbol) -> Designator {
258 Designator::Identifier(other)
259 }
260}
261
262impl From<WithTokenSpan<Symbol>> for WithTokenSpan<Designator> {
263 fn from(other: WithTokenSpan<Symbol>) -> WithTokenSpan<Designator> {
264 other.map_into(|sym| sym.into())
265 }
266}
267
268impl<'a> From<&'a Symbol> for Designator {
269 fn from(other: &'a Symbol) -> Designator {
270 other.clone().into()
271 }
272}
273
274impl SubprogramDesignator {
275 pub fn into_designator(self) -> Designator {
276 match self {
277 SubprogramDesignator::Identifier(ident) => Designator::Identifier(ident),
278 SubprogramDesignator::OperatorSymbol(ident) => Designator::OperatorSymbol(ident),
279 }
280 }
281}
282
283impl SubprogramSpecification {
284 pub fn token(&self) -> TokenId {
285 match self {
286 SubprogramSpecification::Function(ref function) => function.designator.tree.token,
287 SubprogramSpecification::Procedure(ref procedure) => procedure.designator.tree.token,
288 }
289 }
290}
291
292impl EnumerationLiteral {
293 pub fn into_designator(self) -> Designator {
294 match self {
295 EnumerationLiteral::Identifier(ident) => Designator::Identifier(ident),
296 EnumerationLiteral::Character(byte) => Designator::Character(byte),
297 }
298 }
299}
300
301impl Designator {
302 pub fn as_identifier(&self) -> Option<&Symbol> {
303 if let Designator::Identifier(sym) = self {
304 Some(sym)
305 } else {
306 None
307 }
308 }
309
310 pub fn expect_identifier(&self) -> &Symbol {
311 self.as_identifier().unwrap()
312 }
313
314 pub fn describe(&self) -> String {
315 match self {
316 Designator::Character(chr) => format!("'{chr}'"),
317 Designator::Identifier(ident) => format!("'{ident}'"),
318 Designator::OperatorSymbol(op) => format!("operator \"{op}\""),
319 Designator::Anonymous(_) => "<anonymous>".to_owned(),
320 }
321 }
322}
323
324impl Name {
325 pub fn suffix_reference_mut(&mut self) -> Option<&mut Reference> {
326 match self {
327 Name::Designator(suffix) => Some(&mut suffix.reference),
328 Name::Selected(_, suffix) => Some(&mut suffix.item.reference),
329 _ => None,
330 }
331 }
332
333 pub fn get_suffix_reference(&self) -> Option<EntityId> {
335 match self {
336 Name::Designator(suffix) => suffix.reference.get(),
337 Name::Selected(_, suffix) => suffix.item.reference.get(),
338 _ => None,
339 }
340 }
341
342 pub fn get_suffix_reference_disregard_index(&self) -> Option<EntityId> {
345 use Name::*;
346 match self {
347 Designator(suffix) => suffix.reference.get(),
348 Selected(_, suffix) => suffix.item.reference.get(),
349 Slice(name, _) => name.item.get_suffix_reference_disregard_index(),
350 CallOrIndexed(coi) => coi.name.item.get_suffix_reference_disregard_index(),
351 _ => None,
352 }
353 }
354
355 pub fn prefix(&self) -> Option<&Designator> {
356 match self {
357 Self::Attribute(attr) => attr.name.item.prefix(),
358 Self::Designator(d) => Some(d.designator()),
359 Self::External(..) => None,
360 Self::CallOrIndexed(fcall) => fcall.name.item.prefix(),
361 Self::SelectedAll(name) => name.item.prefix(),
362 Self::Selected(name, ..) => name.item.prefix(),
363 Self::Slice(name, ..) => name.item.prefix(),
364 }
365 }
366
367 pub fn is_selected_name(&self) -> bool {
370 match self {
371 Name::Designator(_) => true,
372 Name::Selected(prefix, _) => prefix.item.is_selected_name(),
373 _ => false,
374 }
375 }
376}
377
378impl CallOrIndexed {
379 pub fn as_indexed(&mut self) -> Option<IndexedName<'_>> {
382 if !self.could_be_indexed_name() {
383 return None;
384 }
385
386 let CallOrIndexed {
387 ref mut name,
388 ref mut parameters,
389 } = self;
390
391 let mut indexes: Vec<Index<'_>> = Vec::with_capacity(parameters.items.len());
392
393 for elem in parameters.items.iter_mut() {
394 if let ActualPart::Expression(ref mut expr) = &mut elem.actual.item {
395 indexes.push(Index {
396 pos: elem.actual.span,
397 expr,
398 });
399 }
400 }
401
402 Some(IndexedName { name, indexes })
403 }
404
405 pub fn could_be_indexed_name(&self) -> bool {
406 self.parameters
407 .items
408 .iter()
409 .all(|assoc| assoc.formal.is_none() && !matches!(assoc.actual.item, ActualPart::Open))
410 }
411}
412
413pub struct IndexedName<'a> {
414 pub name: &'a mut WithTokenSpan<Name>,
415 pub indexes: Vec<Index<'a>>,
416}
417
418pub struct Index<'a> {
419 pub pos: TokenSpan,
420 pub expr: &'a mut Expression,
421}
422
423impl AttributeName {
424 pub fn as_range(&self) -> Option<RangeAttribute> {
425 if let AttributeDesignator::Range(r) = self.attr.item {
426 Some(r)
427 } else {
428 None
429 }
430 }
431
432 pub fn as_type(&self) -> Option<TypeAttribute> {
433 if self.signature.is_none() && self.expr.is_none() {
434 if let AttributeDesignator::Type(t) = self.attr.item {
435 Some(t)
436 } else {
437 None
438 }
439 } else {
440 None
441 }
442 }
443}
444
445impl RangeConstraint {
446 pub fn span(&self) -> TokenSpan {
447 self.left_expr.span.combine(self.right_expr.span)
448 }
449}
450
451impl crate::ast::Range {
452 pub fn span(&self) -> TokenSpan {
453 use crate::ast::Range::*;
454 match self {
455 Range(constraint) => constraint.span(),
456 Attribute(attr) => attr.name.span.end_with(attr.attr.token),
457 }
458 }
459}
460
461impl DiscreteRange {
462 pub fn span(&self) -> TokenSpan {
463 match self {
464 DiscreteRange::Discrete(type_mark, _) => type_mark.span,
465 DiscreteRange::Range(range) => range.span(),
466 }
467 }
468}
469
470impl SubprogramSpecification {
471 pub fn subpgm_designator(&self) -> &WithToken<SubprogramDesignator> {
472 match self {
473 SubprogramSpecification::Procedure(s) => &s.designator.tree,
474 SubprogramSpecification::Function(s) => &s.designator.tree,
475 }
476 }
477
478 pub fn reference_mut(&mut self) -> &mut Reference {
479 match self {
480 SubprogramSpecification::Function(ref mut function) => &mut function.designator.decl,
481 SubprogramSpecification::Procedure(ref mut procedure) => &mut procedure.designator.decl,
482 }
483 }
484}
485
486impl SubprogramDeclaration {
487 pub fn subpgm_designator(&self) -> &WithToken<SubprogramDesignator> {
488 self.specification.subpgm_designator()
489 }
490
491 pub fn reference_mut(&mut self) -> &mut Reference {
492 self.specification.reference_mut()
493 }
494}
495
496impl ConcurrentStatement {
497 pub fn label_typ(&self) -> Option<Concurrent> {
498 use ConcurrentStatement::*;
499 match self {
500 ProcedureCall(_) => None,
501 Block(_) => Some(Concurrent::Block),
502 Process(_) => Some(Concurrent::Process),
503 Assert(_) => None,
504 Assignment(_) => None,
505 Instance(_) => Some(Concurrent::Instance),
506 ForGenerate(_) | IfGenerate(_) | CaseGenerate(_) => Some(Concurrent::Generate),
507 }
508 }
509
510 pub fn end_label_pos(&self) -> Option<&SrcPos> {
511 use ConcurrentStatement::*;
512
513 match self {
514 ProcedureCall(_) => None,
515 Block(value) => value.end_label_pos.as_ref(),
516 Process(value) => value.end_label_pos.as_ref(),
517 Assert(_) => None,
518 Assignment(_) => None,
519 Instance(_) => None,
520 ForGenerate(value) => value.end_label_pos.as_ref(),
521 IfGenerate(value) => value.end_label_pos.as_ref(),
522 CaseGenerate(value) => value.end_label_pos.as_ref(),
523 }
524 }
525
526 pub fn can_have_label(&self) -> bool {
527 self.label_typ().is_some()
528 }
529}
530
531impl SequentialStatement {
532 pub fn label_typ(&self) -> Option<Sequential> {
533 use SequentialStatement::*;
534 match self {
535 Wait(_) => None,
536 Assert(_) => None,
537 Report(_) => None,
538 VariableAssignment(_) => None,
539 SignalAssignment(_) => None,
540 SignalForceAssignment(_) => None,
541 SignalReleaseAssignment(_) => None,
542 ProcedureCall(_) => None,
543 If(_) => Some(Sequential::If),
544 Case(_) => Some(Sequential::Case),
545 Loop(_) => Some(Sequential::Loop),
546 Next(_) => None,
547 Exit(_) => None,
548 Return(_) => None,
549 Null => None,
550 }
551 }
552
553 pub fn end_label_pos(&self) -> Option<&SrcPos> {
554 use SequentialStatement::*;
555 match self {
556 Wait(_) => None,
557 Assert(_) => None,
558 Report(_) => None,
559 VariableAssignment(_) => None,
560 SignalAssignment(_) => None,
561 SignalForceAssignment(_) => None,
562 SignalReleaseAssignment(_) => None,
563 ProcedureCall(_) => None,
564 If(value) => value.end_label_pos.as_ref(),
565 Case(value) => value.end_label_pos.as_ref(),
566 Loop(value) => value.end_label_pos.as_ref(),
567 Next(_) => None,
568 Exit(_) => None,
569 Return(_) => None,
570 Null => None,
571 }
572 }
573
574 pub fn can_have_label(&self) -> bool {
575 self.label_typ().is_some()
576 }
577}