Skip to content

Commit

Permalink
Add msb/lsb #9
Browse files Browse the repository at this point in the history
  • Loading branch information
dalance committed Jan 31, 2023
1 parent 6724421 commit 9648b9e
Show file tree
Hide file tree
Showing 18 changed files with 22,202 additions and 18,207 deletions.
48 changes: 48 additions & 0 deletions crates/analyzer/src/analyzer_error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,24 @@ pub enum AnalyzerError {
error_location: SourceSpan,
},

#[diagnostic(code(AnalyzerError::InvalidLsb), help("remove lsb"))]
#[error("lsb can't be placed at here")]
InvalidLsb {
#[source_code]
input: NamedSource,
#[label("Error location")]
error_location: SourceSpan,
},

#[diagnostic(code(AnalyzerError::InvalidMsb), help("remove msb"))]
#[error("msb can't be placed at here")]
InvalidMsb {
#[source_code]
input: NamedSource,
#[label("Error location")]
error_location: SourceSpan,
},

#[diagnostic(code(AnalyzerError::MismatchArity), help("fix function arguments"))]
#[error("function \"{name}\" has {arity} arguments, but {args} arguments are supplied")]
MismatchArity {
Expand Down Expand Up @@ -155,6 +173,15 @@ pub enum AnalyzerError {
error_location: SourceSpan,
},

#[diagnostic(code(AnalyzerError::UnknownMsb), help(""))]
#[error("resolving msb is failed")]
UnknownMsb {
#[source_code]
input: NamedSource,
#[label("Error location")]
error_location: SourceSpan,
},

#[diagnostic(code(AnalyzerError::DuplicatedIdentifier), help(""))]
#[error("{identifier} is duplicated")]
DuplicatedIdentifier {
Expand Down Expand Up @@ -285,6 +312,20 @@ impl AnalyzerError {
}
}

pub fn invalid_lsb(source: &str, token: &VerylToken) -> Self {
AnalyzerError::InvalidLsb {
input: AnalyzerError::named_source(source, token),
error_location: token.token.into(),
}
}

pub fn invalid_msb(source: &str, token: &VerylToken) -> Self {
AnalyzerError::InvalidMsb {
input: AnalyzerError::named_source(source, token),
error_location: token.token.into(),
}
}

pub fn mismatch_arity(
name: &str,
arity: usize,
Expand Down Expand Up @@ -366,6 +407,13 @@ impl AnalyzerError {
}
}

pub fn unknown_msb(source: &str, token: &VerylToken) -> Self {
AnalyzerError::UnknownMsb {
input: AnalyzerError::named_source(source, token),
error_location: token.token.into(),
}
}

pub fn duplicated_identifier(identifier: &str, source: &str, token: &VerylToken) -> Self {
AnalyzerError::DuplicatedIdentifier {
identifier: identifier.to_string(),
Expand Down
1 change: 1 addition & 0 deletions crates/analyzer/src/evaluator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -627,6 +627,7 @@ impl Evaluator {
Factor::IfExpression(x) => self.if_expression(&x.if_expression),
Factor::CaseExpression(x) => self.case_expression(&x.case_expression),
Factor::StringLiteral(_) => Evaluated::Unknown,
Factor::FactorGroup(_) => Evaluated::Unknown,
}
}

Expand Down
6 changes: 6 additions & 0 deletions crates/analyzer/src/handlers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ pub mod check_invalid_direction;
pub mod check_invalid_number_character;
pub mod check_invalid_reset;
pub mod check_invalid_statement;
pub mod check_msb_lsb;
pub mod check_number_overflow;
pub mod check_system_function;
pub mod create_reference;
Expand All @@ -18,6 +19,7 @@ use check_invalid_direction::*;
use check_invalid_number_character::*;
use check_invalid_reset::*;
use check_invalid_statement::*;
use check_msb_lsb::*;
use check_number_overflow::*;
use check_system_function::*;
use create_reference::*;
Expand Down Expand Up @@ -82,6 +84,7 @@ pub struct Pass2Handlers<'a> {
check_enum: CheckEnum<'a>,
check_function: CheckFunction<'a>,
check_instance: CheckInstance<'a>,
check_msb_lsb: CheckMsbLsb<'a>,
create_reference: CreateReference<'a>,
}

Expand All @@ -91,6 +94,7 @@ impl<'a> Pass2Handlers<'a> {
check_enum: CheckEnum::new(text),
check_function: CheckFunction::new(text),
check_instance: CheckInstance::new(text),
check_msb_lsb: CheckMsbLsb::new(text),
create_reference: CreateReference::new(text),
}
}
Expand All @@ -100,6 +104,7 @@ impl<'a> Pass2Handlers<'a> {
&mut self.check_enum as &mut dyn Handler,
&mut self.check_function as &mut dyn Handler,
&mut self.check_instance as &mut dyn Handler,
&mut self.check_msb_lsb as &mut dyn Handler,
&mut self.create_reference as &mut dyn Handler,
]
}
Expand All @@ -109,6 +114,7 @@ impl<'a> Pass2Handlers<'a> {
ret.append(&mut self.check_enum.errors);
ret.append(&mut self.check_function.errors);
ret.append(&mut self.check_instance.errors);
ret.append(&mut self.check_msb_lsb.errors);
ret.append(&mut self.create_reference.errors);
ret
}
Expand Down
135 changes: 135 additions & 0 deletions crates/analyzer/src/handlers/check_msb_lsb.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
use crate::analyzer_error::AnalyzerError;
use crate::msb_table;
use crate::namespace_table;
use crate::symbol::SymbolKind;
use crate::symbol_table::{self, SymbolPath, SymbolPathNamespace};
use veryl_parser::veryl_grammar_trait::*;
use veryl_parser::veryl_walker::{Handler, HandlerPoint};
use veryl_parser::ParolError;

