pub trait CompilerDriver: Sized {
// Required methods
fn main_path(&self) -> &ModulePath;
fn load_module(
&mut self,
path: &ModulePath,
) -> Result<TranslationUnit, Error>;
fn link(
&self,
modules: &mut Vec<Module>,
used_items: &UsedItems,
) -> Result<TranslationUnit, Error>;
// Provided methods
fn canonical_path(&self, path: &ModulePath) -> ModulePath { ... }
fn main_entry_points(
&self,
main_module: &TranslationUnit,
) -> Result<HashSet<Ident>, Error> { ... }
fn module_usage_analysis(
&self,
module: &Module,
already_used: &mut UsedItems,
to_analyze: &mut UsedItems,
) -> Result<(), Error> { ... }
fn usage_analysis(
&self,
module: &Module,
decl_name: &str,
min_vis: Visibility,
already_used: &mut UsedItems,
to_analyze: &mut UsedItems,
) -> Result<(), Error> { ... }
fn compile(&mut self) -> Result<CompileResult, Error> { ... }
fn load_module_async(
&mut self,
path: &ModulePath,
) -> impl Future<Output = Result<TranslationUnit, Error>> { ... }
fn compile_async(
&mut self,
) -> impl Future<Output = Result<CompileResult, Error>> { ... }
}Expand description
Re-implementing this trait gives full control over the steps of the compilation pipeline.
It is implemented by crate::Compiler.
The steps, default-implemented in Self::compile, are:
- Load the main module.
- Get the list declarations in the main module serving as entry points; they are the basis of static usage analysis.
- Run static usage analysis: for each entry point, collect the list of declarations it depends on, transitively. Usage analysis returns the set of imported identifiers (defined in other modules).
- Load missing imported modules found via usage analysis.
- Run the previous two steps with imported modules/identifiers, until all identifiers have been usage-analyzed.
- Assemble loaded modules into a final module.
WESL features are implemented at different steps of this pipeline:
- Conditional translation runs after module loading.
- Import resolution runs at usage analysis.
- Name mangling runs before assembly.
Required Methods§
Sourcefn main_path(&self) -> &ModulePath
fn main_path(&self) -> &ModulePath
Get the path of the main module.
Sourcefn load_module(&mut self, path: &ModulePath) -> Result<TranslationUnit, Error>
fn load_module(&mut self, path: &ModulePath) -> Result<TranslationUnit, Error>
Get the TranslationUnit for a module at a given path.
This function is called only once per module path.
Sourcefn link(
&self,
modules: &mut Vec<Module>,
used_items: &UsedItems,
) -> Result<TranslationUnit, Error>
fn link( &self, modules: &mut Vec<Module>, used_items: &UsedItems, ) -> Result<TranslationUnit, Error>
Assemble the list of loaded module into a final output.
used_items contains the result of static usage analysis, i.e the list identifiers
which the main module entrypoints depend on, transitively.
Provided Methods§
Sourcefn canonical_path(&self, path: &ModulePath) -> ModulePath
fn canonical_path(&self, path: &ModulePath) -> ModulePath
Get the canonical path to a module.
Currently, this only affects package dependency unification, e.g. if package A imports from X and package B also imports from X, and both X are semver-compatible, then there should be a unique path to X.
Sourcefn main_entry_points(
&self,
main_module: &TranslationUnit,
) -> Result<HashSet<Ident>, Error>
fn main_entry_points( &self, main_module: &TranslationUnit, ) -> Result<HashSet<Ident>, Error>
List identifiers of declarations serving as starting point for static usage analysis.
Typically they are the entry points functions (@vertex, @fragment and @compute),
but some users might want to keep different declarations.
Sourcefn module_usage_analysis(
&self,
module: &Module,
already_used: &mut UsedItems,
to_analyze: &mut UsedItems,
) -> Result<(), Error>
fn module_usage_analysis( &self, module: &Module, already_used: &mut UsedItems, to_analyze: &mut UsedItems, ) -> Result<(), Error>
Find declarations used in external modules which this module depends on, no matter what.
Currently, only items referenced by module-scope const_asserts are always included.
See Self::usage_analysis.
Sourcefn usage_analysis(
&self,
module: &Module,
decl_name: &str,
min_vis: Visibility,
already_used: &mut UsedItems,
to_analyze: &mut UsedItems,
) -> Result<(), Error>
fn usage_analysis( &self, module: &Module, decl_name: &str, min_vis: Visibility, already_used: &mut UsedItems, to_analyze: &mut UsedItems, ) -> Result<(), Error>
Find declaration names which a local declaration depends on.
Adds external referenced idents to to_analyze with their minimum required visibility.
Perform usage analysis recursively with local referenced idents, and adds them to already_used
with their declaration visibility.
So at the end of the call, to_analyze contains incomplete usage analysis which needs to continue
in a separate module. already_used contains finished analysis.
min_vis is the minimum visibility requirement for the declaration.
Sourcefn compile(&mut self) -> Result<CompileResult, Error>
fn compile(&mut self) -> Result<CompileResult, Error>
Run the compilation pipeline.
See standalone default implementation in pass::compile.
Sourcefn load_module_async(
&mut self,
path: &ModulePath,
) -> impl Future<Output = Result<TranslationUnit, Error>>
fn load_module_async( &mut self, path: &ModulePath, ) -> impl Future<Output = Result<TranslationUnit, Error>>
Async version of Self::load_module.
Sourcefn compile_async(
&mut self,
) -> impl Future<Output = Result<CompileResult, Error>>
fn compile_async( &mut self, ) -> impl Future<Output = Result<CompileResult, Error>>
Async version of Self::compile.
Dyn Compatibility§
This trait is not dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety".