/// Resolve a name within a scope. Traverses to the parent scopes if nothing
/// matching the name is found.
Resolve a name within a scope. Traverses to the parent scopes if nothing
matching the name is found.
Resolve a name within a scope . Traverses to the parent scopes if nothing matching the name is found .
pub fn resolve_name(
        &self,
        name: Spanned<ResolvableName>,
        scope_id: ScopeRef,
        only_defs: bool,
        allow_fail: bool,
    ) -> Result<Vec<Spanned<Def>>> {
        if self.sess.opts.verbosity.contains(Verbosity::NAMES) {
            debugln!("resolving `{}` in scope {:?}", name.value, scope_id);
        }
        if self.sess.opts.trace_scoreboard {
            debugln!(
                "[SB][VHDL] resolve {:?} in scope {:?}",
                name.value,
                scope_id
            );
        }
        let mut found_defs = Vec::new();
        let parent_id = if !(*BUILTIN_SCOPE_REFS).contains(&scope_id) {
            if only_defs {
                let defs = self.defs(scope_id)?;
                if let Some(d) = defs.get(&name.value) {
                    found_defs.extend(d);
                }
                None
            } else {
                let scope = self.scope(scope_id)?;
                for &defs_id in &scope.defs {
                    let defs = self.defs(defs_id)?;
                    if let Some(d) = defs.get(&name.value) {
                        found_defs.extend(d);
                    }
                }
                if let Some(d) = scope.explicit_defs.get(&name.value) {
                    found_defs.extend(d.iter());
                }
                scope.parent
            }
        } else {
            None
        };
        // Check the revised scoping mechanism for definitions.
        // TODO: Remove everything else once this becomes the main approach.
        {
            let tbl = self.sb.scope2_table.borrow();
            if let Some(scope) = tbl.get(&scope_id) {
                if let Some(d) = scope.defs.get(&name.value) {
                    found_defs.extend(d);
                }
                if let Some(d) = scope.imported_defs.get(&name.value) {
                    found_defs.extend(d);
                }
                for &id in &scope.imported_scopes {
                    if let Some(scope) = tbl.get(&id) {
                        if let Some(d) = scope.defs.get(&name.value) {
                            found_defs.extend(d);
                        }
                    }
                }
            }
        }
        // If nothing matched the definition, try to escalate to the parent
        // scope. If there is no parent scope, i.e. we're the parent, fail with
        // a diagnostic.
        if found_defs.is_empty() {
            if let Some(parent_id) = parent_id {
                self.resolve_name(name, parent_id, only_defs, allow_fail)
            } else if allow_fail {
                Ok(vec![])
            } else {
                self.emit(
                    DiagBuilder2::error(format!("`{}` is not known", name.value)).span(name.span),
                );
                Err(())
            }
        } else {
            if self.sess.opts.trace_scoreboard {
                debugln!("[SB][VHDL] resolved {:?} to {:?}", name.value, found_defs);
            }
            if self.sess.opts.verbosity.contains(Verbosity::NAMES) {
                self.emit(
                    DiagBuilder2::note(format!("resolved `{}` to {:?}", name.value, found_defs))
                        .span(name.span),
                );
            }
            Ok(found_defs)
        }
    }
pub fn resolve_name ( & self , name : Spanned < ResolvableName > , scope_id : ScopeRef , only_defs : bool , allow_fail : bool , ) -> Result < Vec < Spanned < Def > > > { if self . sess . opts . verbosity . contains ( Verbosity :: NAMES ) { debugln ! ( " " name value scope_id ) ; } if self . sess . opts . trace_scoreboard { debugln ! ( " " name value scope_id ) ; } let mut found_defs = Vec :: new ( ) ; let parent_id = if ! ( * BUILTIN_SCOPE_REFS ) . contains ( & scope_id ) { if only_defs { let defs = self . defs ( scope_id ) ? ; if let Some ( d ) = defs . get ( & name . value ) { found_defs . extend ( d ) ; } None } else { let scope = self . scope ( scope_id ) ? ; for & defs_id in & scope . defs { let defs = self . defs ( defs_id ) ? ; if let Some ( d ) = defs . get ( & name . value ) { found_defs . extend ( d ) ; } } if let Some ( d ) = scope . explicit_defs . get ( & name . value ) { found_defs . extend ( d . iter ( ) ) ; } scope . parent } } else { None } ; // Check the revised scoping mechanism for definitions. // TODO: Remove everything else once this becomes the main approach. { let tbl = self . sb . scope2_table . borrow ( ) ; if let Some ( scope ) = tbl . get ( & scope_id ) { if let Some ( d ) = scope . defs . get ( & name . value ) { found_defs . extend ( d ) ; } if let Some ( d ) = scope . imported_defs . get ( & name . value ) { found_defs . extend ( d ) ; } for & id in & scope . imported_scopes { if let Some ( scope ) = tbl . get ( & id ) { if let Some ( d ) = scope . defs . get ( & name . value ) { found_defs . extend ( d ) ; } } } } } // If nothing matched the definition, try to escalate to the parent // scope. If there is no parent scope, i.e. we're the parent, fail with // a diagnostic. if found_defs . is_empty ( ) { if let Some ( parent_id ) = parent_id { self . resolve_name ( name , parent_id , only_defs , allow_fail ) } else if allow_fail { Ok ( vec ! [ ] ) } else { self . emit ( DiagBuilder2 :: error ( format ! ( " " name value ) ) . span ( name . span ) , ) ; Err ( ( ) ) } } else { if self . sess . opts . trace_scoreboard { debugln ! ( " " name value found_defs ) ; } if self . sess . opts . verbosity . contains ( Verbosity :: NAMES ) { self . emit ( DiagBuilder2 :: note ( format ! ( " " name value found_defs ) ) . span ( name . span ) , ) ; } Ok ( found_defs ) } }
Resolve a name within a scope.
Resolve a name within a scope .
&self
name
Spanned<ResolvableName>
scope_id
ScopeRef
only_defs
bool
allow_fail
bool