Support executing require in dynamically generated, library-aware virtual filesystems
#339
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
This PR introduces
Library::RequireVfsas an alternative toRequireVfs(the current abstraction around the filesystem,@stdlibraries,@lutelibraries, and [optionally] CLI commands).To accomplish this, we introduce
IRequireVfsas a shared interface inrequire.hthat bothRequireVfsandLibrary::RequireVfsimplement;RequireCtxnow simply contains astd::unique_ptr<IRequireVfs>.At a surface level,
Library::RequireVfs's logic is fairly similar toRequireVfs's. OurRequireVfsimplementation can be in any of the following VFS types at a given moment:Disk,Std,Cli,Lute. Similarly,Library::RequireVfscan be in any of the following:Library,Std,Lute.The default VFS type (for example, when code execution of a project begins) for
Library::RequireVfsisLibrary. In this case,Library::RequireVfsmanages an internalLibrary::Vfs, which itself can be in one of two VFS states:DiskorSubtree. Conceptually, theDiskcase is used to execute user code, andSubtreeis used for executing code in installed libraries.To enable executing code that relies on installed libraries,
Library::Vfsmust be constructed with two arguments:directDependencies: the list of all libraries that user code directly depends on.libraries: the list of all transitive dependencies of the user code, with their dependencies on each other also passed in explicitly.What this enables: when executing user code (in
Diskmode), we are able to dynamically inject aliases to the libraries indirectDependenciesthat, when followed, transitionLibrary::VfsintoSubtreemode. Then, when executing library code (inSubtreemode), we are able to use the dependency information passed in via thelibrariesconstructor argument to inject aliases to each library's direct dependencies.Because this happens on a per-library basis, an alias
@depdoesn't need to mean the same thing inlibrary1andlibrary2. Although it is still true that user code and any individual library cannot directly depend on multiple versions of a dependency, multiple versions are completely fine in the set of transitive dependencies.