///|
fn copy_wgsl_source_registry_map(
source_registry : Map[String, String],
) -> Map[String, String] {
let copied : Map[String, String] = Map([])
for entry in source_registry.iter() {
let (rel_path, source) = entry
copied.set(rel_path, source)
}
copied
}
///|
fn copy_wgsl_import_module_map(
module_paths : Map[String, String],
) -> Map[String, String] {
let copied : Map[String, String] = Map([])
for entry in module_paths.iter() {
let (module_path, rel_path) = entry
copied.set(module_path, rel_path)
}
copied
}
///|
fn copy_wgsl_import_module_candidates_for_path(
module_candidates : Map[String, Array[String]],
module_path : String,
) -> Array[String] {
match module_candidates.get(module_path.trim().to_owned()) {
Some(rel_paths) => rel_paths.copy()
None => []
}
}
///|
fn clear_wgsl_source_registry(
source_registry : Map[String, String],
module_paths : Map[String, String],
module_candidates : Map[String, Array[String]],
) -> Unit {
source_registry.clear()
module_paths.clear()
module_candidates.clear()
}
///|
fn register_source_into(
source_registry : Map[String, String],
module_paths : Map[String, String],
module_candidates : Map[String, Array[String]],
rel_path : String,
source : String,
explicit_module_path : String?,
) -> String? {
let normalized_rel = normalize_shader_rel_path(rel_path)
if normalized_rel == "" {
return None
}
remove_module_paths_for_rel_path(module_paths, normalized_rel)
remove_module_candidates_for_rel_path(module_candidates, normalized_rel)
source_registry.set(normalized_rel, source)
let mut module_path : String? = explicit_module_path
if module_path is None {
module_path = wgsl_source_define_import_path(source)
}
if module_path is None {
module_path = wgsl_module_path_from_rel_path(normalized_rel)
}
if module_path is Some(path) && path != "" {
module_paths.set(path, normalized_rel)
register_module_candidate_rel_path(module_candidates, path, normalized_rel)
}
Some(normalized_rel)
}
///|
fn remove_module_paths_for_rel_path(
module_paths : Map[String, String],
rel_path : String,
) -> Unit {
let stale_modules : Array[String] = []
for entry in module_paths.iter() {
let (module_path, module_rel_path) = entry
if normalize_shader_rel_path(module_rel_path) == rel_path {
stale_modules.push(module_path)
}
}
for module_path in stale_modules {
ignore(module_paths.remove(module_path))
}
}
///|
fn remove_wgsl_import_module_candidate(
module_candidates : Map[String, Array[String]],
module_path : String,
rel_path : String,
) -> Unit {
let normalized_rel = normalize_shader_rel_path(rel_path)
if normalized_rel == "" {
return
}
match module_candidates.get(module_path) {
Some(rel_paths) => {
let kept : Array[String] = []
for candidate_rel in rel_paths {
if normalize_shader_rel_path(candidate_rel) != normalized_rel {
kept.push(candidate_rel)
}
}
if kept.length() == 0 {
ignore(module_candidates.remove(module_path))
} else {
module_candidates.set(module_path, kept)
}
}
None => ()
}
}
///|
fn remove_module_candidates_for_rel_path(
module_candidates : Map[String, Array[String]],
rel_path : String,
) -> Unit {
let normalized_rel = normalize_shader_rel_path(rel_path)
let module_paths_to_prune : Array[String] = []
for entry in module_candidates.iter() {
let (module_path, rel_paths) = entry
let kept : Array[String] = []
for candidate_rel in rel_paths {
if normalize_shader_rel_path(candidate_rel) != normalized_rel {
kept.push(candidate_rel)
}
}
if kept.length() == 0 {
module_paths_to_prune.push(module_path)
} else if kept.length() != rel_paths.length() {
module_candidates.set(module_path, kept)
}
}
for module_path in module_paths_to_prune {
ignore(module_candidates.remove(module_path))
}
}
///|
fn register_module_candidate_rel_path(
module_candidates : Map[String, Array[String]],
module_path : String,
rel_path : String,
) -> Unit {
let normalized_rel = normalize_shader_rel_path(rel_path)
if module_path == "" || normalized_rel == "" {
return
}
match module_candidates.get(module_path) {
Some(rel_paths) => {
for existing_rel in rel_paths {
if normalize_shader_rel_path(existing_rel) == normalized_rel {
return
}
}
rel_paths.push(normalized_rel)
}
None => module_candidates.set(module_path, [normalized_rel])
}
}
///|
fn push_wgsl_registry_diagnostic(
diagnostics : Array[WgslDiagnostic],
severity : WgslDiagnosticSeverity,
message : String,
rel_path : String?,
symbol_name : String?,
) -> Unit {
diagnostics.push(WgslDiagnostic(severity, message, rel_path, symbol_name))
}
///|
fn wgsl_diagnostics_has_error(diagnostics : Array[WgslDiagnostic]) -> Bool {
for diagnostic in diagnostics {
if diagnostic.severity == Error {
return true
}
}
false
}
///|
fn analyze_source_files_against(
existing_rel_to_source : Map[String, String],
files : Array[WgslSourceFile],
diagnostics : Array[WgslDiagnostic],
) -> Unit {
let batch_rel_to_source : Map[String, String] = Map([])
for source_file in files {
let normalized_rel = normalize_shader_rel_path(source_file.rel_path)
if normalized_rel == "" {
push_wgsl_registry_diagnostic(
diagnostics,
Error,
"registry source file path resolves to an empty normalized path",
Some(source_file.rel_path),
None,
)
continue
}
if batch_rel_to_source.get(normalized_rel) is Some(existing_source) {
if existing_source != source_file.source {
push_wgsl_registry_diagnostic(
diagnostics,
Error,
"multiple WGSL source files normalize to the same rel_path with different contents",
Some(normalized_rel),
None,
)
}
} else if existing_rel_to_source.get(normalized_rel)
is Some(existing_source) {
if existing_source != source_file.source {
push_wgsl_registry_diagnostic(
diagnostics,
Error,
"bulk registry would overwrite an existing rel_path with different contents",
Some(normalized_rel),
None,
)
}
}
batch_rel_to_source.set(normalized_rel, source_file.source)
}
}
///|
fn register_source_files_checked_into(
source_registry : Map[String, String],
module_paths : Map[String, String],
module_candidates : Map[String, Array[String]],
files : Array[WgslSourceFile],
diagnostics : Array[WgslDiagnostic],
) -> Unit {
let existing_rel_to_source = copy_wgsl_source_registry_map(source_registry)
analyze_source_files_against(existing_rel_to_source, files, diagnostics)
if wgsl_diagnostics_has_error(diagnostics) {
return
}
register_source_files_into(
source_registry, module_paths, module_candidates, files,
)
}
///|
fn register_source_files_into(
source_registry : Map[String, String],
module_paths : Map[String, String],
module_candidates : Map[String, Array[String]],
files : Array[WgslSourceFile],
) -> Unit {
for file in files {
ignore(
register_source_into(
source_registry,
module_paths,
module_candidates,
file.rel_path,
file.source,
None,
),
)
}
}
///|
fn registered_source_from_registry(
source_registry : Map[String, String],
rel_path : String,
) -> String? {
let normalized_rel = normalize_shader_rel_path(rel_path)
if normalized_rel == "" {
return None
}
source_registry.get(normalized_rel)
}