A WESL module compiler for MoonBit backed by WGSL Core.
Dependencies
moon add Milky2018/moon_weslimport {
"Milky2018/moon_wesl",
}///|
test {
let resolver = @moon_wesl.VirtualResolver::new()
let util_path = @moon_wesl.ModulePath::from_path("/shaders/util.wesl")
let root_path = @moon_wesl.ModulePath::from_path(
"/shaders/custom_material.wesl",
)
resolver.add_module(
util_path, "fn make_polka_dots(v: f32) -> f32 {\n @if(PARTY_MODE) {\n return v * 2.0;\n } @else {\n return v;\n }\n}\n",
)
resolver.add_module(
root_path, "import super::util::make_polka_dots;\n@fragment\nfn fragment(v: f32) -> f32 {\n return make_polka_dots(v);\n}\n",
)
let features = @moon_wesl.Features::default()
features.set_feature("PARTY_MODE", Enable)
let options = {
..@moon_wesl.CompileOptions::default(),
lower: true,
features,
}
let result = try! @moon_wesl.compile(
root_path,
resolver,
@moon_wesl.EscapeMangler::default(),
options,
)
inspect(result.to_string().contains("@fragment"), content="true")
}///|
pub(open) trait Resolver {
fn resolve_source(Self, @moon_wesl.ModulePath) -> String raise @moon_wesl.ResolveError
}| Field | Default | Meaning |
|---|---|---|
| imports | true | Parse and resolve import statements. If disabled, import declarations are ignored instead of resolved. |
| condcomp | true | Evaluate @if / @else if / @else blocks using the features map. |
| strip | true | Emit only reachable declarations instead of the full transitive module closure. |
| lower | false | Remove top-level alias and const declarations by textual substitution. |
| lazy_resolution | true | When stripping is enabled, avoid eagerly loading imports that are never used. |
| mangle_root | false | Mangle declarations from the root module too. |
| keep_root | false | Keep every declaration in the root module when stripping is enabled. |
| keep | None | Keep a specific set of root declarations even if they are not entry points. |
| features | {} | Configure conditional compilation; start from Features::default() and call set_feature. |
moon test -v
moon info
moon fmtpub(open) trait ModulePreprocessor {
fn preprocess_module(Self, ModulePath, TranslationUnit) -> TranslationUnit raise ResolveError
}pub(open) trait Resolver {
fn resolve_source(Self, ModulePath) -> String raise ResolveError
fn resolve_module(Self, ModulePath) -> TranslationUnit raise ResolveError = _
fn display_name(Self, ModulePath) -> String? = _
}pub(open) trait SourceMap {
fn get_decl(Self, String) -> (ModulePath, String)?
fn get_source(Self, ModulePath) -> String?
fn get_display_name(Self, ModulePath) -> String?
fn get_default_source(Self) -> String? = _
fn unmangle_text(Self, String) -> String = _
}pub(all) suberror ModulePathParseError {
Empty
MisplacedPackage
MisplacedSelf
MisplacedSuper
}pub(all) suberror ValidateError {
UndefinedSymbol(String)
ParamCount(String, Int, Int)
NotCallable(String)
Duplicate(String)
Cycle(String, String)
}pub(all) suberror WeslCompileError {
Resolve(ResolveError)
Parse(String)
Validation(String)
Validate(ValidateError)
InvalidExpression(String)
DuplicateSymbol(String)
CircularDecl(String)
MissingDecl(ModulePath, String)
Private(String, ModulePath)
}pub(all) struct AliasDeclaration {
name : String
target : String?
target_type : TypeExpression?
} derive(Eq, Debug)pub(all) struct AssignmentStatement {
operator : AssignmentOperator
lhs : Expression
rhs : Expression
} derive(Eq, Debug)pub(all) struct Attribute {
name : String
arguments : String?
argument_exprs : Array[Expression]
condition_expr : CondExpression?
span : SyntaxSpan
} derive(Eq, Debug)pub struct BasicSourceMap {
root : ModulePath
mappings : HashMap[String, (ModulePath, String)]
sources : HashMap[ModulePath, (String?, String)]
default_source : String?
} derive(Debug)impl SourceMap for BasicSourceMapfn BasicSourceMap::add_decl(self : BasicSourceMap, decl : String, path : ModulePath, item : String) -> Unitfn BasicSourceMap::add_source(self : BasicSourceMap, file : ModulePath, name : String?, source : String) -> Unitpub struct CodegenModule {
name : String
source : String
submodules : Array[CodegenModule]
} derive(Eq, Debug)fn CodegenModule::with_submodules(self : CodegenModule, submodules : Array[CodegenModule]) -> CodegenModulepub struct CodegenPkg {
crate_name : String
root : CodegenModule
dependencies : Array[CodegenPkg]
} derive(Eq, Debug)pub struct CompileResult {
syntax : TranslationUnit
sourcemap : BasicSourceMap?
modules : Array[ModulePath]
} derive(Debug)fn CompileResult::exec(self : CompileResult, entrypoint : String, inputs : Inputs, resources : Array[ResourceBinding], overrides : Array[OverrideValue]) -> ExecResult raise WeslCompileErrorimpl ModulePreprocessor for CondCompPreprocessorfn preprocess_module(self : CondCompPreprocessor, _path : ModulePath, unit : TranslationUnit) -> TranslationUnit raise ResolveErrorpub(all) enum CondExpression {
Literal(Bool)
Feature(String)
Not(CondExpression)
And(CondExpression, CondExpression)
Or(CondExpression, CondExpression)
} derive(Eq, Debug)pub(all) struct ConstAssertDeclaration {
assertion : String
assertion_expr : Expression
} derive(Eq, Debug)pub(all) struct ConstDeclaration {
name : String
type_text : String?
type_expr : TypeExpression?
initializer : String?
initializer_expr : Expression?
} derive(Eq, Debug)pub(all) enum ControlStatement {
Block(BlockStatement)
If(IfStatement)
Switch(SwitchStatement)
Loop(LoopStatement)
For(ForStatement)
While(WhileStatement)
Continuing(ContinuingStatement)
} derive(Eq, Debug)fn[S : SourceMap] Diagnostic::unmangle_with_sourcemap(self : Diagnostic, sourcemap : S) -> Diagnosticfn Diagnostic::with_module_path(self : Diagnostic, path : ModulePath, display_name : String?) -> Diagnosticpub(all) struct DiagnosticDetail {
source : String?
output : String?
module_path : ModulePath?
display_name : String?
declaration : String?
span : SourceSpan?
message : String?
} derive(Eq, Debug)pub struct EscapeMangler {
}pub(all) struct ExecResult {
value : String?
buffer : Bytes?
resources : Array[ResourceBinding]
} derive(Eq, Debug)pub(all) enum Expression {
Literal(String)
Bool(Bool)
TypeOrIdentifier(TypeExpression)
Parenthesized(Expression)
NamedComponent(Expression, String)
Indexing(Expression, Expression)
Unary(UnaryOperator, Expression)
Binary(BinaryOperator, Expression, Expression)
FunctionCall(FunctionCallExpression)
} derive(Eq, Debug)pub(all) enum ForInitializer {
Declaration(StatementDeclaration)
Assignment(AssignmentStatement)
Expression(Expression)
} derive(Eq, Debug)pub(all) struct ForStatement {
initializer : ForInitializer?
condition : Expression?
update : ForUpdate?
body : FunctionBody
} derive(Eq, Debug)pub(all) enum ForUpdate {
Assignment(AssignmentStatement)
Increment(Expression)
Decrement(Expression)
Expression(Expression)
} derive(Eq, Debug)pub(all) struct FunctionCallExpression {
callee : TypeExpression
arguments : Array[Expression]
} derive(Eq, Debug)pub(all) struct FunctionDeclaration {
name : String
generic_parameters : String?
parameters : Array[FunctionParameter]
return_type : String?
return_type_expr : TypeExpression?
return_attributes : Array[Attribute]
body : FunctionBody
} derive(Eq, Debug)pub(all) struct FunctionParameter {
name : String
type_text : String
type_expr : TypeExpression
attributes : Array[Attribute]
} derive(Eq, Debug)pub(all) struct GlobalDeclaration {
header : GlobalDeclarationHeader
attributes : Array[Attribute]
source : String
span : SyntaxSpan
} derive(Eq, Debug)pub(all) enum GlobalDeclarationHeader {
Function(FunctionDeclaration)
Struct(StructDeclaration)
Alias(AliasDeclaration)
Const(ConstDeclaration)
Override(OverrideDeclaration)
Let(LetDeclaration)
Var(VarDeclaration)
ConstAssert(ConstAssertDeclaration)
EnableDirective(EnableDirectiveDeclaration)
RequiresDirective(RequiresDirectiveDeclaration)
DiagnosticDirective(DiagnosticDirectiveDeclaration)
Other
} derive(Eq, Debug)pub struct IdentityPreprocessor {
}impl ModulePreprocessor for IdentityPreprocessorfn preprocess_module(_self : IdentityPreprocessor, _path : ModulePath, unit : TranslationUnit) -> TranslationUnit raise ResolveErrorpub(all) struct IfStatement {
condition : Expression
body : FunctionBody
else_body : FunctionBody?
} derive(Eq, Debug)pub(all) struct ImportNode {
path_segments : Array[String]
rename : String?
children : Array[ImportNode]
} derive(Eq, Debug)pub(all) struct ImportStatement {
span : SyntaxSpan
attributes : Array[Attribute]
entries : Array[ImportNode]
source : String
} derive(Eq, Debug)pub(all) struct ImportedName {
export_module_path : ModulePath?
export_name : String?
namespace_path : ModulePath
local_name : String
} derive(Eq, Debug)pub(all) struct Inputs {
vertex_index : Int?
instance_index : Int?
position : Array[Double]?
front_facing : Bool?
sample_index : Int?
sample_mask : Int?
local_invocation_id : Array[Int]?
local_invocation_index : Int?
global_invocation_id : Array[Int]?
workgroup_id : Array[Int]?
num_workgroups : Array[Int]?
subgroup_invocation_id : Int?
subgroup_size : Int?
subgroup_id : Int?
num_subgroups : Int?
primitive_index : Int?
view_index : Int?
user_defined : Array[UserInput]
} derive(Eq, Debug)pub(all) struct LetDeclaration {
name : String
type_text : String?
type_expr : TypeExpression?
initializer : String?
initializer_expr : Expression?
} derive(Eq, Debug)pub(all) struct ModulePath {
origin : PathOrigin
components : Array[String]
} derive(Eq, Hash, Debug)pub(all) struct OverrideDeclaration {
name : String
type_text : String?
type_expr : TypeExpression?
initializer : String?
initializer_expr : Expression?
} derive(Eq, Debug)pub struct Preprocessor[R, P] {
resolver : R
preprocess : P
}impl Resolver for Preprocessor[R, P]fn[R : Resolver, P : ModulePreprocessor] display_name(self : Preprocessor[R, P], path : ModulePath) -> String?fn[R : Resolver, P : ModulePreprocessor] resolve_module(self : Preprocessor[R, P], path : ModulePath) -> TranslationUnit raise ResolveErrorfn[R : Resolver, P : ModulePreprocessor] resolve_source(self : Preprocessor[R, P], path : ModulePath) -> String raise ResolveErrorpub struct Router {
// private fields
}fn Router::mount_standard_resolver(self : Router, prefix : ModulePath, resolver : StandardResolver) -> Unitpub struct SourceMapper[R] {
root : ModulePath
resolver : R
mangler : ManglerKind
sourcemap : BasicSourceMap
}impl Resolver for SourceMapper[R]fn[R : Resolver] resolve_module(self : SourceMapper[R], path : ModulePath) -> TranslationUnit raise ResolveErrorfn[R : Resolver] resolve_source(self : SourceMapper[R], path : ModulePath) -> String raise ResolveErrorpub struct StandardResolver {
pkg : PkgResolver
modules : VirtualResolver
constants : HashMap[String, Double]
}impl Resolver for StandardResolverfn StandardResolver::add_module(self : StandardResolver, path : ModulePath, source : String) -> Unitpub(all) struct Statement {
kind : StatementKind
source : String
expression : Expression?
declaration : StatementDeclaration?
assignment : AssignmentStatement?
update_expression : Expression?
control : ControlStatement?
attributes : Array[Attribute]
} derive(Eq, Debug)pub(all) struct StatementDeclaration {
kind : StatementDeclarationKind
name : String?
template_arguments : String?
type_text : String?
type_expr : TypeExpression?
initializer : String?
initializer_expr : Expression?
} derive(Eq, Debug)pub(all) struct StructMember {
name : String
type_text : String
type_expr : TypeExpression
attributes : Array[Attribute]
} derive(Eq, Debug)pub(all) struct SwitchCase {
selectors : Array[Expression]
is_default : Bool
body : FunctionBody
attributes : Array[Attribute]
} derive(Eq, Debug)pub(all) struct SwitchStatement {
selector : Expression
cases : Array[SwitchCase]
} derive(Eq, Debug)pub(all) struct TranslationUnit {
imports : Array[ImportStatement]
global_declarations : Array[GlobalDeclaration]
} derive(Eq, Debug)pub(all) struct TypeExpression {
path : Array[String]
ident : String
template_text : String?
template_args : Array[TypeTemplateArgument]
} derive(Eq, Debug)pub(all) struct VarDeclaration {
name : String?
template_arguments : String?
type_text : String?
type_expr : TypeExpression?
initializer : String?
initializer_expr : Expression?
} derive(Eq, Debug)impl Resolver for VirtualResolverfn VirtualResolver::add_translation_unit(self : VirtualResolver, path : ModulePath, translation_unit : TranslationUnit) -> Unitfn VirtualResolver::get_module(self : VirtualResolver, path : ModulePath) -> String raise ResolveErrorpub struct Wesl[R] {
options : CompileOptions
use_sourcemap : Bool
resolver : R
mangler : ManglerKind
}fn Wesl::add_constant(self : Wesl[StandardResolver], name : String, value : Double) -> Wesl[StandardResolver]fn Wesl::add_constants(self : Wesl[StandardResolver], constants : Array[(String, Double)]) -> Wesl[StandardResolver]fn Wesl::add_module(self : Wesl[StandardResolver], path : ModulePath, source : String) -> Wesl[StandardResolver]fn Wesl::add_packages(self : Wesl[StandardResolver], pkgs : Array[CodegenPkg]) -> Wesl[StandardResolver]fn[R : Resolver] Wesl::compile(self : Wesl[R], root : ModulePath) -> CompileResult raise WeslCompileErrorfn[R : Resolver] Wesl::compile_diagnostic(self : Wesl[R], root : ModulePath) -> CompileResult raise WeslDiagnosticErrorfn[R : Resolver] compile(root : ModulePath, resolver : R, _mangler : EscapeMangler, options : CompileOptions) -> CompileResult raise WeslCompileErrorfn[R : Resolver] compile_diagnostic(root : ModulePath, resolver : R, _mangler : EscapeMangler, options : CompileOptions) -> CompileResult raise WeslDiagnosticErrorfn[R : Resolver] compile_sourcemap(root : ModulePath, resolver : R, _mangler : EscapeMangler, options : CompileOptions) -> CompileResult raise WeslCompileErrorfn[R : Resolver] compile_sourcemap_diagnostic(root : ModulePath, resolver : R, _mangler : EscapeMangler, options : CompileOptions) -> CompileResult raise WeslDiagnosticErrorfn parse_translation_unit(current_path : ModulePath, source : String, parse_imports : Bool) -> TranslationUnit raise WeslCompileErrorA WESL module compiler for MoonBit backed by WGSL Core.
Dependencies