// Copyright (c) 2016-2021 Fabian Schuiki //! This module implements an abstract syntax tree for VHDL. It is emitted by //! the parser. use std; use std::fmt; use crate::lexer::token::Literal; use moore_common::name::Name; use moore_common::source::{Span, Spanned}; use moore_common::util::{HasDesc, HasSpan}; pub use self::ExprData::*; pub use self::StmtData::*; pub use self::TypeData::*; /// A positive, small ID assigned to each node in the AST. Used as a lightweight /// way to refer to individual nodes, e.g. during symbol table construction and /// name resolution. #[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Hash, Debug)] pub struct NodeId(u32); impl NodeId { pub fn new(x: usize) -> NodeId { use std::u32; assert!(x < (u32::MAX as usize)); NodeId(x as u32) } pub fn from_u32(x: u32) -> NodeId { NodeId(x) } pub fn as_usize(&self) -> usize { self.0 as usize } pub fn as_u32(&self) -> u32 { self.0 } } impl std::fmt::Display for NodeId { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { write!(f, "{}", self.0) } } impl Default for NodeId { fn default() -> NodeId { DUMMY_NODE_ID } } /// During parsing and syntax tree construction, we assign each node this ID. /// Only later, during the renumbering pass do we assign actual IDs to each /// node. pub const DUMMY_NODE_ID: NodeId = NodeId(0); /// A design unit. Multiple design units make up a design file. Each unit /// consists of an optional context clause followed by a primary or secondary /// unit. #[derive(Clone, Debug, PartialEq, Eq)] pub struct DesignUnit { pub id: NodeId, pub ctx: Vec, pub data: DesignUnitData, } #[derive(Clone, Debug, PartialEq, Eq)] pub enum DesignUnitData { EntityDecl(EntityDecl), CfgDecl(CfgDecl), PkgDecl(PkgDecl), PkgInst(PkgInst), CtxDecl(CtxDecl), ArchBody(ArchBody), PkgBody(PkgBody), } /// A context item, multiple of which make up a context clause. #[derive(Clone, Debug, PartialEq, Eq)] pub enum CtxItem { LibClause(Spanned>), UseClause(Spanned>), CtxRef(Spanned>), } /// An identifier. Has a node ID such that it may be referenced later on. #[derive(Copy, Clone, Debug, PartialEq, Eq)] // #[deprecated(note="use `Spanned` instead of `Ident`")] pub struct Ident { pub id: NodeId, pub span: Span, pub name: Name, } impl From> for Ident { fn from(n: Spanned) -> Ident { Ident { id: Default::default(), span: n.span, name: n.value, } } } impl Into> for Ident { fn into(self) -> Spanned { Spanned::new(self.name, self.span) } } /// A compound name consisting of a primary name (identifier, character literal, /// or string literal), and zero or more suffices (select, attribute, call). The /// names in *IEEE 1076-2008 section 8.1* map to this as follows: /// /// | In the standard | In this module | /// |---------------------|---------------------------------| /// | simple_name | `PrimaryNameKind::Ident` | /// | operator_symbol | `PrimaryNameKind::String` | /// | character_literal | `PrimaryNameKind::Char` | /// | selected_name | `NamePart::{Select, SelectAll}` | /// | indexed_name | `NamePart::Call` | /// | slice_name | `NamePart::Call` | /// | function_call | `NamePart::Call` | /// | attribute_name | `NamePart::Attribute` | /// | external_name | not implemented | /// #[derive(Clone, Debug, PartialEq, Eq)] pub struct CompoundName { pub id: NodeId, pub span: Span, pub primary: PrimaryName, pub parts: Vec, } impl HasSpan for CompoundName { fn span(&self) -> Span { self.span } } impl HasDesc for CompoundName { fn desc(&self) -> &'static str { "name" } } #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub struct PrimaryName { pub id: NodeId, pub span: Span, pub kind: PrimaryNameKind, } #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum PrimaryNameKind { Ident(Name), Char(char), String(Name), } #[derive(Clone, Debug, PartialEq, Eq)] pub enum NamePart { Select(PrimaryName), SelectAll(Span), Signature(Signature), Attribute(Ident), Call(ParenElems), Range(Box), } /// A context declaration. #[derive(Clone, Debug, PartialEq, Eq)] pub struct CtxDecl { pub id: NodeId, pub span: Span, pub name: Spanned, pub items: Vec, } /// An entity declaration. #[derive(Clone, Debug, PartialEq, Eq)] pub struct EntityDecl { pub id: NodeId, pub span: Span, pub name: Spanned, pub decls: Vec, pub stmts: Option>, } /// A configuration declaration. #[derive(Clone, Debug, PartialEq, Eq)] pub struct CfgDecl { pub id: NodeId, pub span: Span, pub name: Spanned, pub target: CompoundName, pub decls: Vec, } /// An architecture body. #[derive(Clone, Debug, PartialEq, Eq)] pub struct ArchBody { pub id: NodeId, pub span: Span, pub name: Spanned, pub target: CompoundName, pub decls: Vec, pub stmts: Vec, } /// A package declaration. #[derive(Clone, Debug, PartialEq, Eq)] pub struct PkgDecl { pub id: NodeId, pub span: Span, pub name: Spanned, pub decls: Vec, } /// A package body. #[derive(Clone, Debug, PartialEq, Eq)] pub struct PkgBody { pub id: NodeId, pub span: Span, pub name: Spanned, pub decls: Vec, } /// A package instantiation declaration. #[derive(Clone, Debug, PartialEq, Eq)] pub struct PkgInst { pub id: NodeId, pub span: Span, pub name: Spanned, pub target: CompoundName, pub generics: Option, } /// An interface declaration. #[derive(Clone, Debug, PartialEq, Eq)] pub enum IntfDecl { TypeDecl(TypeDecl), SubprogSpec(IntfSubprogDecl), PkgInst(PkgInst), ObjDecl(IntfObjDecl), } impl HasSpan for IntfDecl { fn span(&self) -> Span { match *self { IntfDecl::TypeDecl(ref n) => n.span, IntfDecl::SubprogSpec(ref n) => n.span, IntfDecl::PkgInst(ref n) => n.span, IntfDecl::ObjDecl(ref n) => n.span, } } fn human_span(&self) -> Span { match *self { IntfDecl::TypeDecl(ref n) => n.name.span, IntfDecl::PkgInst(ref n) => n.name.span, _ => self.span(), } } } impl HasDesc for IntfDecl { fn desc(&self) -> &'static str { match *self { IntfDecl::TypeDecl(_) => "interface type declaration", IntfDecl::SubprogSpec(_) => "interface subprogram declaration", IntfDecl::PkgInst(_) => "interface package declaration", IntfDecl::ObjDecl(ref n) => n.desc(), } } } #[derive(Clone, Debug, PartialEq, Eq)] pub struct IntfSubprogDecl { pub id: NodeId, pub span: Span, pub spec: SubprogSpec, pub default: Option, } #[derive(Clone, Debug, PartialEq, Eq)] pub enum SubprogDefault { Any, Name(CompoundName), } /// An interface object declaration. #[derive(Clone, Debug, PartialEq, Eq)] pub struct IntfObjDecl { pub kind: IntfObjKind, pub span: Span, pub names: Vec, pub mode: Option, pub ty: SubtypeInd, pub bus: bool, pub default: Option, } impl HasDesc for IntfObjDecl { fn desc(&self) -> &'static str { match self.kind { IntfObjKind::Const => "interface constant declaration", IntfObjKind::Signal => "interface signal declaration", IntfObjKind::Var => "interface variable declaration", IntfObjKind::File => "interface file declaration", } } } #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum IntfObjKind { Const, Signal, Var, File, } #[derive(Clone, Copy, Debug, PartialEq, Eq)] pub enum IntfMode { In, Out, Inout, Buffer, Linkage, } /// A declarative item. #[derive(Clone, Debug, PartialEq, Eq)] pub enum DeclItem { PkgBody(PkgBody), PkgInst(PkgInst), PkgDecl(PkgDecl), TypeDecl(TypeDecl), SubtypeDecl(SubtypeDecl), ObjDecl(ObjDecl), AliasDecl(AliasDecl), UseClause(Span, Spanned>), SubprogDecl(Subprog), CompDecl(CompDecl), DisconDecl(DisconSpec), CfgSpec(CfgSpec), AttrDecl(AttrDecl), PortgenMap(Span, Spanned, ParenElems), PortgenClause(Span, Spanned, Spanned>), GroupDecl(GroupDecl), VunitBindInd(()), BlockCompCfg(BlockCompCfg), } impl HasSpan for DeclItem { fn span(&self) -> Span { match *self { DeclItem::PkgBody(ref n) => n.span, DeclItem::PkgInst(ref n) => n.span, DeclItem::PkgDecl(ref n) => n.span, DeclItem::TypeDecl(ref n) => n.span, DeclItem::SubtypeDecl(ref n) => n.span, DeclItem::ObjDecl(ref n) => n.span, DeclItem::AliasDecl(ref n) => n.span, DeclItem::UseClause(sp, ref n) => Span::union(sp, n.span), DeclItem::SubprogDecl(ref n) => n.span(), DeclItem::CompDecl(ref n) => n.span, DeclItem::DisconDecl(ref n) => n.span, DeclItem::CfgSpec(ref n) => n.span, DeclItem::AttrDecl(ref n) => n.span, DeclItem::PortgenMap(sp, _, _) => sp, DeclItem::PortgenClause(sp, _, _) => sp, DeclItem::GroupDecl(ref n) => n.span, DeclItem::VunitBindInd(_) => unimplemented!(), DeclItem::BlockCompCfg(ref n) => n.span, } } fn human_span(&self) -> Span { match *self { DeclItem::PkgBody(ref n) => n.name.span, DeclItem::PkgInst(ref n) => n.name.span, DeclItem::PkgDecl(ref n) => n.name.span, DeclItem::TypeDecl(ref n) => n.name.span, DeclItem::SubtypeDecl(ref n) => n.name.span, DeclItem::AliasDecl(ref n) => n.name.span, DeclItem::UseClause(sp, _) => sp, DeclItem::SubprogDecl(ref n) => n.human_span(), DeclItem::PortgenMap(_, Spanned { span, .. }, _) => span, DeclItem::PortgenClause(_, Spanned { span, .. }, _) => span, _ => self.span(), } } } impl HasDesc for DeclItem { fn desc(&self) -> &'static str { match *self { DeclItem::PkgBody(..) => "package body", DeclItem::PkgInst(..) => "package instance", DeclItem::PkgDecl(..) => "package declaration", DeclItem::TypeDecl(..) => "type declaration", DeclItem::SubtypeDecl(..) => "subtype declaration", DeclItem::ObjDecl(..) => "object declaration", DeclItem::AliasDecl(..) => "alias declaration", DeclItem::UseClause(..) => "use clause", DeclItem::SubprogDecl(ref n) => n.desc(), DeclItem::CompDecl(..) => "component declaration", DeclItem::DisconDecl(..) => "disconnection declaration", DeclItem::CfgSpec(..) => "configuration specification", DeclItem::AttrDecl(..) => "attribute declaration", DeclItem::PortgenMap( _, Spanned { value: PortgenKind::Port, .. }, .., ) => "port map", DeclItem::PortgenMap( _, Spanned { value: PortgenKind::Generic, .. }, .., ) => "generic map", DeclItem::PortgenClause( _, Spanned { value: PortgenKind::Port, .. }, .., ) => "port clause", DeclItem::PortgenClause( _, Spanned { value: PortgenKind::Generic, .. }, .., ) => "generic clause", DeclItem::GroupDecl(..) => "group declaration", DeclItem::VunitBindInd(..) => "vunit binding indication", DeclItem::BlockCompCfg(..) => "block component configuration", } } } #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum PortgenKind { Port, Generic, } #[derive(Clone, Debug, PartialEq, Eq)] pub struct Subprog { pub id: NodeId, pub span: Span, pub spec: SubprogSpec, pub data: SubprogData, } impl HasSpan for Subprog { fn span(&self) -> Span { self.span } fn human_span(&self) -> Span { self.spec.name.span } } impl HasDesc for Subprog { fn desc(&self) -> &'static str { self.data.desc() } } #[derive(Clone, Debug, PartialEq, Eq)] pub enum SubprogData { Decl, Inst { name: CompoundName, generics: Option, }, Body { decls: Vec, stmts: Vec, }, } impl HasDesc for SubprogData { fn desc(&self) -> &'static str { match *self { SubprogData::Decl => "subprogram declaration", SubprogData::Inst { .. } => "subprogram instantiation", SubprogData::Body { .. } => "subprogram body", } } } #[derive(Clone, Debug, PartialEq, Eq)] pub struct SubprogSpec { pub span: Span, pub name: PrimaryName, pub kind: SubprogKind, pub purity: Option, pub generic_clause: Option>, pub generic_map: Option, pub params: Option>, pub retty: Option, } #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum SubprogPurity { Pure, Impure, } #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum SubprogKind { Proc, Func, } #[derive(Clone, Debug, PartialEq, Eq)] pub struct SubtypeInd { pub span: Span, pub res: Option, pub name: CompoundName, } impl HasSpan for SubtypeInd { fn span(&self) -> Span { self.span } } impl HasDesc for SubtypeInd { fn desc(&self) -> &'static str { "subtype indication" } } #[derive(Clone, Debug, PartialEq, Eq)] pub struct SubtypeDecl { pub id: NodeId, pub span: Span, pub name: Spanned, pub subtype: SubtypeInd, } #[derive(Clone, Debug, PartialEq, Eq)] pub enum ResolInd { Exprs(ParenElems), Name(CompoundName), } /// An alias declaration. #[derive(Clone, Debug, PartialEq, Eq)] pub struct AliasDecl { pub id: NodeId, pub span: Span, pub name: PrimaryName, pub subtype: Option, pub target: CompoundName, } #[derive(Clone, Debug, PartialEq, Eq)] pub struct ObjDecl { pub span: Span, pub kind: ObjKind, pub names: Vec, pub subtype: SubtypeInd, pub detail: Option>, pub init: Option, } #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum ObjKind { Const, Signal, File, Var, SharedVar, } /// Additional mutually exclusive details that may be provided with an object /// declaration. #[derive(Clone, Debug, PartialEq, Eq)] pub enum ObjDetail { Register, Bus, /// A file opening action. Open(Option, Expr), } impl HasSpan for ObjDecl { fn span(&self) -> Span { self.span } fn human_span(&self) -> Span { self.names .iter() .map(|n| n.span) .fold(self.names[0].span, Span::union) } } impl HasDesc for ObjDecl { fn desc(&self) -> &'static str { match self.kind { ObjKind::Const => "constant declaration", ObjKind::Signal => "signal declaration", ObjKind::File => "file declaration", ObjKind::Var => "variable declaration", ObjKind::SharedVar => "shared variable declaration", } } } /// A component declaration. #[derive(Clone, Debug, PartialEq, Eq)] pub struct CompDecl { pub id: NodeId, pub span: Span, pub name: Spanned, pub generics: Option>>, pub ports: Option>>, } #[derive(Clone, Debug, PartialEq, Eq)] pub struct DisconSpec { pub span: Span, pub target: DisconTarget, pub ty: CompoundName, pub after: Expr, } #[derive(Clone, Debug, PartialEq, Eq)] pub enum DisconTarget { Others, All, Signals(Vec), } #[derive(Clone, Debug, PartialEq, Eq)] pub struct BlockCompCfg { pub span: Span, pub spec: Spanned, pub bind: BindingInd, pub decls: Vec, } #[derive(Clone, Debug, PartialEq, Eq)] pub enum BlockCompSpec { CompOthers(CompoundName), CompAll(CompoundName), CompNames(Vec, CompoundName), Block(CompoundName), } #[derive(Clone, Debug, PartialEq, Eq)] pub struct BindingInd { pub span: Span, pub entity: Option, pub generics: Option, pub ports: Option, } #[derive(Clone, Debug, PartialEq, Eq)] pub enum EntityAspect { Entity(CompoundName), Cfg(CompoundName), Open, } #[derive(Clone, Debug, PartialEq, Eq)] pub struct CfgSpec { pub span: Span, pub spec: Spanned, pub bind: BindingInd, pub vunits: Vec<()>, } #[derive(Clone, Debug, PartialEq, Eq)] pub struct AttrDecl { pub id: NodeId, pub span: Span, pub name: Spanned, pub data: AttrData, } #[derive(Clone, Debug, PartialEq, Eq)] pub enum AttrData { Decl(CompoundName), Spec { target: AttrTarget, cls: EntityClass, expr: Expr, }, } #[derive(Clone, Debug, PartialEq, Eq)] pub enum AttrTarget { Others, All, List(Vec<(CompoundName, Option)>), } #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum EntityClass { Arch, Comp, Cfg, Const, Entity, File, Func, Group, Label, Literal, Pkg, Proc, Prop, Seq, Signal, Subtype, Type, Units, Var, } #[derive(Clone, Debug, PartialEq, Eq)] pub struct GroupDecl { pub id: NodeId, pub span: Span, pub name: Spanned, pub data: GroupData, } #[derive(Clone, Debug, PartialEq, Eq)] pub enum GroupData { /// A group declaration. Decl(CompoundName), /// A group template. Each element consists of an entity class, and a bool /// that indicates whether a `<>` was present in the source text. Temp(Vec<(EntityClass, bool)>), } /// A parenthesized expression element. A parenthesized expression contains /// elements of which each may either be a simple ``, or an association of /// the form ` => `. #[derive(Clone, Debug, PartialEq, Eq)] pub struct ParenElem { pub span: Span, pub choices: Choices, pub expr: Expr, } /// A vector of parenthesized expression elements, including the span of the /// expression that this would cover. pub type ParenElems = Spanned>; /// An expression. #[derive(Clone, Debug, PartialEq, Eq)] pub struct Expr { pub span: Span, pub data: ExprData, } impl HasSpan for Expr { fn span(&self) -> Span { self.span } } impl HasDesc for Expr { fn desc(&self) -> &'static str { self.data.desc() } } /// The data associated with a specific expression. #[derive(Clone, Debug, PartialEq, Eq)] pub enum ExprData { NullExpr, OpenExpr, OthersExpr, DefaultExpr, BoxExpr, NewExpr(Box), LitExpr(Literal, Option>), ResolExpr(ParenElems, CompoundName), ParenExpr(ParenElems), DoubleNameExpr(CompoundName, CompoundName), QualExpr(CompoundName, ParenElems), NameExpr(CompoundName), UnaryExpr(Spanned, Box), BinaryExpr(Spanned, Box, Box), } impl HasDesc for ExprData { fn desc(&self) -> &'static str { match *self { NullExpr => "null expression", UnaryExpr(..) => "unary expression", BinaryExpr(..) => "binary expression", _ => "expression", } } } #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum UnaryOp { Not, Abs, Sign(Sign), Logical(LogicalOp), Inertial, Condition, } #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum BinaryOp { Dir(Dir), Logical(LogicalOp), Rel(RelationalOp), Match(RelationalOp), Shift(ShiftOp), Add, Sub, Concat, Mul, Div, Mod, Rem, Pow, } #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum Dir { To, Downto, } impl std::fmt::Display for Dir { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { match *self { Dir::To => write!(f, "to"), Dir::Downto => write!(f, "downto"), } } } #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum Sign { Pos, Neg, } #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] pub enum LogicalOp { And, Or, Nand, Nor, Xor, Xnor, } impl fmt::Display for LogicalOp { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { LogicalOp::And => write!(f, "and"), LogicalOp::Or => write!(f, "or"), LogicalOp::Nand => write!(f, "nand"), LogicalOp::Nor => write!(f, "nor"), LogicalOp::Xor => write!(f, "xor"), LogicalOp::Xnor => write!(f, "xnor"), } } } #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] pub enum RelationalOp { Eq, Neq, Lt, Leq, Gt, Geq, } impl fmt::Display for RelationalOp { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { RelationalOp::Eq => write!(f, "="), RelationalOp::Neq => write!(f, "/="), RelationalOp::Lt => write!(f, "<"), RelationalOp::Leq => write!(f, "<="), RelationalOp::Gt => write!(f, ">"), RelationalOp::Geq => write!(f, ">="), } } } #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] pub enum ShiftOp { Sll, Srl, Sla, Sra, Rol, Ror, } impl fmt::Display for ShiftOp { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { ShiftOp::Sll => write!(f, "sll"), ShiftOp::Srl => write!(f, "srl"), ShiftOp::Sla => write!(f, "sla"), ShiftOp::Sra => write!(f, "sra"), ShiftOp::Rol => write!(f, "rol"), ShiftOp::Ror => write!(f, "ror"), } } } /// A type declaration. If the `data` field is omitted, this is an incomplete /// declaration. #[derive(Clone, Debug, PartialEq, Eq)] pub struct TypeDecl { pub id: NodeId, pub span: Span, pub name: Spanned, pub data: Option>, } impl HasSpan for TypeDecl { fn span(&self) -> Span { self.span } fn human_span(&self) -> Span { self.name.span } } impl HasDesc for TypeDecl { fn desc(&self) -> &'static str { match self.data { Some(ref d) => d.desc(), None => "incomplete type declaration", } } } #[derive(Clone, Debug, PartialEq, Eq)] pub enum TypeData { EnumType(ParenElems), RangeType(Box, Option>)>>), ArrayType(ParenElems, SubtypeInd), RecordType(Vec<(Vec, SubtypeInd)>), AccessType(SubtypeInd), FileType(CompoundName), ProtectedType(Vec), } impl HasDesc for TypeData { fn desc(&self) -> &'static str { match *self { TypeData::EnumType(..) => "enumeration type declaration", TypeData::RangeType(..) => "range type declaration", TypeData::ArrayType(..) => "array type declaration", TypeData::RecordType(..) => "record type declaration", TypeData::AccessType(..) => "access type declaration", TypeData::FileType(..) => "file type declaration", TypeData::ProtectedType(..) => "protected type declaration", } } } #[derive(Clone, Debug, PartialEq, Eq)] pub struct Stmt { pub id: NodeId, pub span: Span, pub label: Option>, pub data: StmtData, } impl HasSpan for Stmt { fn span(&self) -> Span { self.span } fn human_span(&self) -> Span { match self.label { Some(Spanned { span, .. }) => span, _ => self.span(), } } } impl HasDesc for Stmt { fn desc(&self) -> &'static str { self.data.desc() } } #[derive(Clone, Debug, PartialEq, Eq)] pub enum StmtData { WaitStmt { on: Option>>, until: Option, time: Option, }, AssertStmt { cond: Expr, report: Option, severity: Option, }, ReportStmt { msg: Expr, severity: Option, }, IfStmt { conds: Vec<(Expr, StmtBody)>, alt: Option, }, CaseStmt { qm: bool, switch: Expr, cases: Vec<(Choices, StmtBody)>, }, LoopStmt { scheme: LoopScheme, body: StmtBody, }, NexitStmt { mode: NexitMode, target: Option>, cond: Option, }, ReturnStmt(Option), NullStmt, IfGenStmt { conds: Vec<(Expr, GenBody)>, alt: Option, }, CaseGenStmt { switch: Expr, cases: Vec<(Choices, GenBody)>, }, ForGenStmt { param: Spanned, range: Expr, body: GenBody, }, BlockStmt { guard: Option, decls: Vec, stmts: Vec, }, ProcStmt { sensitivity: Option, decls: Vec, stmts: Vec, postponed: bool, }, AssignStmt { target: Spanned, kind: AssignKind, guarded: bool, mode: Spanned, }, SelectAssignStmt { select: Expr, qm: bool, target: Spanned, kind: AssignKind, guarded: bool, mode: SelectAssignMode, waves: Vec, }, InstOrCallStmt { target: Option, name: CompoundName, generics: Option, ports: Option, }, } impl HasDesc for StmtData { fn desc(&self) -> &'static str { match *self { StmtData::WaitStmt { .. } => "wait statement", StmtData::AssertStmt { .. } => "assertion statement", StmtData::ReportStmt { .. } => "report statement", StmtData::IfStmt { .. } => "if statement", StmtData::CaseStmt { .. } => "case statement", StmtData::LoopStmt { .. } => "loop statement", StmtData::NexitStmt { mode: NexitMode::Next, .. } => "next statement", StmtData::NexitStmt { mode: NexitMode::Exit, .. } => "exit statement", StmtData::ReturnStmt(..) => "return statement", StmtData::NullStmt => "null statement", StmtData::IfGenStmt { .. } => "if-generate statement", StmtData::CaseGenStmt { .. } => "case-generate statement", StmtData::ForGenStmt { .. } => "for-generate statement", StmtData::BlockStmt { .. } => "block statement", StmtData::ProcStmt { .. } => "process statement", StmtData::AssignStmt { .. } => "assign statement", StmtData::SelectAssignStmt { .. } => "assign statement", StmtData::InstOrCallStmt { .. } => "instantiation or call statement", } } } /// The body of an if, loop, or case statement. #[derive(Clone, Debug, PartialEq, Eq)] pub struct StmtBody { pub id: NodeId, pub stmts: Vec, } #[derive(Clone, Debug, PartialEq, Eq)] pub enum LoopScheme { While(Expr), For(Spanned, Expr), Loop, } #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum NexitMode { Next, Exit, } #[derive(Clone, Debug, PartialEq, Eq)] pub struct GenBody { pub id: NodeId, pub label: Option>, pub span: Span, pub decls: Vec, pub stmts: Vec, } #[derive(Clone, Debug, PartialEq, Eq)] pub enum Sensitivity { All, List(Vec), } #[derive(Clone, Debug, PartialEq, Eq)] pub enum AssignTarget { Name(CompoundName), Aggregate(ParenElems), } #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum InstTarget { Comp, Entity, Cfg, } #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum AssignKind { Signal, Var, } #[derive(Clone, Debug, PartialEq, Eq)] pub enum AssignMode { Release(Option>), Force(Option>, Vec), Normal(Option>, Vec), } #[derive(Clone, Debug, PartialEq, Eq)] pub enum SelectAssignMode { Force(Option>), Normal(Option>), } #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum ForceMode { In, Out, } #[derive(Clone, Debug, PartialEq, Eq)] pub enum DelayMech { Transport, Inertial, InertialReject(Expr), } #[derive(Clone, Debug, PartialEq, Eq)] pub struct Wave { pub span: Span, pub elems: Option)>>, } /// A conditional wave. #[derive(Clone, Debug, PartialEq, Eq)] pub struct CondWave(pub Wave, pub Option); /// A selected wave. The second element of the tuple represents the choices for /// which this wave would be selected. #[derive(Clone, Debug, PartialEq, Eq)] pub struct SelectWave(pub Wave, pub Choices); #[derive(Clone, Debug, PartialEq, Eq)] pub struct Signature { pub span: Span, pub args: Vec, pub retty: Option, } pub type Choices = Spanned>;