pub struct CheckMsbLsb<'a> {
pub errors: Vec<AnalyzerError>,
text: &'a str,
point: HandlerPoint,
identifier_path: Vec<SymbolPathNamespace>,
range_dimension: Vec<usize>,
in_expression_identifier: bool,
in_range: bool,
}

impl<'a> CheckMsbLsb<'a> {
pub fn new(text: &'a str) -> Self {
Self {
errors: Vec::new(),
text,
point: HandlerPoint::Before,
identifier_path: Vec::new(),
range_dimension: Vec::new(),
in_expression_identifier: false,
in_range: false,
}
}
}

impl<'a> Handler for CheckMsbLsb<'a> {
fn set_point(&mut self, p: HandlerPoint) {
self.point = p;
}
}

impl<'a> VerylGrammarTrait for CheckMsbLsb<'a> {
fn lsb(&mut self, arg: &Lsb) -> Result<(), ParolError> {
if let HandlerPoint::Before = self.point {
if !(self.in_expression_identifier && self.in_range) {
self.errors
.push(AnalyzerError::invalid_lsb(self.text, &arg.lsb_token));
}
}
Ok(())
}

fn msb(&mut self, arg: &Msb) -> Result<(), ParolError> {
if let HandlerPoint::Before = self.point {
if self.in_expression_identifier && self.in_range {
let resolved = if let Ok(x) =
symbol_table::resolve(self.identifier_path.last().unwrap().clone())
{
if let Some(x) = x.found {
if let SymbolKind::Variable(x) = x.kind {
let range_dimension = *self.range_dimension.last().unwrap();
let expression = if range_dimension >= x.r#type.array.len() {
&x.r#type.width[range_dimension - x.r#type.array.len()]
} else {
&x.r#type.array[range_dimension]
};
msb_table::insert(arg.msb_token.token.id, expression);
true
} else {
false
}
} else {
false
}
} else {
false
};
if !resolved {
self.errors
.push(AnalyzerError::unknown_msb(self.text, &arg.msb_token));
}
} else {
self.errors
.push(AnalyzerError::invalid_msb(self.text, &arg.msb_token));
}
}
Ok(())
}

fn identifier(&mut self, arg: &Identifier) -> Result<(), ParolError> {
if let HandlerPoint::Before = self.point {
if self.in_expression_identifier {
self.identifier_path
.last_mut()
.unwrap()
.0
.push(arg.identifier_token.token.text);
}
}
Ok(())
}

fn range(&mut self, _arg: &Range) -> Result<(), ParolError> {
match self.point {
HandlerPoint::Before => {
self.in_range = true;
}
HandlerPoint::After => {
self.in_range = false;
if self.in_expression_identifier {
*self.range_dimension.last_mut().unwrap() += 1;
}
}
}
Ok(())
}

