use super::analyze::*;
use super::named_entity::*;
use super::names::*;
use super::region::*;
use crate::ast::*;
use crate::data::*;
impl<'a> AnalyzeContext<'a> {
pub fn resolve_target(
&self,
scope: &Scope<'a>,
target: &mut WithPos<Target>,
assignment_type: AssignmentType,
diagnostics: &mut dyn DiagnosticHandler,
) -> EvalResult<TypeEnt<'a>> {
match target.item {
Target::Name(ref mut name) => {
self.resolve_target_name(scope, name, &target.pos, assignment_type, diagnostics)
}
Target::Aggregate(ref mut assocs) => {
self.analyze_aggregate(scope, assocs, diagnostics)?;
Err(EvalError::Unknown)
}
}
}
pub fn resolve_target_name(
&self,
scope: &Scope<'a>,
target: &mut Name,
target_pos: &SrcPos,
assignment_type: AssignmentType,
diagnostics: &mut dyn DiagnosticHandler,
) -> EvalResult<TypeEnt<'a>> {
let object_name = self.resolve_object_name(
scope,
target_pos,
target,
"may not be the target of an assignment",
diagnostics,
)?;
if !is_valid_assignment_target(&object_name.base) {
diagnostics.push(Diagnostic::error(
target_pos,
format!(
"{} may not be the target of an assignment",
object_name.base.describe_class()
),
));
} else if !is_valid_assignment_type(&object_name.base, assignment_type) {
diagnostics.push(Diagnostic::error(
target_pos,
format!(
"{} may not be the target of a {} assignment",
object_name.base.describe_class(),
assignment_type.to_str()
),
));
}
Ok(object_name.type_mark())
}
}
#[derive(Copy, Clone)]
pub enum AssignmentType {
Signal,
Variable,
}
impl AssignmentType {
fn to_str(self) -> &'static str {
match self {
AssignmentType::Signal => "signal",
AssignmentType::Variable => "variable",
}
}
}
fn is_valid_assignment_target(base: &ObjectBase) -> bool {
base.class() != ObjectClass::Constant && !matches!(base.mode(), Some(Mode::In))
}
fn is_valid_assignment_type(base: &ObjectBase, assignment_type: AssignmentType) -> bool {
let class = base.class();
match assignment_type {
AssignmentType::Signal => matches!(class, ObjectClass::Signal),
AssignmentType::Variable => {
matches!(class, ObjectClass::Variable | ObjectClass::SharedVariable)
}
}
}