Skip to content

Commit

Permalink
Merge pull request #1043 from veryl-lang/cond_type
Browse files Browse the repository at this point in the history
`cond_type` attribute
  • Loading branch information
dalance authored Nov 13, 2024
2 parents 8899ac0 + d9bf679 commit 220873d
Show file tree
Hide file tree
Showing 18 changed files with 9,977 additions and 8,657 deletions.
32 changes: 31 additions & 1 deletion crates/analyzer/src/analyzer_error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -614,7 +614,12 @@ pub enum AnalyzerError {
error_location: SourceSpan,
},

#[diagnostic(severity(Error), code(invalid_enum_encoding), help(""), url(""))]
#[diagnostic(
severity(Error),
code(invalid_enum_encoding),
help(""),
url("https://doc.veryl-lang.org/book/07_appendix/02_semantic_error.html#invalid_enum_encoding")
)]
#[error("{identifier} is not valid enum encoding")]
InvalidEnumEncoding {
identifier: String,
Expand All @@ -624,6 +629,23 @@ pub enum AnalyzerError {
error_location: SourceSpan,
},

#[diagnostic(
severity(Error),
code(invalid_cond_type),
help(""),
url(
"https://doc.veryl-lang.org/book/07_appendix/02_semantic_error.html#invalid_cond_type"
)
)]
#[error("{identifier} is not valid condition type")]
InvalidCondType {
identifier: String,
#[source_code]
input: NamedSource<String>,
#[label("Error location")]
error_location: SourceSpan,
},

#[diagnostic(
severity(Error),
code(too_large_enum_variant),
Expand Down Expand Up @@ -1412,6 +1434,14 @@ impl AnalyzerError {
}
}

pub fn invalid_cond_type(identifier: &str, source: &str, token: &TokenRange) -> Self {
AnalyzerError::InvalidCondType {
identifier: identifier.to_string(),
input: AnalyzerError::named_source(source, token),
error_location: token.into(),
}
}

pub fn too_large_enum_variant(
identifier: &str,
value: isize,
Expand Down
48 changes: 48 additions & 0 deletions crates/analyzer/src/attribute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ pub enum Attribute {
EnumEncoding(EnumEncodingItem),
EnumMemberPrefix(StrId),
Test(Token, Option<StrId>),
CondType(CondTypeItem),
}

impl fmt::Display for Attribute {
Expand All @@ -24,6 +25,7 @@ impl fmt::Display for Attribute {
Attribute::EnumEncoding(x) => format!("enum_encoding({})", x),
Attribute::EnumMemberPrefix(x) => format!("enum_member_prefix({})", x),
Attribute::Test(x, _) => format!("test({})", x.text),
Attribute::CondType(x) => format!("cond_type({})", x),
};
text.fmt(f)
}
Expand All @@ -35,6 +37,7 @@ pub enum AttributeError {
MismatchArgs(&'static str),
InvalidAllow(StrId),
InvalidEnumEncoding(StrId),
InvalidCondType(StrId),
}

fn get_arg_ident(
Expand Down Expand Up @@ -91,6 +94,11 @@ struct Pattern {
pub gray: StrId,
pub enum_member_prefix: StrId,
pub test: StrId,
pub cond_type: StrId,
pub unique: StrId,
pub unique0: StrId,
pub priority: StrId,
pub none: StrId,
}

impl Pattern {
Expand All @@ -109,6 +117,11 @@ impl Pattern {
gray: resource_table::insert_str("gray"),
enum_member_prefix: resource_table::insert_str("enum_member_prefix"),
test: resource_table::insert_str("test"),
cond_type: resource_table::insert_str("cond_type"),
unique: resource_table::insert_str("unique"),
unique0: resource_table::insert_str("unique0"),
priority: resource_table::insert_str("priority"),
none: resource_table::insert_str("none"),
}
}
}
Expand Down Expand Up @@ -197,6 +210,21 @@ impl TryFrom<&veryl_parser::veryl_grammar_trait::Attribute> for Attribute {
Err(AttributeError::MismatchArgs("single identifier"))
}
}
x if x == pat.cond_type => {
let arg = get_arg_ident(&value.attribute_opt, 0);

if let Some(arg) = arg {
match arg.text {
x if x == pat.unique => Ok(Attribute::CondType(CondTypeItem::Unique)),
x if x == pat.unique0 => Ok(Attribute::CondType(CondTypeItem::Unique0)),
x if x == pat.priority => Ok(Attribute::CondType(CondTypeItem::Priority)),
x if x == pat.none => Ok(Attribute::CondType(CondTypeItem::None)),
_ => Err(AttributeError::InvalidCondType(arg.text)),
}
} else {
Err(AttributeError::MismatchArgs("condition type"))
}
}
_ => Err(AttributeError::UnknownAttribute),
})
}
Expand Down Expand Up @@ -238,3 +266,23 @@ impl fmt::Display for EnumEncodingItem {
text.fmt(f)
}
}

