wgsl-tooling-wg / wesl-spec

A portable and modular superset of WGSL
BSD 3-Clause "New" or "Revised" License
30 stars 3 forks source link

What is canonical module name for a given file #36

Open ncthbrt opened 1 month ago

ncthbrt commented 1 month ago

If we're unifying file and symbolic module imports, we need a mechanism to turn a file into a module. This necessitates being able to give each file a canonical module name based on its file path. How do we go about that given that paths from the wesl root may include noise like ./src etc?

k2d222 commented 1 month ago

I think by default the file path should also be the module path. Possibly with a way to override that path in the config.

here's how I have implemented it so far:

ncthbrt commented 1 month ago

the root is set to be the folder containing the main file.

What happens if the subfolder is more nested than its dependencies, @k2d222? That was my original thought too

k2d222 commented 1 month ago

A remaining question is how to deal with inline modules. I lean towards a full scan of the root by the compiler to detect all file modules and inline modules paths.

But for packages published to npm/cargo, a generated (or edited manually) manifest file would be included and therefore prevent needing to scan the fs.

k2d222 commented 1 month ago

the root is set to be the folder containing the main file.

What happens if the subfolder is more nested than its dependencies, @k2d222? That was my original thought too

with the current import gleamy syntax, you can import relative files in parent modules with ... with a rusty syntax, you can use super.

ncthbrt commented 1 month ago

That's from the perspective of one file though. What is the absolute name of the module? I basically more or less need something that can be written as a list of identifiers to be the absolute path. Because I want to be able to rewrite something like this:

import ../a/b/c;

@vertex
fn main() -> vec4<f32> {
    return c();
}

To something like this:

import my_application/a/b/c;

@vertex
fn main() -> vec4<f32> {
    return c();
}

mod my_application {
    mod a {
        mod b {
            fn c() -> vec4<f32> {
                return vec4<f32>();
            }
        }
    }
}

And then finally to something like this:

@vertex
fn main() -> vec4<f32> {
    return my_application/a/b/c();
}

mod my_application {
    mod a {
        mod b {
            fn c() -> vec4<f32> {
                return vec4<f32>();
            }
        }
    }
}
mighdoll commented 1 month ago

In the current spec I think there's no name for the root application package. In the current typescript linker implementation, I create a synthetic canonical name, something like "_root/a/b/c", but that's hidden from users. Does the canonical name of the root package need to be visible?

Related, we discussed but decided to leave out having a shortcut syntax to the root of the package, i.e. there's no import /foo/bar in the syntax, so there's no equiv of rust use crate::foo::bar or js import bar from "/foo.js";. The plan AFAIR was to leave it out for simplicity and await user feedback. (But we could file an issue to discuss this)

import util is an absolute import and looks for util.wgsl at the root.

hmm.. import util matching _root/util.wgsl sounds like it might conflict with the spec'd package import syntax..?

any absolute path can be overriden by the linker's configuration

Should we make a spec issue around this config idea? Too soon? Or is it linker-implementation specific?

ncthbrt commented 1 month ago

The root would be visible in name mangled output and also in subpasses

ncthbrt commented 1 month ago

Also when converting from file based imports to module based imports

mighdoll commented 1 month ago

The root would be visible in name mangled output and also in subpasses by subpasses do you mean precompiling parts of a shader at build time and then later at runtime? And if so, what problem do you see?

Also when converting from file based imports to module based imports Not sure what you mean by converting, are you referring to linker internals thing or a thing a wesl programmer might do?

ncthbrt commented 1 month ago

A thing a wesl programmer might do. By conversion I mean as in the example above. Converting from a file based module structure to a single file with nested inline modules.

And passes is based on the architecture of the compiler, which is designed to be modular so it can be extended. A pass takes in the ast and mutates it. The compiler performs a series of passes.