use std::fmt::{self, Display};
use std::str::FromStr;
use crate::IdCode;
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
#[non_exhaustive]
#[allow(missing_docs)]
pub enum ScopeType {
Module,
Task,
Function,
Begin,
Fork,
}
crate::unit_error_struct!(InvalidScopeType, "invalid scope type");
impl FromStr for ScopeType {
type Err = InvalidScopeType;
fn from_str(s: &str) -> Result<Self, Self::Err> {
use ScopeType::*;
match s {
"module" => Ok(Module),
"task" => Ok(Task),
"function" => Ok(Function),
"begin" => Ok(Begin),
"fork" => Ok(Fork),
_ => Err(InvalidScopeType),
}
}
}
impl Display for ScopeType {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
use ScopeType::*;
write!(
f,
"{}",
match *self {
Module => "module",
Task => "task",
Function => "function",
Begin => "begin",
Fork => "fork",
}
)
}
}
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
#[non_exhaustive]
#[allow(missing_docs)]
pub enum VarType {
Event,
Integer,
Parameter,
Real,
Reg,
Supply0,
Supply1,
Time,
Tri,
TriAnd,
TriOr,
TriReg,
Tri0,
Tri1,
WAnd,
Wire,
WOr,
String,
}
crate::unit_error_struct!(InvalidVarType, "invalid variable type");
impl FromStr for VarType {
type Err = InvalidVarType;
fn from_str(s: &str) -> Result<Self, Self::Err> {
use VarType::*;
match s {
"event" => Ok(Event),
"integer" => Ok(Integer),
"parameter" => Ok(Parameter),
"real" => Ok(Real),
"reg" => Ok(Reg),
"supply0" => Ok(Supply0),
"supply1" => Ok(Supply1),
"time" => Ok(Time),
"tri" => Ok(Tri),
"triand" => Ok(TriAnd),
"trior" => Ok(TriOr),
"trireg" => Ok(TriReg),
"tri0" => Ok(Tri0),
"tri1" => Ok(Tri1),
"wand" => Ok(WAnd),
"wire" => Ok(Wire),
"wor" => Ok(WOr),
"string" => Ok(String),
_ => Err(InvalidVarType),
}
}
}
impl Display for VarType {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
use VarType::*;
write!(
f,
"{}",
match *self {
Event => "event",
Integer => "integer",
Parameter => "parameter",
Real => "real",
Reg => "reg",
Supply0 => "supply0",
Supply1 => "supply1",
Time => "time",
Tri => "tri",
TriAnd => "triand",
TriOr => "trior",
TriReg => "trireg",
Tri0 => "tri0",
Tri1 => "tri1",
WAnd => "wand",
Wire => "wire",
WOr => "wor",
String => "string",
}
)
}
}
#[derive(Debug, Clone, PartialEq)]
#[non_exhaustive]
pub struct Scope {
pub scope_type: ScopeType,
pub identifier: String,
pub items: Vec<ScopeItem>,
}
impl Scope {
pub fn new(scope_type: ScopeType, identifier: String) -> Self {
Self { scope_type, identifier, items: Vec::new() }
}
pub fn find_var<'a>(&'a self, reference: &str) -> Option<&'a Var> {
for c in &self.items {
if let ScopeItem::Var(v) = c {
if v.reference == reference {
return Some(v);
}
}
}
None
}
}
impl Default for Scope {
fn default() -> Scope {
Scope {
scope_type: ScopeType::Module,
identifier: "".to_string(),
items: Vec::new(),
}
}
}
#[derive(Debug, Copy, Clone, PartialEq)]
pub enum ReferenceIndex {
BitSelect(i32),
Range(i32, i32),
}
crate::unit_error_struct!(InvalidReferenceIndex, "invalid reference index");
impl FromStr for ReferenceIndex {
type Err = InvalidReferenceIndex;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let s = s.strip_prefix('[').ok_or(InvalidReferenceIndex)?;
let s = s.strip_suffix(']').ok_or(InvalidReferenceIndex)?;
match s.split_once(':') {
Some((msb_str, lsb_str)) => {
let msb: i32 = msb_str
.trim()
.parse()
.map_err(|_| InvalidReferenceIndex)?;
let lsb: i32 = lsb_str
.trim()
.parse()
.map_err(|_| InvalidReferenceIndex)?;
Ok(ReferenceIndex::Range(msb, lsb))
}
None => {
let idx = s
.trim()
.parse()
.map_err(|_| InvalidReferenceIndex{})?;
Ok(ReferenceIndex::BitSelect(idx))
}
}
}
}
impl Display for ReferenceIndex {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
use ReferenceIndex::*;
match self {
BitSelect(idx) => write!(f, "[{}]", idx),
Range(msb, lsb) => write!(f, "[{}:{}]", msb, lsb),
}
}
}
#[test]
fn test_parse_reference_index() {
assert_eq!("[0]".parse(), Ok(ReferenceIndex::BitSelect(0)));
assert_eq!("[ 1 ]".parse(), Ok(ReferenceIndex::BitSelect(1)));
assert_eq!("[7:0]".parse(), Ok(ReferenceIndex::Range(7, 0)));
assert_eq!("[12:-4]".parse(), Ok(ReferenceIndex::Range(12, -4)));
assert_eq!("[ 0 : 8 ]".parse(), Ok(ReferenceIndex::Range(0, 8)));
}
#[derive(Debug, Clone, PartialEq)]
#[non_exhaustive]
pub struct Var {
pub var_type: VarType,
pub size: u32,
pub code: IdCode,
pub reference: String,
pub index: Option<ReferenceIndex>,
}
impl Var {
pub fn new(
var_type: VarType,
size: u32,
code: IdCode,
reference: String,
index: Option<ReferenceIndex>,
) -> Self {
Self { var_type, size, code, reference, index }
}
}
#[derive(Debug, Clone, PartialEq)]
#[non_exhaustive]
pub enum ScopeItem {
Scope(Scope),
Var(Var),
Comment(String),
}