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::RequireVfs
as an alternative toRequireVfs
(the current abstraction around the filesystem,@std
libraries,@lute
libraries, and [optionally] CLI commands).To accomplish this, we introduce
IRequireVfs
as a shared interface inrequire.h
that bothRequireVfs
andLibrary::RequireVfs
implement;RequireCtx
now simply contains astd::unique_ptr<IRequireVfs>
.At a surface level,
Library::RequireVfs
's logic is fairly similar toRequireVfs
's. OurRequireVfs
implementation can be in any of the following VFS types at a given moment:Disk
,Std
,Cli
,Lute
. Similarly,Library::RequireVfs
can be in any of the following:Library
,Std
,Lute
.The default VFS type (for example, when code execution of a project begins) for
Library::RequireVfs
isLibrary
. In this case,Library::RequireVfs
manages an internalLibrary::Vfs
, which itself can be in one of two VFS states:Disk
orSubtree
. Conceptually, theDisk
case is used to execute user code, andSubtree
is used for executing code in installed libraries.To enable executing code that relies on installed libraries,
Library::Vfs
must 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
Disk
mode), we are able to dynamically inject aliases to the libraries indirectDependencies
that, when followed, transitionLibrary::Vfs
intoSubtree
mode. Then, when executing library code (inSubtree
mode), we are able to use the dependency information passed in via thelibraries
constructor argument to inject aliases to each library's direct dependencies.Because this happens on a per-library basis, an alias
@dep
doesn't need to mean the same thing inlibrary1
andlibrary2
. 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.