Skip to content

Commit

Permalink
Introduce new type checker
Browse files Browse the repository at this point in the history
  • Loading branch information
dalance committed Jan 29, 2025
1 parent 15e0c31 commit 86a00f3
Show file tree
Hide file tree
Showing 9 changed files with 493 additions and 298 deletions.
542 changes: 352 additions & 190 deletions crates/analyzer/src/evaluator.rs

Large diffs are not rendered by default.

7 changes: 3 additions & 4 deletions crates/analyzer/src/handlers/check_clock_reset.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::analyzer_error::AnalyzerError;
use crate::evaluator::{Evaluated, Evaluator};
use crate::evaluator::{EvaluatedValue, Evaluator};
use crate::symbol::{SymbolKind, TypeKind};
use crate::symbol_table;
use veryl_parser::veryl_grammar_trait::*;
Expand Down Expand Up @@ -256,12 +256,11 @@ impl VerylGrammarTrait for CheckClockReset<'_> {
}

fn assignment(&mut self, arg: &Assignment) -> Result<(), ParolError> {
use Evaluated::*;
if let HandlerPoint::Before = self.point {
if self.in_if_reset {
// Check to see right hand side of reset is const evaluable
match self.evaluator.expression(&arg.expression) {
UnknownStatic | Fixed { .. } => (),
match self.evaluator.expression(&arg.expression).value {
EvaluatedValue::UnknownStatic | EvaluatedValue::Fixed(_) => (),
_ => {
self.errors
.push(AnalyzerError::invalid_reset_non_elaborative(
Expand Down
7 changes: 5 additions & 2 deletions crates/analyzer/src/handlers/check_expression.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::analyzer_error::AnalyzerError;
use crate::evaluator::{Evaluated, Evaluator};
use crate::evaluator::{EvaluatedValue, Evaluator};
use crate::symbol::{Direction, GenericBoundKind, SymbolId, SymbolKind};
use crate::symbol_table;
use veryl_parser::veryl_grammar_trait::*;
Expand Down Expand Up @@ -66,7 +66,10 @@ impl VerylGrammarTrait for CheckExpression<'_> {
fn expression(&mut self, arg: &Expression) -> Result<(), ParolError> {
if let HandlerPoint::Before = self.point {
if self.case_condition_depth >= 1 {
let result = matches!(self.evaluator.expression(arg), Evaluated::Variable { .. });
let result = matches!(
self.evaluator.expression(arg).value,
EvaluatedValue::Unknown
);
if result {
self.errors
.push(AnalyzerError::invalid_case_condition_non_elaborative(
Expand Down
5 changes: 2 additions & 3 deletions crates/analyzer/src/handlers/create_symbol_table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@ use crate::analyzer_error::AnalyzerError;
use crate::attribute::Attribute as Attr;
use crate::attribute::{AllowItem, EnumEncodingItem};
use crate::attribute_table;
use crate::evaluator::Evaluated;
use crate::evaluator::Evaluator;
use crate::evaluator::{EvaluatedValue, Evaluator};
use crate::namespace::Namespace;
use crate::namespace_table;
use crate::symbol::ClockDomain as SymClockDomain;
Expand Down Expand Up @@ -300,7 +299,7 @@ impl<'a> CreateSymbolTable<'a> {
fn evaluate_enum_value(&mut self, arg: &EnumItem) -> EnumMemberValue {
if let Some(ref x) = arg.enum_item_opt {
let evaluated = Evaluator::new().expression(&x.expression);
if let Evaluated::Fixed { value, .. } = evaluated {
if let EvaluatedValue::Fixed(value) = evaluated.value {
let valid_variant = match self.enum_encoding {
EnumEncodingItem::OneHot => value.count_ones() == 1,
EnumEncodingItem::Gray => {
Expand Down
94 changes: 63 additions & 31 deletions crates/analyzer/src/symbol.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
use crate::attribute::EnumEncodingItem;
use crate::evaluator::{Evaluated, Evaluator};
use crate::evaluator::{Evaluated, EvaluatedTypeClockKind, EvaluatedTypeResetKind, Evaluator};
use crate::namespace::Namespace;
use crate::symbol_path::{GenericSymbolPath, SymbolPath};
use crate::symbol_table;
use std::cell::{Cell, RefCell};
use std::cell::RefCell;
use std::collections::HashMap;
use std::fmt;
use veryl_parser::resource_table::{PathId, StrId};
Expand Down Expand Up @@ -68,7 +68,7 @@ pub struct Symbol {
pub references: Vec<Token>,
pub generic_instances: Vec<SymbolId>,
pub imported: Vec<Namespace>,
pub evaluated: Cell<Option<Evaluated>>,
pub evaluated: RefCell<Option<Evaluated>>,
pub allow_unused: bool,
pub public: bool,
pub doc_comment: DocComment,
Expand All @@ -90,7 +90,7 @@ impl Symbol {
references: Vec::new(),
generic_instances: Vec::new(),
imported: Vec::new(),
evaluated: Cell::new(None),
evaluated: RefCell::new(None),
allow_unused: false,
public,
doc_comment,
Expand All @@ -112,49 +112,81 @@ impl Symbol {
}

pub fn evaluate(&self) -> Evaluated {
if let Some(evaluated) = self.evaluated.get() {
evaluated
if self.evaluated.borrow().is_some() {
self.evaluated.borrow().clone().unwrap()
} else {
let evaluated = match &self.kind {
SymbolKind::Variable(x) => {
let mut evaluator = Evaluator::new();
if x.r#type.kind.is_clock() | x.r#type.kind.is_reset() {
match x.r#type.kind {
TypeKind::Clock => Evaluated::Clock,
TypeKind::ClockPosedge => Evaluated::ClockPosedge,
TypeKind::ClockNegedge => Evaluated::ClockNegedge,
TypeKind::Reset => Evaluated::Reset,
TypeKind::ResetAsyncHigh => Evaluated::ResetAsyncHigh,
TypeKind::ResetAsyncLow => Evaluated::ResetAsyncLow,
TypeKind::ResetSyncHigh => Evaluated::ResetSyncHigh,
TypeKind::ResetSyncLow => Evaluated::ResetSyncLow,
TypeKind::Clock => {
Evaluated::create_clock(EvaluatedTypeClockKind::Implicit)
}
TypeKind::ClockPosedge => {
Evaluated::create_clock(EvaluatedTypeClockKind::Posedge)
}
TypeKind::ClockNegedge => {
Evaluated::create_clock(EvaluatedTypeClockKind::Negedge)
}
TypeKind::Reset => {
Evaluated::create_reset(EvaluatedTypeResetKind::Implicit)
}
TypeKind::ResetAsyncHigh => {
Evaluated::create_reset(EvaluatedTypeResetKind::AsyncHigh)
}
TypeKind::ResetAsyncLow => {
Evaluated::create_reset(EvaluatedTypeResetKind::AsyncLow)
}
TypeKind::ResetSyncHigh => {
Evaluated::create_reset(EvaluatedTypeResetKind::SyncHigh)
}
TypeKind::ResetSyncLow => {
Evaluated::create_reset(EvaluatedTypeResetKind::SyncLow)
}
_ => unreachable!(),
}
} else if let Some(width) = evaluator.type_width(x.r#type.clone()) {
if x.loop_variable {
Evaluated::UnknownStatic
Evaluated::create_unknown(true)
} else {
Evaluated::Variable { width }
Evaluated::create_variable(width, true)
}
} else {
Evaluated::Unknown
Evaluated::create_unknown(false)
}
}
SymbolKind::Port(x) => {
if let Some(x) = &x.r#type {
match x.kind {
TypeKind::Clock => Evaluated::Clock,
TypeKind::ClockPosedge => Evaluated::ClockPosedge,
TypeKind::ClockNegedge => Evaluated::ClockNegedge,
TypeKind::Reset => Evaluated::Reset,
TypeKind::ResetAsyncHigh => Evaluated::ResetAsyncHigh,
TypeKind::ResetAsyncLow => Evaluated::ResetAsyncLow,
TypeKind::ResetSyncHigh => Evaluated::ResetSyncHigh,
TypeKind::ResetSyncLow => Evaluated::ResetSyncLow,
_ => Evaluated::Unknown,
TypeKind::Clock => {
Evaluated::create_clock(EvaluatedTypeClockKind::Implicit)
}
TypeKind::ClockPosedge => {
Evaluated::create_clock(EvaluatedTypeClockKind::Posedge)
}
TypeKind::ClockNegedge => {
Evaluated::create_clock(EvaluatedTypeClockKind::Negedge)
}
TypeKind::Reset => {
Evaluated::create_reset(EvaluatedTypeResetKind::Implicit)
}
TypeKind::ResetAsyncHigh => {
Evaluated::create_reset(EvaluatedTypeResetKind::AsyncHigh)
}
TypeKind::ResetAsyncLow => {
Evaluated::create_reset(EvaluatedTypeResetKind::AsyncLow)
}
TypeKind::ResetSyncHigh => {
Evaluated::create_reset(EvaluatedTypeResetKind::SyncHigh)
}
TypeKind::ResetSyncLow => {
Evaluated::create_reset(EvaluatedTypeResetKind::SyncLow)
}
_ => Evaluated::create_unknown(false),
}
} else {
Evaluated::Unknown
Evaluated::create_unknown(false)
}
}
SymbolKind::Parameter(x) => {
Expand All @@ -166,12 +198,12 @@ impl Symbol {
}
SymbolKind::EnumMember(_) => {
// TODO: Actually Evaluate its Width
Evaluated::UnknownStatic
Evaluated::create_unknown(true)
}
SymbolKind::Genvar => Evaluated::UnknownStatic,
_ => Evaluated::Unknown,
SymbolKind::Genvar => Evaluated::create_unknown(true),
_ => Evaluated::create_unknown(false),
};
self.evaluated.replace(Some(evaluated));
self.evaluated.replace(Some(evaluated.clone()));
evaluated
}
}
Expand Down
8 changes: 4 additions & 4 deletions crates/analyzer/src/symbol_table.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::evaluator::Evaluated;
use crate::evaluator::EvaluatedValue;
use crate::namespace::Namespace;
use crate::symbol::{DocComment, GenericBoundKind, Symbol, SymbolId, SymbolKind, TypeKind};
use crate::symbol_path::{SymbolPath, SymbolPathNamespace};
Expand Down Expand Up @@ -537,9 +537,9 @@ impl fmt::Display for SymbolTable {
for (k, v) in &vec {
for id in *v {
let symbol = self.symbol_table.get(id).unwrap();
let evaluated = if let Some(evaluated) = symbol.evaluated.get() {
match evaluated {
Evaluated::Unknown => "".to_string(),
let evaluated = if let Some(evaluated) = symbol.evaluated.borrow().as_ref() {
match evaluated.value {
EvaluatedValue::Unknown => "".to_string(),
_ => format!(" ( {evaluated:?} )"),
}
} else {
Expand Down
95 changes: 43 additions & 52 deletions crates/analyzer/src/var_ref.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::evaluator::{Evaluated, Evaluator};
use crate::evaluator::{Evaluated, EvaluatedValue, Evaluator};
use crate::namespace::Namespace;
use crate::symbol::{ConnectTarget, SymbolId};
use crate::symbol_table;
Expand Down Expand Up @@ -75,7 +75,7 @@ impl VarRefAffiliation {
}
}

#[derive(Clone, Copy, Debug)]
#[derive(Clone, Debug)]
pub enum VarRefPathItem {
Identifier {
symbol_id: SymbolId,
Expand Down Expand Up @@ -119,35 +119,32 @@ impl VarRefPathItem {

fn select_range(&self, x: &VarRefPathItem) -> Option<RangeInclusive<isize>> {
match x {
VarRefPathItem::SelectSingle {
index: Evaluated::Fixed { value: index, .. },
} => Some(*index..=*index),
VarRefPathItem::SelectColon { msb, lsb } => match (msb, lsb) {
(Evaluated::Fixed { value: msb, .. }, Evaluated::Fixed { value: lsb, .. }) => {
Some(*lsb..=*msb)
}
VarRefPathItem::SelectSingle { index } => match index.value {
EvaluatedValue::Fixed(x) => Some(x..=x),
_ => None,
},
VarRefPathItem::SelectPlusClon { position, width } => match (position, width) {
(
Evaluated::Fixed {
value: position, ..
},
Evaluated::Fixed { value: width, .. },
) => Some(*position..=position + width - 1),
VarRefPathItem::SelectColon { msb, lsb } => match (&msb.value, &lsb.value) {
(EvaluatedValue::Fixed(msb), EvaluatedValue::Fixed(lsb)) => Some(*lsb..=*msb),
_ => None,
},
VarRefPathItem::SelectMinusColon { position, width } => match (position, width) {
(
Evaluated::Fixed {
value: position, ..
},
Evaluated::Fixed { value: width, .. },
) => Some(position - width + 1..=*position),
_ => None,
},
VarRefPathItem::SelectStep { index, step } => match (index, step) {
(Evaluated::Fixed { value: index, .. }, Evaluated::Fixed { value: step, .. }) => {
VarRefPathItem::SelectPlusClon { position, width } => {
match (&position.value, &width.value) {
(EvaluatedValue::Fixed(position), EvaluatedValue::Fixed(width)) => {
Some(*position..=position + width - 1)
}
_ => None,
}
}
VarRefPathItem::SelectMinusColon { position, width } => {
match (&position.value, &width.value) {
(EvaluatedValue::Fixed(position), EvaluatedValue::Fixed(width)) => {
Some(position - width + 1..=*position)
}
_ => None,
}
}
VarRefPathItem::SelectStep { index, step } => match (&index.value, &step.value) {
(EvaluatedValue::Fixed(index), EvaluatedValue::Fixed(step)) => {
Some(step * index..=step * (index + 1) - 1)
}
_ => None,
Expand Down Expand Up @@ -212,42 +209,36 @@ impl fmt::Display for VarRefPathItem {
}
}
VarRefPathItem::SelectSingle { index } => {
if let Evaluated::Fixed { value: index, .. } = index {
if let EvaluatedValue::Fixed(index) = index.value {
format!("[{}]", index)
} else {
"[]".to_string()
}
}
VarRefPathItem::SelectColon { msb, lsb } => match (msb, lsb) {
(Evaluated::Fixed { value: msb, .. }, Evaluated::Fixed { value: lsb, .. }) => {
VarRefPathItem::SelectColon { msb, lsb } => match (&msb.value, &lsb.value) {
(EvaluatedValue::Fixed(msb), EvaluatedValue::Fixed(lsb)) => {
format!("[{}:{}]", msb, lsb)
}
_ => "[]".to_string(),
},
VarRefPathItem::SelectPlusClon { position, width } => match (position, width) {
(
Evaluated::Fixed {
value: position, ..
},
Evaluated::Fixed { value: width, .. },
) => {
format!("[{}+:{}]", position, width)
VarRefPathItem::SelectPlusClon { position, width } => {
match (&position.value, &width.value) {
(EvaluatedValue::Fixed(position), EvaluatedValue::Fixed(width)) => {
format!("[{}+:{}]", position, width)
}
_ => "[]".to_string(),
}
_ => "[]".to_string(),
},
VarRefPathItem::SelectMinusColon { position, width } => match (position, width) {
(
Evaluated::Fixed {
value: position, ..
},
Evaluated::Fixed { value: width, .. },
) => {
format!("[{}-:{}]", position, width)
}
VarRefPathItem::SelectMinusColon { position, width } => {
match (&position.value, &width.value) {
(EvaluatedValue::Fixed(position), EvaluatedValue::Fixed(width)) => {
format!("[{}-:{}]", position, width)
}
_ => "[]".to_string(),
}
_ => "[]".to_string(),
},
VarRefPathItem::SelectStep { index, step } => match (index, step) {
(Evaluated::Fixed { value: index, .. }, Evaluated::Fixed { value: step, .. }) => {
}
VarRefPathItem::SelectStep { index, step } => match (&index.value, &step.value) {
(EvaluatedValue::Fixed(index), EvaluatedValue::Fixed(step)) => {
format!("[{} step {}]", index, step)
}
_ => "[]".to_string(),
Expand Down
Loading

0 comments on commit 86a00f3

Please sign in to comment.