use crate::hir;
use crate::score::*;
use crate::syntax::ast;
use moore_common::errors::*;
use moore_common::score::Result;
use moore_common::source::*;
#[deny(missing_docs)]
use std::collections::HashMap;
pub struct DefsContext<'sbc, 'lazy: 'sbc, 'sb: 'lazy, 'ast: 'sb, 'ctx: 'sb> {
ctx: &'sbc ScoreContext<'lazy, 'sb, 'ast, 'ctx>,
defs: Defs,
failed: bool,
}
impl<'sbc, 'lazy, 'sb, 'ast, 'ctx> DefsContext<'sbc, 'lazy, 'sb, 'ast, 'ctx> {
pub fn new(
ctx: &'sbc ScoreContext<'lazy, 'sb, 'ast, 'ctx>,
) -> DefsContext<'sbc, 'lazy, 'sb, 'ast, 'ctx> {
DefsContext {
ctx: ctx,
defs: HashMap::new(),
failed: false,
}
}
pub fn finish(self) -> Result<Defs> {
if self.failed {
Err(())
} else {
Ok(self.defs)
}
}
pub fn emit(&mut self, diag: DiagBuilder2) {
if diag.severity >= Severity::Error {
self.failed = true;
}
self.ctx.sess.emit(diag)
}
pub fn declare(&mut self, name: Spanned<ResolvableName>, def: Def) {
if self.ctx.sess.opts.trace_scoreboard {
debugln!("[SB][VHDL][SCOPE] declaring `{}` as {:?}", name.value, def);
}
match def {
Def::Enum(_) => {
self.defs
.entry(name.value)
.or_insert_with(|| Vec::new())
.push(Spanned::new(def, name.span));
}
_ => {
let ins = self
.defs
.insert(name.value, vec![Spanned::new(def, name.span)]);
if let Some(existing) = ins {
self.emit(
DiagBuilder2::error(format!("`{}` has already been declared", name.value))
.span(name.span)
.add_note("previous declaration was here:")
.span(existing.last().unwrap().span),
);
}
}
}
}
pub fn declare_primary_name(&mut self, name: &ast::PrimaryName, def: Def) {
match self.ctx.resolvable_from_primary_name(name) {
Ok(n) => self.declare(n, def),
Err(()) => self.failed = true,
}
}
pub fn declare_pkg(&mut self, id: PkgDeclRef) {
self.declare(self.ctx.ast(id).1.name.map_into(), Def::Pkg(id))
}
pub fn declare_pkg_inst(&mut self, id: PkgInstRef) {
self.declare(self.ctx.ast(id).1.name.map_into(), Def::PkgInst(id))
}
pub fn declare_type(&mut self, id: TypeDeclRef) {
let ast = self.ctx.ast(id).1;
self.declare(ast.name.map_into(), Def::Type(id));
match ast.data {
Some(Spanned {
value: ast::EnumType(ref paren_elems),
..
}) => {
for (i, lit) in paren_elems.value.iter().enumerate() {
match lit.expr.data {
ast::NameExpr(ref name) => self.declare(
match self.ctx.resolvable_from_primary_name(&name.primary) {
Ok(n) => n,
Err(()) => continue,
},
Def::Enum(EnumRef(id, i)),
),
_ => (),
}
}
}
Some(Spanned {
value: ast::RangeType(_, Some(ref units)),
..
}) => {
for (i, unit) in units.iter().enumerate() {
self.declare(
Spanned::new(unit.0.name.into(), unit.0.span),
Def::Unit(UnitRef(id, i)),
);
}
}
_ => (),
}
}
pub fn declare_subtype(&mut self, id: SubtypeDeclRef) {
self.declare(self.ctx.ast(id).1.name.map_into(), Def::Subtype(id))
}
pub fn declare_any_in_block(&mut self, id: DeclInBlockRef) {
match id {
DeclInBlockRef::Subprog(id) => self.declare_subprog(id),
DeclInBlockRef::SubprogInst(id) => self.declare_subprog_inst(id),
DeclInBlockRef::SubprogBody(_id) => (),
DeclInBlockRef::Pkg(id) => self.declare_pkg(id),
DeclInBlockRef::PkgInst(id) => self.declare_pkg_inst(id),
DeclInBlockRef::PkgBody(_id) => (),
DeclInBlockRef::Type(id) => self.declare_type(id),
DeclInBlockRef::Subtype(id) => self.declare_subtype(id),
DeclInBlockRef::Const(id) => self.declare_const(id),
DeclInBlockRef::Signal(id) => self.declare_signal(id),
DeclInBlockRef::Var(id) => self.declare_var(id),
DeclInBlockRef::File(id) => self.declare_file(id),
DeclInBlockRef::Alias(id) => self.declare_alias(id),
DeclInBlockRef::Comp(id) => self.declare_comp(id),
DeclInBlockRef::Attr(id) => self.declare_attr(id),
DeclInBlockRef::AttrSpec(_id) => (),
DeclInBlockRef::CfgSpec(_id) => (),
DeclInBlockRef::Discon(_id) => (),
DeclInBlockRef::GroupTemp(id) => self.declare_group_temp(id),
DeclInBlockRef::Group(id) => self.declare_group(id),
}
}
pub fn declare_any_in_pkg(&mut self, id: DeclInPkgRef) {
match id {
DeclInPkgRef::Subprog(id) => self.declare_subprog(id),
DeclInPkgRef::SubprogInst(id) => self.declare_subprog_inst(id),
DeclInPkgRef::Pkg(id) => self.declare_pkg(id),
DeclInPkgRef::PkgInst(id) => self.declare_pkg_inst(id),
DeclInPkgRef::Type(id) => self.declare_type(id),
DeclInPkgRef::Subtype(id) => self.declare_subtype(id),
DeclInPkgRef::Const(id) => self.declare_const(id),
DeclInPkgRef::Signal(id) => self.declare_signal(id),
DeclInPkgRef::Var(id) => self.declare_var(id),
DeclInPkgRef::File(id) => self.declare_file(id),
DeclInPkgRef::Alias(id) => self.declare_alias(id),
DeclInPkgRef::Comp(id) => self.declare_comp(id),
DeclInPkgRef::Attr(id) => self.declare_attr(id),
DeclInPkgRef::AttrSpec(_id) => (),
DeclInPkgRef::Discon(_id) => (),
DeclInPkgRef::GroupTemp(id) => self.declare_group_temp(id),
DeclInPkgRef::Group(id) => self.declare_group(id),
}
}
pub fn declare_any_in_pkg_body(&mut self, id: DeclInPkgBodyRef) {
match id {
DeclInPkgBodyRef::Subprog(id) => self.declare_subprog(id),
DeclInPkgBodyRef::SubprogBody(_id) => (),
DeclInPkgBodyRef::SubprogInst(id) => self.declare_subprog_inst(id),
DeclInPkgBodyRef::Pkg(id) => self.declare_pkg(id),
DeclInPkgBodyRef::PkgBody(_id) => (),
DeclInPkgBodyRef::PkgInst(id) => self.declare_pkg_inst(id),
DeclInPkgBodyRef::Type(id) => self.declare_type(id),
DeclInPkgBodyRef::Subtype(id) => self.declare_subtype(id),
DeclInPkgBodyRef::Const(id) => self.declare_const(id),
DeclInPkgBodyRef::Var(id) => self.declare_var(id),
DeclInPkgBodyRef::File(id) => self.declare_file(id),
DeclInPkgBodyRef::Alias(id) => self.declare_alias(id),
DeclInPkgBodyRef::Attr(id) => self.declare_attr(id),
DeclInPkgBodyRef::AttrSpec(_id) => (),
DeclInPkgBodyRef::GroupTemp(id) => self.declare_group_temp(id),
DeclInPkgBodyRef::Group(id) => self.declare_group(id),
}
}
pub fn declare_any_in_subprog(&mut self, id: DeclInSubprogRef) {
match id {
DeclInSubprogRef::Subprog(id) => self.declare_subprog(id),
DeclInSubprogRef::SubprogBody(_id) => (),
DeclInSubprogRef::SubprogInst(id) => self.declare_subprog_inst(id),
DeclInSubprogRef::Pkg(id) => self.declare_pkg(id),
DeclInSubprogRef::PkgBody(_id) => (),
DeclInSubprogRef::PkgInst(id) => self.declare_pkg_inst(id),
DeclInSubprogRef::Type(id) => self.declare_type(id),
DeclInSubprogRef::Subtype(id) => self.declare_subtype(id),
DeclInSubprogRef::Const(id) => self.declare_const(id),
DeclInSubprogRef::Var(id) => self.declare_var(id),
DeclInSubprogRef::File(id) => self.declare_file(id),
DeclInSubprogRef::Alias(id) => self.declare_alias(id),
DeclInSubprogRef::Attr(id) => self.declare_attr(id),
DeclInSubprogRef::AttrSpec(_id) => (),
DeclInSubprogRef::GroupTemp(id) => self.declare_group_temp(id),
DeclInSubprogRef::Group(id) => self.declare_group(id),
}
}
pub fn declare_any_in_process(&mut self, id: DeclInProcRef) {
match id {
DeclInProcRef::Subprog(id) => self.declare_subprog(id),
DeclInProcRef::SubprogInst(id) => self.declare_subprog_inst(id),
DeclInProcRef::SubprogBody(_id) => (),
DeclInProcRef::Pkg(id) => self.declare_pkg(id),
DeclInProcRef::PkgInst(id) => self.declare_pkg_inst(id),
DeclInProcRef::PkgBody(_id) => (),
DeclInProcRef::Type(id) => self.declare_type(id),
DeclInProcRef::Subtype(id) => self.declare_subtype(id),
DeclInProcRef::Const(id) => self.declare_const(id),
DeclInProcRef::Var(id) => self.declare_var(id),
DeclInProcRef::File(id) => self.declare_file(id),
DeclInProcRef::Alias(id) => self.declare_alias(id),
DeclInProcRef::Attr(id) => self.declare_attr(id),
DeclInProcRef::AttrSpec(_id) => (),
DeclInProcRef::GroupTemp(id) => self.declare_group_temp(id),
DeclInProcRef::Group(id) => self.declare_group(id),
}
}
pub fn declare_const(&mut self, id: ConstDeclRef) {
let hir = match self.ctx.lazy_hir(id) {
Ok(h) => h,
Err(()) => {
self.failed = true;
return;
}
};
self.declare(hir.name.map_into(), Def::Const(id.into()))
}
pub fn declare_signal(&mut self, id: SignalDeclRef) {
let hir = match self.ctx.lazy_hir(id) {
Ok(h) => h,
Err(()) => {
self.failed = true;
return;
}
};
self.declare(hir.name.map_into(), Def::Signal(id.into()))
}
pub fn declare_var(&mut self, id: VarDeclRef) {
let hir = match self.ctx.lazy_hir(id) {
Ok(h) => h,
Err(()) => {
self.failed = true;
return;
}
};
self.declare(hir.name.map_into(), Def::Var(id.into()))
}
pub fn declare_file(&mut self, id: FileDeclRef) {
let hir = match self.ctx.lazy_hir(id) {
Ok(h) => h,
Err(()) => {
self.failed = true;
return;
}
};
self.declare(hir.name.map_into(), Def::File(id.into()))
}
pub fn declare_alias(&mut self, id: AliasDeclRef) {
self.declare_primary_name(&self.ctx.ast(id).1.name, Def::Alias(id))
}
pub fn declare_comp(&mut self, id: CompDeclRef) {
self.declare(self.ctx.ast(id).1.name.map_into(), Def::Comp(id))
}
pub fn declare_attr(&mut self, id: AttrDeclRef) {
self.declare(self.ctx.ast(id).1.name.map_into(), Def::Attr(id))
}
pub fn declare_group_temp(&mut self, id: GroupTempRef) {
self.declare(self.ctx.ast(id).1.name.map_into(), Def::GroupTemp(id))
}
pub fn declare_group(&mut self, id: GroupDeclRef) {
self.declare(self.ctx.ast(id).1.name.map_into(), Def::Group(id))
}
pub fn declare_subprog(&mut self, id: SubprogDeclRef) {
self.declare_primary_name(&self.ctx.ast(id).1.spec.name, Def::Subprog(id))
}
pub fn declare_subprog_inst(&mut self, id: SubprogInstRef) {
self.declare_primary_name(&self.ctx.ast(id).1.spec.name, Def::SubprogInst(id))
}
pub fn declare_subprog_spec(&mut self, hir: &hir::SubprogSpec) {
self.declare_generics(&hir.generics);
self.declare_intf_objs(&hir.params);
}
pub fn declare_intf_objs(&mut self, ids: &[IntfObjRef]) {
if !ids.is_empty() {
unimplemented!();
}
}
pub fn declare_generics(&mut self, ids: &[GenericRef]) {
if !ids.is_empty() {
unimplemented!();
}
}
}