pub fn locate_import_file(filename: &str, bindings: &SymbolBindings, allow_relative: bool) -> ImportFile {
    // The import_path atom can be defined to a list of paths to try to read imported files from
    let import_path = get_id_for_atom_with_name("import_path");
    let built_ins   = get_id_for_atom_with_name("built_ins");

    let import_path = bindings.look_up(import_path);
    let built_ins   = bindings.look_up(built_ins);

    // Convert the import path into a list of strings
    let import_path = read_strings(import_path);

    // Try to open the file by searching the input paths
    let file_path = Path::new(filename);

    let file_path = if allow_relative && !file_path.is_absolute() && file_path.is_file() {
        // If the current directory is allowed then try the current directory
        Some(file_path.to_path_buf())
    } else if allow_relative && !file_path.is_absolute() && file_path.extension().is_none() && file_path.with_extension(DEFAULT_EXTENSION).is_file() {
        // We also add the '.sf' extension if it's not already set
        Some(file_path.with_extension(DEFAULT_EXTENSION))
    } else if file_path.is_absolute() || file_path.components().nth(0) == Some(Component::CurDir) || file_path.components().nth(0) == Some(Component::ParentDir) {
        // Absolute paths are not searched for: we'll just return it as existing if an absolute path or a path starting at the current directory is used
        if file_path.is_file() {
            Some(file_path.to_path_buf())
        } else if file_path.extension().is_none() && file_path.with_extension(DEFAULT_EXTENSION).is_file() {
            Some(file_path.with_extension(DEFAULT_EXTENSION))
        } else {
            None
        }
    } else {
        // Relative paths are searched via the import paths
        let mut found = None;
        for import_prefix in import_path.iter() {
            let import_prefix = Path::new(import_prefix);

            // To be a valid import path, the path must indicate exactly where it's located
            if import_prefix.is_absolute() || import_prefix.components().nth(0) == Some(Component::CurDir) || import_prefix.components().nth(0) == Some(Component::ParentDir) {
                let try_path = import_prefix.join(file_path);
                if try_path.is_file() {
                    found = Some(try_path);
                } else if try_path.extension().is_none() && try_path.with_extension(DEFAULT_EXTENSION).is_file() {
                    found = Some(try_path.with_extension(DEFAULT_EXTENSION));
                }
            }
        }

        found
    };

    if let Some(file_path) = file_path {
        // Found as an actual file
        ImportFile::FromPath(file_path)
    } else if let Some((built_ins, _)) = built_ins {
        // Search the built-ins from the bindings (try with an extra .sf suffix if necessary)
        let built_in = btree_search(built_ins.clone(), CellRef::new(SafasCell::String(filename.to_string())));
        let built_in = if let Ok(built_in) = built_in {
            if built_in.is_nil() {
                // Try with a .sf extension
                btree_search(built_ins, CellRef::new(SafasCell::String(format!("{}.sf", filename))))
            } else {
                // Already found
                Ok(built_in)
            }
        } else {
            // Error
            built_in
        };

        // If a match was found in the b-tree then use that as the file to load
        match built_in {
            Ok(definition) => {
                if let SafasCell::String(definition) = &*definition {
                    ImportFile::BuiltIn(filename.to_string(), definition.clone())
                } else {
                    ImportFile::NotFound
                }
            },

            Err(_) => {
                ImportFile::NotFound
            }
        }
    } else {
        ImportFile::NotFound
    }
}
///
/// Attempts to locate where a particular file to be imported can be loaded from
/// 
/// The `filename` is the name provided by the user/program for the file to import. The `bindings` are used to
/// retrieve the environment for the import: in particular, the `import_path` and `built_ins` atoms should be
/// defined to be the list of paths to search for imports and the list of built-in definitions respectively.
/// Search order follows the import paths first then looks at the builtins.
///
Attempts to locate where a particular file to be imported can be loaded from
The `filename` is the name provided by the user/program for the file to import.
Attempts to locate where a particular file to be imported can be loaded from The ` filename ` is the name provided by the user / program for the file to import .
pub fn locate_import_file(filename: &str, bindings: &SymbolBindings, allow_relative: bool) -> ImportFile {
    // The import_path atom can be defined to a list of paths to try to read imported files from
    let import_path = get_id_for_atom_with_name("import_path");
    let built_ins   = get_id_for_atom_with_name("built_ins");
    let import_path = bindings.look_up(import_path);
    let built_ins   = bindings.look_up(built_ins);
    // Convert the import path into a list of strings
    let import_path = read_strings(import_path);
    // Try to open the file by searching the input paths
    let file_path = Path::new(filename);
    let file_path = if allow_relative && !file_path.is_absolute() && file_path.is_file() {
        // If the current directory is allowed then try the current directory
        Some(file_path.to_path_buf())
    } else if allow_relative && !file_path.is_absolute() && file_path.extension().is_none() && file_path.with_extension(DEFAULT_EXTENSION).is_file() {
        // We also add the '.sf' extension if it's not already set
        Some(file_path.with_extension(DEFAULT_EXTENSION))
    } else if file_path.is_absolute() || file_path.components().nth(0) == Some(Component::CurDir) || file_path.components().nth(0) == Some(Component::ParentDir) {
        // Absolute paths are not searched for: we'll just return it as existing if an absolute path or a path starting at the current directory is used
        if file_path.is_file() {
            Some(file_path.to_path_buf())
        } else if file_path.extension().is_none() && file_path.with_extension(DEFAULT_EXTENSION).is_file() {
            Some(file_path.with_extension(DEFAULT_EXTENSION))
        } else {
            None
        }
    } else {
        // Relative paths are searched via the import paths
        let mut found = None;
        for import_prefix in import_path.iter() {
            let import_prefix = Path::new(import_prefix);
            // To be a valid import path, the path must indicate exactly where it's located
            if import_prefix.is_absolute() || import_prefix.components().nth(0) == Some(Component::CurDir) || import_prefix.components().nth(0) == Some(Component::ParentDir) {
                let try_path = import_prefix.join(file_path);
                if try_path.is_file() {
                    found = Some(try_path);
                } else if try_path.extension().is_none() && try_path.with_extension(DEFAULT_EXTENSION).is_file() {
                    found = Some(try_path.with_extension(DEFAULT_EXTENSION));
                }
            }
        }
        found
    };
    if let Some(file_path) = file_path {
        // Found as an actual file
        ImportFile::FromPath(file_path)
    } else if let Some((built_ins, _)) = built_ins {
        // Search the built-ins from the bindings (try with an extra .sf suffix if necessary)
        let built_in = btree_search(built_ins.clone(), CellRef::new(SafasCell::String(filename.to_string())));
        let built_in = if let Ok(built_in) = built_in {
            if built_in.is_nil() {
                // Try with a .sf extension
                btree_search(built_ins, CellRef::new(SafasCell::String(format!("{}.sf", filename))))
            } else {
                // Already found
                Ok(built_in)
            }
        } else {
            // Error
            built_in
        };
        // If a match was found in the b-tree then use that as the file to load
        match built_in {
            Ok(definition) => {
                if let SafasCell::String(definition) = &*definition {
                    ImportFile::BuiltIn(filename.to_string(), definition.clone())
                } else {
                    ImportFile::NotFound
                }
            },
            Err(_) => {
                ImportFile::NotFound
            }
        }
    } else {
        ImportFile::NotFound
    }
}
pub fn locate_import_file ( filename : & str , bindings : & SymbolBindings , allow_relative : bool ) -> ImportFile { // The import_path atom can be defined to a list of paths to try to read imported files from let import_path = get_id_for_atom_with_name ( " " ) ; let built_ins = get_id_for_atom_with_name ( " " ) ; let import_path = bindings . look_up ( import_path ) ; let built_ins = bindings . look_up ( built_ins ) ; // Convert the import path into a list of strings let import_path = read_strings ( import_path ) ; // Try to open the file by searching the input paths let file_path = Path :: new ( filename ) ; let file_path = if allow_relative && ! file_path . is_absolute ( ) && file_path . is_file ( ) { // If the current directory is allowed then try the current directory Some ( file_path . to_path_buf ( ) ) } else if allow_relative && ! file_path . is_absolute ( ) && file_path . extension ( ) . is_none ( ) && file_path . with_extension ( DEFAULT_EXTENSION ) . is_file ( ) { // We also add the '.sf' extension if it's not already set Some ( file_path . with_extension ( DEFAULT_EXTENSION ) ) } else if file_path . is_absolute ( ) || file_path . components ( ) . nth ( 0 ) == Some ( Component :: CurDir ) || file_path . components ( ) . nth ( 0 ) == Some ( Component :: ParentDir ) { // Absolute paths are not searched for: we'll just return it as existing if an absolute path or a path starting at the current directory is used if file_path . is_file ( ) { Some ( file_path . to_path_buf ( ) ) } else if file_path . extension ( ) . is_none ( ) && file_path . with_extension ( DEFAULT_EXTENSION ) . is_file ( ) { Some ( file_path . with_extension ( DEFAULT_EXTENSION ) ) } else { None } } else { // Relative paths are searched via the import paths let mut found = None ; for import_prefix in import_path . iter ( ) { let import_prefix = Path :: new ( import_prefix ) ; // To be a valid import path, the path must indicate exactly where it's located if import_prefix . is_absolute ( ) || import_prefix . components ( ) . nth ( 0 ) == Some ( Component :: CurDir ) || import_prefix . components ( ) . nth ( 0 ) == Some ( Component :: ParentDir ) { let try_path = import_prefix . join ( file_path ) ; if try_path . is_file ( ) { found = Some ( try_path ) ; } else if try_path . extension ( ) . is_none ( ) && try_path . with_extension ( DEFAULT_EXTENSION ) . is_file ( ) { found = Some ( try_path . with_extension ( DEFAULT_EXTENSION ) ) ; } } } found } ; if let Some ( file_path ) = file_path { // Found as an actual file ImportFile :: FromPath ( file_path ) } else if let Some ( ( built_ins , _ ) ) = built_ins { // Search the built-ins from the bindings (try with an extra .sf suffix if necessary) let built_in = btree_search ( built_ins . clone ( ) , CellRef :: new ( SafasCell :: String ( filename . to_string ( ) ) ) ) ; let built_in = if let Ok ( built_in ) = built_in { if built_in . is_nil ( ) { // Try with a .sf extension btree_search ( built_ins , CellRef :: new ( SafasCell :: String ( format ! ( " " filename ) ) ) ) } else { // Already found Ok ( built_in ) } } else { // Error built_in } ; // If a match was found in the b-tree then use that as the file to load match built_in { Ok ( definition ) => { if let SafasCell :: String ( definition ) = & * definition { ImportFile :: BuiltIn ( filename . to_string ( ) , definition . clone ( ) ) } else { ImportFile :: NotFound } } , Err ( _ ) => { ImportFile :: NotFound } } } else { ImportFile :: NotFound } }
Attempts to locate where a particular file to be imported can be loaded from
The `filename` is the name provided by the user/program for the file to import.
Attempts to locate where a particular file to be imported can be loaded from The ` filename ` is the name provided by the user / program for the file to import .
filename
&str
bindings
&SymbolBindings
allow_relative
bool
filename
&str
bindings
&SymbolBindings
allow_relative
bool