Skip to main content

CompilerDriver

Trait CompilerDriver 

Source
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:

  1. Load the main module.
  2. Get the list declarations in the main module serving as entry points; they are the basis of static usage analysis.
  3. 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).
  4. Load missing imported modules found via usage analysis.
  5. Run the previous two steps with imported modules/identifiers, until all identifiers have been usage-analyzed.
  6. 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§

Source

fn main_path(&self) -> &ModulePath

Get the path of the main module.

Source

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.

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§

Source

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.

Source

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.

Source

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.

Source

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.

Source

fn compile(&mut self) -> Result<CompileResult, Error>

Run the compilation pipeline.

See standalone default implementation in pass::compile.

Source

fn load_module_async( &mut self, path: &ModulePath, ) -> impl Future<Output = Result<TranslationUnit, Error>>

Async version of Self::load_module.

Source

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".

Implementors§