fn expression_identifier(&mut self, arg: &ExpressionIdentifier) -> Result<(), ParolError> {
match self.point {
HandlerPoint::Before => {
let namespace =
namespace_table::get(arg.identifier.identifier_token.token.id).unwrap();
let symbol_path = SymbolPath::default();
self.identifier_path
.push(SymbolPathNamespace(symbol_path, namespace));
self.range_dimension.push(0);
self.in_expression_identifier = true;
}
HandlerPoint::After => {
self.identifier_path.pop();
self.range_dimension.pop();
self.in_expression_identifier = false;
}
}
Ok(())
}
}
1 change: 1 addition & 0 deletions crates/analyzer/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ pub mod analyzer;
pub mod analyzer_error;
pub mod evaluator;
pub mod handlers;
pub mod msb_table;
pub mod namespace;
pub mod namespace_table;
pub mod symbol;
Expand Down
37 changes: 37 additions & 0 deletions crates/analyzer/src/msb_table.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
use std::cell::RefCell;
use std::collections::HashMap;
use veryl_parser::resource_table::TokenId;
use veryl_parser::veryl_grammar_trait::Expression;

#[derive(Clone, Debug)]
pub struct MsbTable {
table: HashMap<TokenId, Expression>,
}

impl MsbTable {
pub fn insert(&mut self, id: TokenId, expression: &Expression) {
self.table.insert(id, expression.clone());
}

pub fn get(&self, id: TokenId) -> Option<&Expression> {
self.table.get(&id)
}
}

impl Default for MsbTable {
fn default() -> Self {
Self {
table: HashMap::new(),
}
}
}

thread_local!(static MSB_TABLE: RefCell<MsbTable> = RefCell::new(MsbTable::default()));

pub fn insert(id: TokenId, expression: &Expression) {
MSB_TABLE.with(|f| f.borrow_mut().insert(id, expression))
}

pub fn get(id: TokenId) -> Option<Expression> {
MSB_TABLE.with(|f| f.borrow().get(id).cloned())
}
17 changes: 13 additions & 4 deletions crates/analyzer/src/symbol_table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,14 @@ impl SymbolPath {
self.0.push(x)
}

pub fn pop(&mut self) -> Option<StrId> {
self.0.pop()
}

pub fn clear(&mut self) {
self.0.clear()
}

pub fn as_slice(&self) -> &[StrId] {
self.0.as_slice()
}
Expand Down Expand Up @@ -83,14 +91,14 @@ impl From<&syntax_tree::ExpressionIdentifier> for SymbolPath {
}
path.push(value.identifier.identifier_token.token.text);
match &*value.expression_identifier_group {
syntax_tree::ExpressionIdentifierGroup::ColonColonIdentifierExpressionIdentifierGroupList(x) => {
syntax_tree::ExpressionIdentifierGroup::ColonColonIdentifierExpressionIdentifierGroupListExpressionIdentifierGroupList0(x) => {
path.push(x.identifier.identifier_token.token.text);
for x in &x.expression_identifier_group_list {
path.push(x.identifier.identifier_token.token.text);
}
},
syntax_tree::ExpressionIdentifierGroup::ExpressionIdentifierGroupList0ExpressionIdentifierGroupList1(x) => {
for x in &x.expression_identifier_group_list1 {
syntax_tree::ExpressionIdentifierGroup::ExpressionIdentifierGroupList1ExpressionIdentifierGroupList2(x) => {
for x in &x.expression_identifier_group_list2 {
path.push(x.identifier.identifier_token.token.text);
}
},
Expand All @@ -99,7 +107,8 @@ impl From<&syntax_tree::ExpressionIdentifier> for SymbolPath {
}
}

pub struct SymbolPathNamespace(SymbolPath, Namespace);
#[derive(Clone, Default)]
pub struct SymbolPathNamespace(pub SymbolPath, pub Namespace);

impl From<&syntax_tree::Identifier> for SymbolPathNamespace {
fn from(value: &syntax_tree::Identifier) -> Self {
Expand Down
Loading

0 comments on commit 9648b9e

Please sign in to comment.