#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum CondTypeItem {
Unique,
Unique0,
Priority,
None,
}

impl fmt::Display for CondTypeItem {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let text = match self {
CondTypeItem::Unique => "unique",
CondTypeItem::Unique0 => "unique0",
CondTypeItem::Priority => "priority",
CondTypeItem::None => "none",
};
text.fmt(f)
}
}
29 changes: 25 additions & 4 deletions crates/analyzer/src/handlers/check_attribute.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use crate::analyzer_error::AnalyzerError;
use crate::attribute::AttributeError;
use crate::attribute_table;
use veryl_parser::last_token::LastToken;
use veryl_parser::veryl_grammar_trait::*;
Expand Down Expand Up @@ -40,42 +41,62 @@ impl<'a> VerylGrammarTrait for CheckAttribute<'a> {
Err(err) => {
attribute_table::begin(arg.hash.hash_token.token, None);
match err {
crate::attribute::AttributeError::UnknownAttribute => {
AttributeError::UnknownAttribute => {
self.errors.push(AnalyzerError::unknown_attribute(
&arg.identifier.identifier_token.to_string(),
self.text,
&arg.identifier.as_ref().into(),
));
}
crate::attribute::AttributeError::MismatchArgs(x) => {
AttributeError::MismatchArgs(x) => {
self.errors.push(AnalyzerError::mismatch_attribute_args(
&arg.identifier.identifier_token.to_string(),
x,
self.text,
&arg.identifier.as_ref().into(),
));
}
crate::attribute::AttributeError::InvalidAllow(x) => {
AttributeError::InvalidAllow(x) => {
self.errors.push(AnalyzerError::invalid_allow(
&x.to_string(),
self.text,
&arg.identifier.as_ref().into(),
));
}
crate::attribute::AttributeError::InvalidEnumEncoding(x) => {
AttributeError::InvalidEnumEncoding(x) => {
self.errors.push(AnalyzerError::invalid_enum_encoding(
&x.to_string(),
self.text,
&arg.identifier.as_ref().into(),
));
}
AttributeError::InvalidCondType(x) => {
self.errors.push(AnalyzerError::invalid_cond_type(
&x.to_string(),
self.text,
&arg.identifier.as_ref().into(),
));
}
}
}
}
}
Ok(())
}

fn statement_block_group(&mut self, arg: &StatementBlockGroup) -> Result<(), ParolError> {
if let HandlerPoint::After = self.point {
let mut last_token = LastToken::default();
last_token.statement_block_group(arg);
let last_token = last_token.token().unwrap();

for _ in &arg.statement_block_group_list {
attribute_table::end(last_token);
}
}
Ok(())
}

fn modport_group(&mut self, arg: &ModportGroup) -> Result<(), ParolError> {
if let HandlerPoint::After = self.point {
let mut last_token = LastToken::default();
Expand Down
10 changes: 5 additions & 5 deletions crates/analyzer/src/handlers/check_clock_reset.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,11 +98,11 @@ impl<'a> VerylGrammarTrait for CheckClockReset<'a> {
let if_reset_required = if let Some(ref x) = arg.always_ff_declaration_opt {
if x.alwayf_ff_event_list.alwayf_ff_event_list_opt.is_some() {
if let Some(x) = arg.statement_block.statement_block_list.first() {
match &*x.statement_block_item {
StatementBlockItem::Statement(x) => {
!matches!(*x.statement, Statement::IfResetStatement(_))
}
_ => true,
let x: Vec<_> = x.statement_block_group.as_ref().into();
if let Some(StatementBlockItem::Statement(x)) = x.first() {
!matches!(*x.statement, Statement::IfResetStatement(_))
} else {
true
}
} else {
true
Expand Down
28 changes: 24 additions & 4 deletions crates/analyzer/src/handlers/check_var_ref.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::analyzer_error::AnalyzerError;
use crate::attribute::AllowItem;
use crate::attribute::Attribute as Attr;
use crate::attribute::{AllowItem, CondTypeItem};
use crate::attribute_table;
use crate::symbol::{Direction, SymbolId, SymbolKind, TypeKind};
use crate::symbol_table;
Expand All @@ -11,6 +11,7 @@ use crate::var_ref::{
};
use std::collections::HashMap;
use veryl_parser::veryl_grammar_trait::*;
use veryl_parser::veryl_token::Token;
use veryl_parser::veryl_walker::{Handler, HandlerPoint};
use veryl_parser::ParolError;

Expand Down Expand Up @@ -95,6 +96,19 @@ fn can_assign(full_path: &[SymbolId]) -> bool {
false
}

fn has_cond_type(token: &Token) -> bool {
let mut attrs = attribute_table::get(token);
attrs.reverse();
for attr in attrs {
match attr {
Attr::CondType(CondTypeItem::None) => return false,
Attr::CondType(_) => return true,
_ => (),
}
}
false
}

impl<'a> VerylGrammarTrait for CheckVarRef<'a> {
fn r#else(&mut self, arg: &Else) -> Result<(), ParolError> {
if let HandlerPoint::Before = self.point {
Expand Down Expand Up @@ -248,7 +262,9 @@ impl<'a> VerylGrammarTrait for CheckVarRef<'a> {
HandlerPoint::Before => {
self.branch_index = 0;
let branches = 1 + arg.if_statement_list.len() + arg.if_statement_opt.iter().len();
let has_default = arg.if_statement_opt.is_some();
let has_explicit_default = arg.if_statement_opt.is_some();
let has_cond_type = has_cond_type(&arg.r#if.if_token.token);
let has_default = has_explicit_default | has_cond_type;
self.assign_position
.push(AssignPositionType::StatementBranch {
token: arg.r#if.if_token.token,
Expand Down Expand Up @@ -279,7 +295,9 @@ impl<'a> VerylGrammarTrait for CheckVarRef<'a> {
self.branch_index = 0;
let branches =
1 + arg.if_reset_statement_list.len() + arg.if_reset_statement_opt.iter().len();
let has_default = arg.if_reset_statement_opt.is_some();
let has_explicit_default = arg.if_reset_statement_opt.is_some();
let has_cond_type = has_cond_type(&arg.if_reset.if_reset_token.token);
let has_default = has_explicit_default | has_cond_type;
let allow_missing_reset_statement = attribute_table::contains(
&arg.if_reset.if_reset_token.token,
Attr::Allow(AllowItem::MissingResetStatement),
Expand Down Expand Up @@ -326,12 +344,14 @@ impl<'a> VerylGrammarTrait for CheckVarRef<'a> {
HandlerPoint::Before => {
self.branch_index = 0;
let branches = arg.case_statement_list.len();
let has_default = arg.case_statement_list.iter().any(|x| {
let has_explicit_default = arg.case_statement_list.iter().any(|x| {
matches!(
x.case_item.case_item_group.as_ref(),
CaseItemGroup::Defaul(_)
)
});
let has_cond_type = has_cond_type(&arg.case.case_token.token);
let has_default = has_explicit_default | has_cond_type;
self.assign_position
.push(AssignPositionType::StatementBranch {
token: arg.case.case_token.token,
Expand Down
Loading

0 comments on commit 220873d

Please sign in to comment.