fn resolve_import(
    import: &pt::Import,
    parent: Option<&ResolvedFile>,
    file_no: usize,
    cache: &mut FileCache,
    ns: &mut ast::Namespace,
) {
    let filename = match import {
        pt::Import::Plain(f) => f,
        pt::Import::GlobalSymbol(f, _) => f,
        pt::Import::Rename(f, _) => f,
    };

    let import_file_no = match cache.resolve_file(parent, &filename.string) {
        Err(message) => {
            ns.diagnostics
                .push(ast::Diagnostic::error(filename.loc, message));

            return;
        }
        Ok(file) => {
            if !ns.files.iter().any(|f| *f == file.full_path) {
                sema(file.clone(), cache, ns);

                // give up if we failed
                if diagnostics::any_errors(&ns.diagnostics) {
                    return;
                }
            }

            ns.files
                .iter()
                .position(|f| *f == file.full_path)
                .expect("import should be loaded by now")
        }
    };

    match import {
        pt::Import::Rename(_, renames) => {
            for (from, rename_to) in renames {
                if let Some(import) = ns
                    .symbols
                    .get(&(import_file_no, None, from.name.to_owned()))
                {
                    let import = import.clone();

                    let new_symbol = if let Some(to) = rename_to { to } else { from };

                    // Only add symbol if it does not already exist with same definition
                    if let Some(existing) =
                        ns.symbols.get(&(file_no, None, new_symbol.name.clone()))
                    {
                        if existing == &import {
                            continue;
                        }
                    }

                    ns.check_shadowing(file_no, None, new_symbol);

                    ns.add_symbol(file_no, None, new_symbol, import);
                } else {
                    ns.diagnostics.push(ast::Diagnostic::error(
                        from.loc,
                        format!(
                            "import ‘{}’ does not export ‘{}’",
                            filename.string,
                            from.name.to_string()
                        ),
                    ));
                }
            }
        }
        pt::Import::Plain(_) => {
            // find all the exports for the file
            let exports = ns
                .symbols
                .iter()
                .filter_map(|((file_no, contract_no, id), symbol)| {
                    if *file_no == import_file_no {
                        Some((id.clone(), *contract_no, symbol.clone()))
                    } else {
                        None
                    }
                })
                .collect::<Vec<(String, Option<usize>, ast::Symbol)>>();

            for (name, contract_no, symbol) in exports {
                let new_symbol = pt::Identifier {
                    name: name.clone(),
                    loc: filename.loc,
                };

                // Only add symbol if it does not already exist with same definition
                if let Some(existing) = ns.symbols.get(&(file_no, contract_no, name.clone())) {
                    if existing == &symbol {
                        continue;
                    }
                }

                ns.check_shadowing(file_no, contract_no, &new_symbol);

                ns.add_symbol(file_no, contract_no, &new_symbol, symbol);
            }
        }
        pt::Import::GlobalSymbol(_, symbol) => {
            ns.check_shadowing(file_no, None, &symbol);

            ns.add_symbol(
                file_no,
                None,
                &symbol,
                ast::Symbol::Import(symbol.loc, import_file_no),
            );
        }
    }
}
/// Find import file, resolve it by calling sema and add it to the namespace
Find import file, resolve it by calling sema and add it to the namespace
Find import file resolve it by calling sema and add it to the namespace
fn resolve_import(
    import: &pt::Import,
    parent: Option<&ResolvedFile>,
    file_no: usize,
    cache: &mut FileCache,
    ns: &mut ast::Namespace,
) {
    let filename = match import {
        pt::Import::Plain(f) => f,
        pt::Import::GlobalSymbol(f, _) => f,
        pt::Import::Rename(f, _) => f,
    };
    let import_file_no = match cache.resolve_file(parent, &filename.string) {
        Err(message) => {
            ns.diagnostics
                .push(ast::Diagnostic::error(filename.loc, message));
            return;
        }
        Ok(file) => {
            if !ns.files.iter().any(|f| *f == file.full_path) {
                sema(file.clone(), cache, ns);
                // give up if we failed
                if diagnostics::any_errors(&ns.diagnostics) {
                    return;
                }
            }
            ns.files
                .iter()
                .position(|f| *f == file.full_path)
                .expect("import should be loaded by now")
        }
    };
    match import {
        pt::Import::Rename(_, renames) => {
            for (from, rename_to) in renames {
                if let Some(import) = ns
                    .symbols
                    .get(&(import_file_no, None, from.name.to_owned()))
                {
                    let import = import.clone();
                    let new_symbol = if let Some(to) = rename_to { to } else { from };
                    // Only add symbol if it does not already exist with same definition
                    if let Some(existing) =
                        ns.symbols.get(&(file_no, None, new_symbol.name.clone()))
                    {
                        if existing == &import {
                            continue;
                        }
                    }
                    ns.check_shadowing(file_no, None, new_symbol);
                    ns.add_symbol(file_no, None, new_symbol, import);
                } else {
                    ns.diagnostics.push(ast::Diagnostic::error(
                        from.loc,
                        format!(
                            "import ‘{}’ does not export ‘{}’",
                            filename.string,
                            from.name.to_string()
                        ),
                    ));
                }
            }
        }
        pt::Import::Plain(_) => {
            // find all the exports for the file
            let exports = ns
                .symbols
                .iter()
                .filter_map(|((file_no, contract_no, id), symbol)| {
                    if *file_no == import_file_no {
                        Some((id.clone(), *contract_no, symbol.clone()))
                    } else {
                        None
                    }
                })
                .collect::<Vec<(String, Option<usize>, ast::Symbol)>>();
            for (name, contract_no, symbol) in exports {
                let new_symbol = pt::Identifier {
                    name: name.clone(),
                    loc: filename.loc,
                };
                // Only add symbol if it does not already exist with same definition
                if let Some(existing) = ns.symbols.get(&(file_no, contract_no, name.clone())) {
                    if existing == &symbol {
                        continue;
                    }
                }
                ns.check_shadowing(file_no, contract_no, &new_symbol);
                ns.add_symbol(file_no, contract_no, &new_symbol, symbol);
            }
        }
        pt::Import::GlobalSymbol(_, symbol) => {
            ns.check_shadowing(file_no, None, &symbol);
            ns.add_symbol(
                file_no,
                None,
                &symbol,
                ast::Symbol::Import(symbol.loc, import_file_no),
            );
        }
    }
}
fn resolve_import ( import : & pt :: Import , parent : Option < & ResolvedFile > , file_no : usize , cache : & mut FileCache , ns : & mut ast :: Namespace , ) { let filename = match import { pt :: Import :: Plain ( f ) => f , pt :: Import :: GlobalSymbol ( f , _ ) => f , pt :: Import :: Rename ( f , _ ) => f , } ; let import_file_no = match cache . resolve_file ( parent , & filename . string ) { Err ( message ) => { ns . diagnostics . push ( ast :: Diagnostic :: error ( filename . loc , message ) ) ; return ; } Ok ( file ) => { if ! ns . files . iter ( ) . any ( | f | * f == file . full_path ) { sema ( file . clone ( ) , cache , ns ) ; // give up if we failed if diagnostics :: any_errors ( & ns . diagnostics ) { return ; } } ns . files . iter ( ) . position ( | f | * f == file . full_path ) . expect ( " " ) } } ; match import { pt :: Import :: Rename ( _ , renames ) => { for ( from , rename_to ) in renames { if let Some ( import ) = ns . symbols . get ( & ( import_file_no , None , from . name . to_owned ( ) ) ) { let import = import . clone ( ) ; let new_symbol = if let Some ( to ) = rename_to { to } else { from } ; // Only add symbol if it does not already exist with same definition if let Some ( existing ) = ns . symbols . get ( & ( file_no , None , new_symbol . name . clone ( ) ) ) { if existing == & import { continue ; } } ns . check_shadowing ( file_no , None , new_symbol ) ; ns . add_symbol ( file_no , None , new_symbol , import ) ; } else { ns . diagnostics . push ( ast :: Diagnostic :: error ( from . loc , format ! ( " filename string from name to_string ( ) ) , ) ) ; } } } pt :: Import :: Plain ( _ ) => { // find all the exports for the file let exports = ns . symbols . iter ( ) . filter_map ( | ( ( file_no , contract_no , id ) , symbol ) | { if * file_no == import_file_no { Some ( ( id . clone ( ) , * contract_no , symbol . clone ( ) ) ) } else { None } } ) . collect :: < Vec < ( String , Option < usize > , ast :: Symbol ) > > ( ) ; for ( name , contract_no , symbol ) in exports { let new_symbol = pt :: Identifier { name : name . clone ( ) , loc : filename . loc , } ; // Only add symbol if it does not already exist with same definition if let Some ( existing ) = ns . symbols . get ( & ( file_no , contract_no , name . clone ( ) ) ) { if existing == & symbol { continue ; } } ns . check_shadowing ( file_no , contract_no , & new_symbol ) ; ns . add_symbol ( file_no , contract_no , & new_symbol , symbol ) ; } } pt :: Import :: GlobalSymbol ( _ , symbol ) => { ns . check_shadowing ( file_no , None , & symbol ) ; ns . add_symbol ( file_no , None , & symbol , ast :: Symbol :: Import ( symbol . loc , import_file_no ) , ) ; } } }
Find import file, resolve it by calling sema and add it to the namespace
Find import file resolve it by calling sema and add it to the namespace
import
&pt::Import
parent
Option<&ResolvedFile>
file_no
usize
cache
&mut FileCache
ns
&mut ast::Namespace
import
&pt::Import
parent
Option<&ResolvedFile>
file_no
usize
cache
&mut FileCache
ns
&mut ast::Namespace