Skip to content

Commit

Permalink
Copy paste some stuff in the AstResolver impl. TODO: adapt it
Browse files Browse the repository at this point in the history
  • Loading branch information
yannham committed Jan 24, 2025
1 parent a75d6cb commit 3366ff3
Showing 1 changed file with 134 additions and 35 deletions.
169 changes: 134 additions & 35 deletions core/src/cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -569,7 +569,7 @@ impl SourceCache {
}

let mut import_data = ImportData::new();
let resolver = resolvers::AstResolver {
let resolver = AstResolver {
alloc: &alloc,
asts: &HashMap::new(),
new_asts: Vec::new(),
Expand Down Expand Up @@ -1803,45 +1803,144 @@ pub fn timestamp(path: impl AsRef<OsStr>) -> io::Result<SystemTime> {
fs::metadata(path.as_ref())?.modified()
}

/// Provide mockup import resolvers for testing purpose.
pub mod resolvers {
use super::*;
/// As RFC007 is being rolled out, the typechecker now needs to operate on the new AST. We thus
/// need a structure that implements [AstImportResolver]. For borrowing reasons, this can't be all
/// of [Caches] or all of [ast_cache::AstCache], as we need to split the different things that are
/// borrowed mutably or immutably, or with different lifetimes. `AstResolver` is a structure that
/// borrows some parts of the cache during its lifetime and will retrieve alredy imported ASTs, or
/// register the newly imported ones in a separate vector, that can be then added back to the
/// original cache. They can't be added directly to the AST cache, once again, for borrowing and
/// lifetime reasons.
pub struct AstResolver<'ast, 'cache, 'input> {
/// The AST allocator used to parse new sources.
alloc: &'ast AstAlloc,
/// The AST cache before the start of import resolution. Because of technicalities of the
/// self-referential [super::AstCache], we can only take it as an immutable reference. Newly
/// imported ASTs are put in [Self::new_asts].
asts: &'cache HashMap<FileId, (Ast<'ast>, ParseErrors)>,
/// Newly imported ASTs, to be appended to the AST cache after resolution.
new_asts: Vec<(FileId, Ast<'ast>)>,
/// The source cache where new sources will be stored.
sources: &'input mut SourceCache,
/// Direct and reverse dependencies of files (with respect to imports).
import_data: &'cache mut ImportData,
}

pub struct AstResolver<'ast, 'cache, 'input> {
/// The ast allocator used to parse new sources.
pub(super) alloc: &'ast AstAlloc,
/// The ast cache before the start of import resolution. Because of technicalities of the
/// self-referential [super::AstCache], we can only take it as an immutable reference.
/// Newly imported ASTs are put in [Self::new_asts].
pub(super) asts: &'cache HashMap<FileId, (Ast<'ast>, ParseErrors)>,
/// Newly imported ASTs, to be appended to the AST cache after resolution.
pub(super) new_asts: Vec<(FileId, Ast<'ast>)>,
/// The source cache where new sources will be stored.
pub(super) sources: &'input mut SourceCache,
/// Direct and reverse dependencies of files (with respect to imports).
pub(super) import_data: &'cache mut ImportData,
}

impl<'ast, 'cache, 'input> AstResolver<'ast, 'cache, 'input> {
pub(super) fn append_to_cache(self, asts: &mut HashMap<FileId, (Ast<'ast>, ParseErrors)>) {
asts.extend(
self.new_asts
.into_iter()
.map(|(id, ast)| (id, (ast, ParseErrors::default()))),
);
}
impl<'ast, 'cache, 'input> AstResolver<'ast, 'cache, 'input> {
/// Consumes self and add the new file that were imported during the lifetime of this
/// resolver to the given AST cache.
fn append_to_cache(self, asts: &mut HashMap<FileId, (Ast<'ast>, ParseErrors)>) {
asts.extend(
self.new_asts
.into_iter()
.map(|(id, ast)| (id, (ast, ParseErrors::default()))),
);
}
}

impl<'ast, 'cache, 'input> AstImportResolver<'ast> for AstResolver<'ast, 'cache, 'input> {
fn resolve(
&mut self,
_import: &Import,
_parent: Option<FileId>,
_pos: &TermPos,
) -> Result<(ResolvedTerm, Ast<'ast>), ImportError> {
todo!()
impl<'ast, 'cache, 'input> AstImportResolver<'ast> for AstResolver<'ast, 'cache, 'input> {
fn resolve(
&mut self,
import: &Import,
parent: Option<FileId>,
pos: &TermPos,
) -> Result<(ResolvedTerm, Ast<'ast>), ImportError> {
//TODO[RFC007]: continue this, was just copy pasted now

let (possible_parents, path, pkg_id, format) = match import {
Import::Path { path, format } => {
// `parent` is the file that did the import. We first look in its containing directory, followed by
// the directories in the import path.
let mut parent_path = parent
.and_then(|p| self.get_path(p))

Check failure on line 1855 in core/src/cache.rs

View workflow job for this annotation

GitHub Actions / build-and-test (windows-latest)

no method named `get_path` found for mutable reference `&mut cache::AstResolver<'ast, 'cache, 'input>` in the current scope
.map(PathBuf::from)
.unwrap_or_default();
parent_path.pop();

(
std::iter::once(parent_path)
.chain(self.sources.import_paths.iter().cloned())
.collect(),
Path::new(path),
None,
*format,
)
}
Import::Package { id } => {
let package_map = self
.sources
.package_map
.as_ref()
.ok_or(ImportError::NoPackageMap { pos: *pos })?;
let parent_path = parent
.and_then(|p| self.sources.packages.get(&p))
.map(PathBuf::as_path);
let pkg_path = package_map.get(parent_path, *id, *pos)?;
(
vec![pkg_path.to_owned()],
Path::new("main.ncl"),
Some(pkg_path.to_owned()),
// Packages are always in nickel format
InputFormat::Nickel,
)
}
};

// Try to import from all possibilities, taking the first one that succeeds.
let (id_op, path_buf) = possible_parents
.iter()
.find_map(|parent| {
let mut path_buf = parent.clone();
path_buf.push(path);
self.sources
.get_or_add_file(&path_buf, format)
.ok()
.map(|x| (x, path_buf))
})
.ok_or_else(|| {
let parents = possible_parents
.iter()
.map(|p| p.to_string_lossy())
.collect::<Vec<_>>();
ImportError::IOError(
path.to_string_lossy().into_owned(),
format!("could not find import (looked in [{}])", parents.join(", ")),
*pos,
)
})?;

let (result, file_id) = match id_op {
CacheOp::Cached(id) => (ResolvedTerm::FromCache, id),
CacheOp::Done(id) => (ResolvedTerm::FromFile { path: path_buf }, id),
};

if let Some(parent) = parent {
self.import_data
.imports
.entry(parent)
.or_default()
.insert(file_id);
self.import_data
.rev_imports
.entry(file_id)
.or_default()
.insert(parent);
}

self.parse(file_id, format)

Check failure on line 1930 in core/src/cache.rs

View workflow job for this annotation

GitHub Actions / build-and-test (windows-latest)

no method named `parse` found for mutable reference `&mut cache::AstResolver<'ast, 'cache, 'input>` in the current scope
.map_err(|err| ImportError::ParseErrors(err, *pos))?;

if let Some(pkg_id) = pkg_id {
self.sources.packages.insert(file_id, pkg_id);
}

Ok((result, file_id))

Check failure on line 1937 in core/src/cache.rs

View workflow job for this annotation

GitHub Actions / build-and-test (windows-latest)

mismatched types
}
}

/// Provide mockup import resolvers for testing purpose.
pub mod resolvers {
use super::*;

/// A dummy resolver that panics when asked to do something. Used to test code that contains no
/// import.
Expand Down

0 comments on commit 3366ff3

Please sign in to comment.