moore_vhdl_syntax/
ast.rs

1// Copyright (c) 2016-2021 Fabian Schuiki
2
3//! This module implements an abstract syntax tree for VHDL. It is emitted by
4//! the parser.
5
6use std;
7use std::fmt;
8
9use crate::lexer::token::Literal;
10use moore_common::name::Name;
11use moore_common::source::{Span, Spanned};
12use moore_common::util::{HasDesc, HasSpan};
13
14pub use self::ExprData::*;
15pub use self::StmtData::*;
16pub use self::TypeData::*;
17
18/// A positive, small ID assigned to each node in the AST. Used as a lightweight
19/// way to refer to individual nodes, e.g. during symbol table construction and
20/// name resolution.
21#[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash, Debug)]
22pub struct NodeId(u32);
23
24impl NodeId {
25    pub fn new(x: usize) -> NodeId {
26        use std::u32;
27        assert!(x < (u32::MAX as usize));
28        NodeId(x as u32)
29    }
30
31    pub fn from_u32(x: u32) -> NodeId {
32        NodeId(x)
33    }
34
35    pub fn as_usize(&self) -> usize {
36        self.0 as usize
37    }
38
39    pub fn as_u32(&self) -> u32 {
40        self.0
41    }
42}
43
44impl std::fmt::Display for NodeId {
45    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
46        write!(f, "{}", self.0)
47    }
48}
49
50impl Default for NodeId {
51    fn default() -> NodeId {
52        DUMMY_NODE_ID
53    }
54}
55
56/// During parsing and syntax tree construction, we assign each node this ID.
57/// Only later, during the renumbering pass do we assign actual IDs to each
58/// node.
59pub const DUMMY_NODE_ID: NodeId = NodeId(0);
60
61/// A design unit. Multiple design units make up a design file. Each unit
62/// consists of an optional context clause followed by a primary or secondary
63/// unit.
64#[derive(Clone, Debug, PartialEq, Eq)]
65pub struct DesignUnit {
66    pub id: NodeId,
67    pub ctx: Vec<CtxItem>,
68    pub data: DesignUnitData,
69}
70
71#[derive(Clone, Debug, PartialEq, Eq)]
72pub enum DesignUnitData {
73    EntityDecl(EntityDecl),
74    CfgDecl(CfgDecl),
75    PkgDecl(PkgDecl),
76    PkgInst(PkgInst),
77    CtxDecl(CtxDecl),
78    ArchBody(ArchBody),
79    PkgBody(PkgBody),
80}
81
82/// A context item, multiple of which make up a context clause.
83#[derive(Clone, Debug, PartialEq, Eq)]
84pub enum CtxItem {
85    LibClause(Spanned<Vec<Ident>>),
86    UseClause(Spanned<Vec<CompoundName>>),
87    CtxRef(Spanned<Vec<CompoundName>>),
88}
89
90/// An identifier. Has a node ID such that it may be referenced later on.
91#[derive(Copy, Clone, Debug, PartialEq, Eq)]
92// #[deprecated(note="use `Spanned<Name>` instead of `Ident`")]
93pub struct Ident {
94    pub id: NodeId,
95    pub span: Span,
96    pub name: Name,
97}
98
99impl From<Spanned<Name>> for Ident {
100    fn from(n: Spanned<Name>) -> Ident {
101        Ident {
102            id: Default::default(),
103            span: n.span,
104            name: n.value,
105        }
106    }
107}
108
109impl Into<Spanned<Name>> for Ident {
110    fn into(self) -> Spanned<Name> {
111        Spanned::new(self.name, self.span)
112    }
113}
114
115/// A compound name consisting of a primary name (identifier, character literal,
116/// or string literal), and zero or more suffices (select, attribute, call). The
117/// names in *IEEE 1076-2008 section 8.1* map to this as follows:
118///
119/// | In the standard     | In this module                  |
120/// |---------------------|---------------------------------|
121/// | simple_name         | `PrimaryNameKind::Ident`        |
122/// | operator_symbol     | `PrimaryNameKind::String`       |
123/// | character_literal   | `PrimaryNameKind::Char`         |
124/// | selected_name       | `NamePart::{Select, SelectAll}` |
125/// | indexed_name        | `NamePart::Call`                |
126/// | slice_name          | `NamePart::Call`                |
127/// | function_call       | `NamePart::Call`                |
128/// | attribute_name      | `NamePart::Attribute`           |
129/// | external_name       | not implemented                 |
130///
131#[derive(Clone, Debug, PartialEq, Eq)]
132pub struct CompoundName {
133    pub id: NodeId,
134    pub span: Span,
135    pub primary: PrimaryName,
136    pub parts: Vec<NamePart>,
137}
138
139impl HasSpan for CompoundName {
140    fn span(&self) -> Span {
141        self.span
142    }
143}
144
145impl HasDesc for CompoundName {
146    fn desc(&self) -> &'static str {
147        "name"
148    }
149}
150
151#[derive(Copy, Clone, Debug, PartialEq, Eq)]
152pub struct PrimaryName {
153    pub id: NodeId,
154    pub span: Span,
155    pub kind: PrimaryNameKind,
156}
157
158#[derive(Copy, Clone, Debug, PartialEq, Eq)]
159pub enum PrimaryNameKind {
160    Ident(Name),
161    Char(char),
162    String(Name),
163}
164
165#[derive(Clone, Debug, PartialEq, Eq)]
166pub enum NamePart {
167    Select(PrimaryName),
168    SelectAll(Span),
169    Signature(Signature),
170    Attribute(Ident),
171    Call(ParenElems),
172    Range(Box<Expr>),
173}
174
175/// A context declaration.
176#[derive(Clone, Debug, PartialEq, Eq)]
177pub struct CtxDecl {
178    pub id: NodeId,
179    pub span: Span,
180    pub name: Spanned<Name>,
181    pub items: Vec<CtxItem>,
182}
183
184/// An entity declaration.
185#[derive(Clone, Debug, PartialEq, Eq)]
186pub struct EntityDecl {
187    pub id: NodeId,
188    pub span: Span,
189    pub name: Spanned<Name>,
190    pub decls: Vec<DeclItem>,
191    pub stmts: Option<Vec<Stmt>>,
192}
193
194/// A configuration declaration.
195#[derive(Clone, Debug, PartialEq, Eq)]
196pub struct CfgDecl {
197    pub id: NodeId,
198    pub span: Span,
199    pub name: Spanned<Name>,
200    pub target: CompoundName,
201    pub decls: Vec<DeclItem>,
202}
203
204/// An architecture body.
205#[derive(Clone, Debug, PartialEq, Eq)]
206pub struct ArchBody {
207    pub id: NodeId,
208    pub span: Span,
209    pub name: Spanned<Name>,
210    pub target: CompoundName,
211    pub decls: Vec<DeclItem>,
212    pub stmts: Vec<Stmt>,
213}
214
215/// A package declaration.
216#[derive(Clone, Debug, PartialEq, Eq)]
217pub struct PkgDecl {
218    pub id: NodeId,
219    pub span: Span,
220    pub name: Spanned<Name>,
221    pub decls: Vec<DeclItem>,
222}
223
224/// A package body.
225#[derive(Clone, Debug, PartialEq, Eq)]
226pub struct PkgBody {
227    pub id: NodeId,
228    pub span: Span,
229    pub name: Spanned<Name>,
230    pub decls: Vec<DeclItem>,
231}
232
233/// A package instantiation declaration.
234#[derive(Clone, Debug, PartialEq, Eq)]
235pub struct PkgInst {
236    pub id: NodeId,
237    pub span: Span,
238    pub name: Spanned<Name>,
239    pub target: CompoundName,
240    pub generics: Option<ParenElems>,
241}
242
243/// An interface declaration.
244#[derive(Clone, Debug, PartialEq, Eq)]
245pub enum IntfDecl {
246    TypeDecl(TypeDecl),
247    SubprogSpec(IntfSubprogDecl),
248    PkgInst(PkgInst),
249    ObjDecl(IntfObjDecl),
250}
251
252impl HasSpan for IntfDecl {
253    fn span(&self) -> Span {
254        match *self {
255            IntfDecl::TypeDecl(ref n) => n.span,
256            IntfDecl::SubprogSpec(ref n) => n.span,
257            IntfDecl::PkgInst(ref n) => n.span,
258            IntfDecl::ObjDecl(ref n) => n.span,
259        }
260    }
261
262    fn human_span(&self) -> Span {
263        match *self {
264            IntfDecl::TypeDecl(ref n) => n.name.span,
265            IntfDecl::PkgInst(ref n) => n.name.span,
266            _ => self.span(),
267        }
268    }
269}
270
271impl HasDesc for IntfDecl {
272    fn desc(&self) -> &'static str {
273        match *self {
274            IntfDecl::TypeDecl(_) => "interface type declaration",
275            IntfDecl::SubprogSpec(_) => "interface subprogram declaration",
276            IntfDecl::PkgInst(_) => "interface package declaration",
277            IntfDecl::ObjDecl(ref n) => n.desc(),
278        }
279    }
280}
281
282#[derive(Clone, Debug, PartialEq, Eq)]
283pub struct IntfSubprogDecl {
284    pub id: NodeId,
285    pub span: Span,
286    pub spec: SubprogSpec,
287    pub default: Option<SubprogDefault>,
288}
289
290#[derive(Clone, Debug, PartialEq, Eq)]
291pub enum SubprogDefault {
292    Any,
293    Name(CompoundName),
294}
295
296/// An interface object declaration.
297#[derive(Clone, Debug, PartialEq, Eq)]
298pub struct IntfObjDecl {
299    pub kind: IntfObjKind,
300    pub span: Span,
301    pub names: Vec<Ident>,
302    pub mode: Option<IntfMode>,
303    pub ty: SubtypeInd,
304    pub bus: bool,
305    pub default: Option<Expr>,
306}
307
308impl HasDesc for IntfObjDecl {
309    fn desc(&self) -> &'static str {
310        match self.kind {
311            IntfObjKind::Const => "interface constant declaration",
312            IntfObjKind::Signal => "interface signal declaration",
313            IntfObjKind::Var => "interface variable declaration",
314            IntfObjKind::File => "interface file declaration",
315        }
316    }
317}
318
319#[derive(Clone, Copy, Debug, PartialEq, Eq)]
320pub enum IntfObjKind {
321    Const,
322    Signal,
323    Var,
324    File,
325}
326
327#[derive(Clone, Copy, Debug, PartialEq, Eq)]
328pub enum IntfMode {
329    In,
330    Out,
331    Inout,
332    Buffer,
333    Linkage,
334}
335
336/// A declarative item.
337#[derive(Clone, Debug, PartialEq, Eq)]
338pub enum DeclItem {
339    PkgBody(PkgBody),
340    PkgInst(PkgInst),
341    PkgDecl(PkgDecl),
342    TypeDecl(TypeDecl),
343    SubtypeDecl(SubtypeDecl),
344    ObjDecl(ObjDecl),
345    AliasDecl(AliasDecl),
346    UseClause(Span, Spanned<Vec<CompoundName>>),
347    SubprogDecl(Subprog),
348    CompDecl(CompDecl),
349    DisconDecl(DisconSpec),
350    CfgSpec(CfgSpec),
351    AttrDecl(AttrDecl),
352    PortgenMap(Span, Spanned<PortgenKind>, ParenElems),
353    PortgenClause(Span, Spanned<PortgenKind>, Spanned<Vec<IntfDecl>>),
354    GroupDecl(GroupDecl),
355    VunitBindInd(()),
356    BlockCompCfg(BlockCompCfg),
357}
358
359impl HasSpan for DeclItem {
360    fn span(&self) -> Span {
361        match *self {
362            DeclItem::PkgBody(ref n) => n.span,
363            DeclItem::PkgInst(ref n) => n.span,
364            DeclItem::PkgDecl(ref n) => n.span,
365            DeclItem::TypeDecl(ref n) => n.span,
366            DeclItem::SubtypeDecl(ref n) => n.span,
367            DeclItem::ObjDecl(ref n) => n.span,
368            DeclItem::AliasDecl(ref n) => n.span,
369            DeclItem::UseClause(sp, ref n) => Span::union(sp, n.span),
370            DeclItem::SubprogDecl(ref n) => n.span(),
371            DeclItem::CompDecl(ref n) => n.span,
372            DeclItem::DisconDecl(ref n) => n.span,
373            DeclItem::CfgSpec(ref n) => n.span,
374            DeclItem::AttrDecl(ref n) => n.span,
375            DeclItem::PortgenMap(sp, _, _) => sp,
376            DeclItem::PortgenClause(sp, _, _) => sp,
377            DeclItem::GroupDecl(ref n) => n.span,
378            DeclItem::VunitBindInd(_) => unimplemented!(),
379            DeclItem::BlockCompCfg(ref n) => n.span,
380        }
381    }
382
383    fn human_span(&self) -> Span {
384        match *self {
385            DeclItem::PkgBody(ref n) => n.name.span,
386            DeclItem::PkgInst(ref n) => n.name.span,
387            DeclItem::PkgDecl(ref n) => n.name.span,
388            DeclItem::TypeDecl(ref n) => n.name.span,
389            DeclItem::SubtypeDecl(ref n) => n.name.span,
390            DeclItem::AliasDecl(ref n) => n.name.span,
391            DeclItem::UseClause(sp, _) => sp,
392            DeclItem::SubprogDecl(ref n) => n.human_span(),
393            DeclItem::PortgenMap(_, Spanned { span, .. }, _) => span,
394            DeclItem::PortgenClause(_, Spanned { span, .. }, _) => span,
395            _ => self.span(),
396        }
397    }
398}
399
400impl HasDesc for DeclItem {
401    fn desc(&self) -> &'static str {
402        match *self {
403            DeclItem::PkgBody(..) => "package body",
404            DeclItem::PkgInst(..) => "package instance",
405            DeclItem::PkgDecl(..) => "package declaration",
406            DeclItem::TypeDecl(..) => "type declaration",
407            DeclItem::SubtypeDecl(..) => "subtype declaration",
408            DeclItem::ObjDecl(..) => "object declaration",
409            DeclItem::AliasDecl(..) => "alias declaration",
410            DeclItem::UseClause(..) => "use clause",
411            DeclItem::SubprogDecl(ref n) => n.desc(),
412            DeclItem::CompDecl(..) => "component declaration",
413            DeclItem::DisconDecl(..) => "disconnection declaration",
414            DeclItem::CfgSpec(..) => "configuration specification",
415            DeclItem::AttrDecl(..) => "attribute declaration",
416            DeclItem::PortgenMap(
417                _,
418                Spanned {
419                    value: PortgenKind::Port,
420                    ..
421                },
422                ..,
423            ) => "port map",
424            DeclItem::PortgenMap(
425                _,
426                Spanned {
427                    value: PortgenKind::Generic,
428                    ..
429                },
430                ..,
431            ) => "generic map",
432            DeclItem::PortgenClause(
433                _,
434                Spanned {
435                    value: PortgenKind::Port,
436                    ..
437                },
438                ..,
439            ) => "port clause",
440            DeclItem::PortgenClause(
441                _,
442                Spanned {
443                    value: PortgenKind::Generic,
444                    ..
445                },
446                ..,
447            ) => "generic clause",
448            DeclItem::GroupDecl(..) => "group declaration",
449            DeclItem::VunitBindInd(..) => "vunit binding indication",
450            DeclItem::BlockCompCfg(..) => "block component configuration",
451        }
452    }
453}
454
455#[derive(Copy, Clone, Debug, PartialEq, Eq)]
456pub enum PortgenKind {
457    Port,
458    Generic,
459}
460
461#[derive(Clone, Debug, PartialEq, Eq)]
462pub struct Subprog {
463    pub id: NodeId,
464    pub span: Span,
465    pub spec: SubprogSpec,
466    pub data: SubprogData,
467}
468
469impl HasSpan for Subprog {
470    fn span(&self) -> Span {
471        self.span
472    }
473
474    fn human_span(&self) -> Span {
475        self.spec.name.span
476    }
477}
478
479impl HasDesc for Subprog {
480    fn desc(&self) -> &'static str {
481        self.data.desc()
482    }
483}
484
485#[derive(Clone, Debug, PartialEq, Eq)]
486pub enum SubprogData {
487    Decl,
488    Inst {
489        name: CompoundName,
490        generics: Option<ParenElems>,
491    },
492    Body {
493        decls: Vec<DeclItem>,
494        stmts: Vec<Stmt>,
495    },
496}
497
498impl HasDesc for SubprogData {
499    fn desc(&self) -> &'static str {
500        match *self {
501            SubprogData::Decl => "subprogram declaration",
502            SubprogData::Inst { .. } => "subprogram instantiation",
503            SubprogData::Body { .. } => "subprogram body",
504        }
505    }
506}
507
508#[derive(Clone, Debug, PartialEq, Eq)]
509pub struct SubprogSpec {
510    pub span: Span,
511    pub name: PrimaryName,
512    pub kind: SubprogKind,
513    pub purity: Option<SubprogPurity>,
514    pub generic_clause: Option<Vec<IntfDecl>>,
515    pub generic_map: Option<ParenElems>,
516    pub params: Option<Vec<IntfDecl>>,
517    pub retty: Option<CompoundName>,
518}
519
520#[derive(Copy, Clone, Debug, PartialEq, Eq)]
521pub enum SubprogPurity {
522    Pure,
523    Impure,
524}
525
526#[derive(Copy, Clone, Debug, PartialEq, Eq)]
527pub enum SubprogKind {
528    Proc,
529    Func,
530}
531
532#[derive(Clone, Debug, PartialEq, Eq)]
533pub struct SubtypeInd {
534    pub span: Span,
535    pub res: Option<ResolInd>,
536    pub name: CompoundName,
537}
538
539impl HasSpan for SubtypeInd {
540    fn span(&self) -> Span {
541        self.span
542    }
543}
544
545impl HasDesc for SubtypeInd {
546    fn desc(&self) -> &'static str {
547        "subtype indication"
548    }
549}
550
551#[derive(Clone, Debug, PartialEq, Eq)]
552pub struct SubtypeDecl {
553    pub id: NodeId,
554    pub span: Span,
555    pub name: Spanned<Name>,
556    pub subtype: SubtypeInd,
557}
558
559#[derive(Clone, Debug, PartialEq, Eq)]
560pub enum ResolInd {
561    Exprs(ParenElems),
562    Name(CompoundName),
563}
564
565/// An alias declaration.
566#[derive(Clone, Debug, PartialEq, Eq)]
567pub struct AliasDecl {
568    pub id: NodeId,
569    pub span: Span,
570    pub name: PrimaryName,
571    pub subtype: Option<SubtypeInd>,
572    pub target: CompoundName,
573}
574
575#[derive(Clone, Debug, PartialEq, Eq)]
576pub struct ObjDecl {
577    pub span: Span,
578    pub kind: ObjKind,
579    pub names: Vec<Ident>,
580    pub subtype: SubtypeInd,
581    pub detail: Option<Spanned<ObjDetail>>,
582    pub init: Option<Expr>,
583}
584
585#[derive(Copy, Clone, Debug, PartialEq, Eq)]
586pub enum ObjKind {
587    Const,
588    Signal,
589    File,
590    Var,
591    SharedVar,
592}
593
594/// Additional mutually exclusive details that may be provided with an object
595/// declaration.
596#[derive(Clone, Debug, PartialEq, Eq)]
597pub enum ObjDetail {
598    Register,
599    Bus,
600    /// A file opening action.
601    Open(Option<Expr>, Expr),
602}
603
604impl HasSpan for ObjDecl {
605    fn span(&self) -> Span {
606        self.span
607    }
608
609    fn human_span(&self) -> Span {
610        self.names
611            .iter()
612            .map(|n| n.span)
613            .fold(self.names[0].span, Span::union)
614    }
615}
616
617impl HasDesc for ObjDecl {
618    fn desc(&self) -> &'static str {
619        match self.kind {
620            ObjKind::Const => "constant declaration",
621            ObjKind::Signal => "signal declaration",
622            ObjKind::File => "file declaration",
623            ObjKind::Var => "variable declaration",
624            ObjKind::SharedVar => "shared variable declaration",
625        }
626    }
627}
628
629/// A component declaration.
630#[derive(Clone, Debug, PartialEq, Eq)]
631pub struct CompDecl {
632    pub id: NodeId,
633    pub span: Span,
634    pub name: Spanned<Name>,
635    pub generics: Option<Spanned<Vec<IntfDecl>>>,
636    pub ports: Option<Spanned<Vec<IntfDecl>>>,
637}
638
639#[derive(Clone, Debug, PartialEq, Eq)]
640pub struct DisconSpec {
641    pub span: Span,
642    pub target: DisconTarget,
643    pub ty: CompoundName,
644    pub after: Expr,
645}
646
647#[derive(Clone, Debug, PartialEq, Eq)]
648pub enum DisconTarget {
649    Others,
650    All,
651    Signals(Vec<CompoundName>),
652}
653
654#[derive(Clone, Debug, PartialEq, Eq)]
655pub struct BlockCompCfg {
656    pub span: Span,
657    pub spec: Spanned<BlockCompSpec>,
658    pub bind: BindingInd,
659    pub decls: Vec<DeclItem>,
660}
661
662#[derive(Clone, Debug, PartialEq, Eq)]
663pub enum BlockCompSpec {
664    CompOthers(CompoundName),
665    CompAll(CompoundName),
666    CompNames(Vec<Ident>, CompoundName),
667    Block(CompoundName),
668}
669
670#[derive(Clone, Debug, PartialEq, Eq)]
671pub struct BindingInd {
672    pub span: Span,
673    pub entity: Option<EntityAspect>,
674    pub generics: Option<ParenElems>,
675    pub ports: Option<ParenElems>,
676}
677
678#[derive(Clone, Debug, PartialEq, Eq)]
679pub enum EntityAspect {
680    Entity(CompoundName),
681    Cfg(CompoundName),
682    Open,
683}
684
685#[derive(Clone, Debug, PartialEq, Eq)]
686pub struct CfgSpec {
687    pub span: Span,
688    pub spec: Spanned<BlockCompSpec>,
689    pub bind: BindingInd,
690    pub vunits: Vec<()>,
691}
692
693#[derive(Clone, Debug, PartialEq, Eq)]
694pub struct AttrDecl {
695    pub id: NodeId,
696    pub span: Span,
697    pub name: Spanned<Name>,
698    pub data: AttrData,
699}
700
701#[derive(Clone, Debug, PartialEq, Eq)]
702pub enum AttrData {
703    Decl(CompoundName),
704    Spec {
705        target: AttrTarget,
706        cls: EntityClass,
707        expr: Expr,
708    },
709}
710
711#[derive(Clone, Debug, PartialEq, Eq)]
712pub enum AttrTarget {
713    Others,
714    All,
715    List(Vec<(CompoundName, Option<Signature>)>),
716}
717
718#[derive(Copy, Clone, Debug, PartialEq, Eq)]
719pub enum EntityClass {
720    Arch,
721    Comp,
722    Cfg,
723    Const,
724    Entity,
725    File,
726    Func,
727    Group,
728    Label,
729    Literal,
730    Pkg,
731    Proc,
732    Prop,
733    Seq,
734    Signal,
735    Subtype,
736    Type,
737    Units,
738    Var,
739}
740
741#[derive(Clone, Debug, PartialEq, Eq)]
742pub struct GroupDecl {
743    pub id: NodeId,
744    pub span: Span,
745    pub name: Spanned<Name>,
746    pub data: GroupData,
747}
748
749#[derive(Clone, Debug, PartialEq, Eq)]
750pub enum GroupData {
751    /// A group declaration.
752    Decl(CompoundName),
753    /// A group template. Each element consists of an entity class, and a bool
754    /// that indicates whether a `<>` was present in the source text.
755    Temp(Vec<(EntityClass, bool)>),
756}
757
758/// A parenthesized expression element. A parenthesized expression contains
759/// elements of which each may either be a simple `<expr>`, or an association of
760/// the form `<choices> => <expr>`.
761#[derive(Clone, Debug, PartialEq, Eq)]
762pub struct ParenElem {
763    pub span: Span,
764    pub choices: Choices,
765    pub expr: Expr,
766}
767
768/// A vector of parenthesized expression elements, including the span of the
769/// expression that this would cover.
770pub type ParenElems = Spanned<Vec<ParenElem>>;
771
772/// An expression.
773#[derive(Clone, Debug, PartialEq, Eq)]
774pub struct Expr {
775    pub span: Span,
776    pub data: ExprData,
777}
778
779impl HasSpan for Expr {
780    fn span(&self) -> Span {
781        self.span
782    }
783}
784
785impl HasDesc for Expr {
786    fn desc(&self) -> &'static str {
787        self.data.desc()
788    }
789}
790
791/// The data associated with a specific expression.
792#[derive(Clone, Debug, PartialEq, Eq)]
793pub enum ExprData {
794    NullExpr,
795    OpenExpr,
796    OthersExpr,
797    DefaultExpr,
798    BoxExpr,
799    NewExpr(Box<Expr>),
800    LitExpr(Literal, Option<Spanned<Name>>),
801    ResolExpr(ParenElems, CompoundName),
802    ParenExpr(ParenElems),
803    DoubleNameExpr(CompoundName, CompoundName),
804    QualExpr(CompoundName, ParenElems),
805    NameExpr(CompoundName),
806    UnaryExpr(Spanned<UnaryOp>, Box<Expr>),
807    BinaryExpr(Spanned<BinaryOp>, Box<Expr>, Box<Expr>),
808}
809
810impl HasDesc for ExprData {
811    fn desc(&self) -> &'static str {
812        match *self {
813            NullExpr => "null expression",
814            UnaryExpr(..) => "unary expression",
815            BinaryExpr(..) => "binary expression",
816            _ => "expression",
817        }
818    }
819}
820
821#[derive(Copy, Clone, Debug, PartialEq, Eq)]
822pub enum UnaryOp {
823    Not,
824    Abs,
825    Sign(Sign),
826    Logical(LogicalOp),
827    Inertial,
828    Condition,
829}
830
831#[derive(Copy, Clone, Debug, PartialEq, Eq)]
832pub enum BinaryOp {
833    Dir(Dir),
834    Logical(LogicalOp),
835    Rel(RelationalOp),
836    Match(RelationalOp),
837    Shift(ShiftOp),
838    Add,
839    Sub,
840    Concat,
841    Mul,
842    Div,
843    Mod,
844    Rem,
845    Pow,
846}
847
848#[derive(Copy, Clone, Debug, PartialEq, Eq)]
849pub enum Dir {
850    To,
851    Downto,
852}
853
854impl std::fmt::Display for Dir {
855    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
856        match *self {
857            Dir::To => write!(f, "to"),
858            Dir::Downto => write!(f, "downto"),
859        }
860    }
861}
862
863#[derive(Copy, Clone, Debug, PartialEq, Eq)]
864pub enum Sign {
865    Pos,
866    Neg,
867}
868
869#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
870pub enum LogicalOp {
871    And,
872    Or,
873    Nand,
874    Nor,
875    Xor,
876    Xnor,
877}
878
879impl fmt::Display for LogicalOp {
880    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
881        match *self {
882            LogicalOp::And => write!(f, "and"),
883            LogicalOp::Or => write!(f, "or"),
884            LogicalOp::Nand => write!(f, "nand"),
885            LogicalOp::Nor => write!(f, "nor"),
886            LogicalOp::Xor => write!(f, "xor"),
887            LogicalOp::Xnor => write!(f, "xnor"),
888        }
889    }
890}
891
892#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
893pub enum RelationalOp {
894    Eq,
895    Neq,
896    Lt,
897    Leq,
898    Gt,
899    Geq,
900}
901
902impl fmt::Display for RelationalOp {
903    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
904        match *self {
905            RelationalOp::Eq => write!(f, "="),
906            RelationalOp::Neq => write!(f, "/="),
907            RelationalOp::Lt => write!(f, "<"),
908            RelationalOp::Leq => write!(f, "<="),
909            RelationalOp::Gt => write!(f, ">"),
910            RelationalOp::Geq => write!(f, ">="),
911        }
912    }
913}
914
915#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
916pub enum ShiftOp {
917    Sll,
918    Srl,
919    Sla,
920    Sra,
921    Rol,
922    Ror,
923}
924
925impl fmt::Display for ShiftOp {
926    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
927        match *self {
928            ShiftOp::Sll => write!(f, "sll"),
929            ShiftOp::Srl => write!(f, "srl"),
930            ShiftOp::Sla => write!(f, "sla"),
931            ShiftOp::Sra => write!(f, "sra"),
932            ShiftOp::Rol => write!(f, "rol"),
933            ShiftOp::Ror => write!(f, "ror"),
934        }
935    }
936}
937
938/// A type declaration. If the `data` field is omitted, this is an incomplete
939/// declaration.
940#[derive(Clone, Debug, PartialEq, Eq)]
941pub struct TypeDecl {
942    pub id: NodeId,
943    pub span: Span,
944    pub name: Spanned<Name>,
945    pub data: Option<Spanned<TypeData>>,
946}
947
948impl HasSpan for TypeDecl {
949    fn span(&self) -> Span {
950        self.span
951    }
952
953    fn human_span(&self) -> Span {
954        self.name.span
955    }
956}
957
958impl HasDesc for TypeDecl {
959    fn desc(&self) -> &'static str {
960        match self.data {
961            Some(ref d) => d.desc(),
962            None => "incomplete type declaration",
963        }
964    }
965}
966
967#[derive(Clone, Debug, PartialEq, Eq)]
968pub enum TypeData {
969    EnumType(ParenElems),
970    RangeType(Box<Expr>, Option<Vec<(Ident, Option<Box<Expr>>)>>),
971    ArrayType(ParenElems, SubtypeInd),
972    RecordType(Vec<(Vec<Ident>, SubtypeInd)>),
973    AccessType(SubtypeInd),
974    FileType(CompoundName),
975    ProtectedType(Vec<DeclItem>),
976}
977
978impl HasDesc for TypeData {
979    fn desc(&self) -> &'static str {
980        match *self {
981            TypeData::EnumType(..) => "enumeration type declaration",
982            TypeData::RangeType(..) => "range type declaration",
983            TypeData::ArrayType(..) => "array type declaration",
984            TypeData::RecordType(..) => "record type declaration",
985            TypeData::AccessType(..) => "access type declaration",
986            TypeData::FileType(..) => "file type declaration",
987            TypeData::ProtectedType(..) => "protected type declaration",
988        }
989    }
990}
991
992#[derive(Clone, Debug, PartialEq, Eq)]
993pub struct Stmt {
994    pub id: NodeId,
995    pub span: Span,
996    pub label: Option<Spanned<Name>>,
997    pub data: StmtData,
998}
999
1000impl HasSpan for Stmt {
1001    fn span(&self) -> Span {
1002        self.span
1003    }
1004
1005    fn human_span(&self) -> Span {
1006        match self.label {
1007            Some(Spanned { span, .. }) => span,
1008            _ => self.span(),
1009        }
1010    }
1011}
1012
1013impl HasDesc for Stmt {
1014    fn desc(&self) -> &'static str {
1015        self.data.desc()
1016    }
1017}
1018
1019#[derive(Clone, Debug, PartialEq, Eq)]
1020pub enum StmtData {
1021    WaitStmt {
1022        on: Option<Spanned<Vec<CompoundName>>>,
1023        until: Option<Expr>,
1024        time: Option<Expr>,
1025    },
1026    AssertStmt {
1027        cond: Expr,
1028        report: Option<Expr>,
1029        severity: Option<Expr>,
1030    },
1031    ReportStmt {
1032        msg: Expr,
1033        severity: Option<Expr>,
1034    },
1035    IfStmt {
1036        conds: Vec<(Expr, StmtBody)>,
1037        alt: Option<StmtBody>,
1038    },
1039    CaseStmt {
1040        qm: bool,
1041        switch: Expr,
1042        cases: Vec<(Choices, StmtBody)>,
1043    },
1044    LoopStmt {
1045        scheme: LoopScheme,
1046        body: StmtBody,
1047    },
1048    NexitStmt {
1049        mode: NexitMode,
1050        target: Option<Spanned<Name>>,
1051        cond: Option<Expr>,
1052    },
1053    ReturnStmt(Option<Expr>),
1054    NullStmt,
1055    IfGenStmt {
1056        conds: Vec<(Expr, GenBody)>,
1057        alt: Option<GenBody>,
1058    },
1059    CaseGenStmt {
1060        switch: Expr,
1061        cases: Vec<(Choices, GenBody)>,
1062    },
1063    ForGenStmt {
1064        param: Spanned<Name>,
1065        range: Expr,
1066        body: GenBody,
1067    },
1068    BlockStmt {
1069        guard: Option<Expr>,
1070        decls: Vec<DeclItem>,
1071        stmts: Vec<Stmt>,
1072    },
1073    ProcStmt {
1074        sensitivity: Option<Sensitivity>,
1075        decls: Vec<DeclItem>,
1076        stmts: Vec<Stmt>,
1077        postponed: bool,
1078    },
1079    AssignStmt {
1080        target: Spanned<AssignTarget>,
1081        kind: AssignKind,
1082        guarded: bool,
1083        mode: Spanned<AssignMode>,
1084    },
1085    SelectAssignStmt {
1086        select: Expr,
1087        qm: bool,
1088        target: Spanned<AssignTarget>,
1089        kind: AssignKind,
1090        guarded: bool,
1091        mode: SelectAssignMode,
1092        waves: Vec<SelectWave>,
1093    },
1094    InstOrCallStmt {
1095        target: Option<InstTarget>,
1096        name: CompoundName,
1097        generics: Option<ParenElems>,
1098        ports: Option<ParenElems>,
1099    },
1100}
1101
1102impl HasDesc for StmtData {
1103    fn desc(&self) -> &'static str {
1104        match *self {
1105            StmtData::WaitStmt { .. } => "wait statement",
1106            StmtData::AssertStmt { .. } => "assertion statement",
1107            StmtData::ReportStmt { .. } => "report statement",
1108            StmtData::IfStmt { .. } => "if statement",
1109            StmtData::CaseStmt { .. } => "case statement",
1110            StmtData::LoopStmt { .. } => "loop statement",
1111            StmtData::NexitStmt {
1112                mode: NexitMode::Next,
1113                ..
1114            } => "next statement",
1115            StmtData::NexitStmt {
1116                mode: NexitMode::Exit,
1117                ..
1118            } => "exit statement",
1119            StmtData::ReturnStmt(..) => "return statement",
1120            StmtData::NullStmt => "null statement",
1121            StmtData::IfGenStmt { .. } => "if-generate statement",
1122            StmtData::CaseGenStmt { .. } => "case-generate statement",
1123            StmtData::ForGenStmt { .. } => "for-generate statement",
1124            StmtData::BlockStmt { .. } => "block statement",
1125            StmtData::ProcStmt { .. } => "process statement",
1126            StmtData::AssignStmt { .. } => "assign statement",
1127            StmtData::SelectAssignStmt { .. } => "assign statement",
1128            StmtData::InstOrCallStmt { .. } => "instantiation or call statement",
1129        }
1130    }
1131}
1132
1133/// The body of an if, loop, or case statement.
1134#[derive(Clone, Debug, PartialEq, Eq)]
1135pub struct StmtBody {
1136    pub id: NodeId,
1137    pub stmts: Vec<Stmt>,
1138}
1139
1140#[derive(Clone, Debug, PartialEq, Eq)]
1141pub enum LoopScheme {
1142    While(Expr),
1143    For(Spanned<Name>, Expr),
1144    Loop,
1145}
1146
1147#[derive(Copy, Clone, Debug, PartialEq, Eq)]
1148pub enum NexitMode {
1149    Next,
1150    Exit,
1151}
1152
1153#[derive(Clone, Debug, PartialEq, Eq)]
1154pub struct GenBody {
1155    pub id: NodeId,
1156    pub label: Option<Spanned<Name>>,
1157    pub span: Span,
1158    pub decls: Vec<DeclItem>,
1159    pub stmts: Vec<Stmt>,
1160}
1161
1162#[derive(Clone, Debug, PartialEq, Eq)]
1163pub enum Sensitivity {
1164    All,
1165    List(Vec<CompoundName>),
1166}
1167
1168#[derive(Clone, Debug, PartialEq, Eq)]
1169pub enum AssignTarget {
1170    Name(CompoundName),
1171    Aggregate(ParenElems),
1172}
1173
1174#[derive(Copy, Clone, Debug, PartialEq, Eq)]
1175pub enum InstTarget {
1176    Comp,
1177    Entity,
1178    Cfg,
1179}
1180
1181#[derive(Copy, Clone, Debug, PartialEq, Eq)]
1182pub enum AssignKind {
1183    Signal,
1184    Var,
1185}
1186
1187#[derive(Clone, Debug, PartialEq, Eq)]
1188pub enum AssignMode {
1189    Release(Option<Spanned<ForceMode>>),
1190    Force(Option<Spanned<ForceMode>>, Vec<CondWave>),
1191    Normal(Option<Spanned<DelayMech>>, Vec<CondWave>),
1192}
1193
1194#[derive(Clone, Debug, PartialEq, Eq)]
1195pub enum SelectAssignMode {
1196    Force(Option<Spanned<ForceMode>>),
1197    Normal(Option<Spanned<DelayMech>>),
1198}
1199
1200#[derive(Copy, Clone, Debug, PartialEq, Eq)]
1201pub enum ForceMode {
1202    In,
1203    Out,
1204}
1205
1206#[derive(Clone, Debug, PartialEq, Eq)]
1207pub enum DelayMech {
1208    Transport,
1209    Inertial,
1210    InertialReject(Expr),
1211}
1212
1213#[derive(Clone, Debug, PartialEq, Eq)]
1214pub struct Wave {
1215    pub span: Span,
1216    pub elems: Option<Vec<(Expr, Option<Expr>)>>,
1217}
1218
1219/// A conditional wave.
1220#[derive(Clone, Debug, PartialEq, Eq)]
1221pub struct CondWave(pub Wave, pub Option<Expr>);
1222
1223/// A selected wave. The second element of the tuple represents the choices for
1224/// which this wave would be selected.
1225#[derive(Clone, Debug, PartialEq, Eq)]
1226pub struct SelectWave(pub Wave, pub Choices);
1227
1228#[derive(Clone, Debug, PartialEq, Eq)]
1229pub struct Signature {
1230    pub span: Span,
1231    pub args: Vec<CompoundName>,
1232    pub retty: Option<CompoundName>,
1233}
1234
1235pub type Choices = Spanned<Vec<Expr>>;