///|
fn wgsl_source_origin_kind_to_compose_declaration_kind(
kind : WgslSourceOriginKind,
) -> WgslComposeDeclarationKind? {
match kind {
Type => Some(Type)
Constant => Some(Constant)
Override => Some(Override)
GlobalVariable => Some(GlobalVariable)
Function => Some(Function)
Other => None
}
}
///|
fn wgsl_compare_import_arena_symbols_by_dependency_pull(
lhs : WgslComposeImportArenaSymbol,
rhs : WgslComposeImportArenaSymbol,
) -> Int32 {
let lhs_pull = lhs.source_order_rank()
let rhs_pull = rhs.source_order_rank()
if lhs_pull >= 0 && rhs_pull >= 0 && lhs_pull != rhs_pull {
return lhs_pull - rhs_pull
}
let lhs_decl = lhs.source_decl_rank()
let rhs_decl = rhs.source_decl_rank()
if lhs_pull >= 0 && rhs_pull >= 0 && lhs_decl != rhs_decl {
return lhs_decl - rhs_decl
}
if lhs_pull >= 0 && rhs_decl >= 0 && lhs_pull != rhs_decl {
return lhs_pull - rhs_decl
}
if rhs_pull >= 0 && lhs_decl >= 0 && lhs_decl != rhs_pull {
return lhs_decl - rhs_pull
}
0
}
///|
fn Composer::compose_wgsl_import_requests(
self : Composer,
current_rel_path : String,
requests : Array[WgslImportRequest],
importer : WgslPreparedComposeSource,
bindings : WgslComposeBindingSet,
session : WgslComposeSession,
importer_defs : WgslActiveComposeDefs,
alias_prefixes : Array[String],
) -> String raise ComposerError {
let merged = StringBuilder()
record_wgsl_import_request_batch_link_edges(
session.link_graph,
current_rel_path,
requests,
)
let importer_facts = importer.active_semantic_facts(session)
for request in requests {
if !session.graph_request_is_planned(current_rel_path, request) {
session.record_graph_planned_request(current_rel_path, request)
}
let request_alias_prefixes = alias_prefixes.copy()
if request.alias_name != "" {
request_alias_prefixes.push(
wgsl_semantic_import_alias_prefix(request.alias_name),
)
}
let request_alias_scope = request_alias_prefixes.join("__")
let full_module_key = wgsl_full_module_visit_key(request.rel_path, "")
if wgsl_path_stack_contains(session.active_rel_paths, request.rel_path) {
raise ImportCycle(
wgsl_import_cycle_string(session.active_rel_paths, request.rel_path),
)
}
if request.import_full_module {
if session.visited.contains(full_module_key) {
collect_wgsl_cached_import_bindings(
session,
request.rel_path,
request.alias_name,
request_alias_scope,
bindings,
)
|> ignore
continue
}
}
let emission_requested_items : Array[String] = []
if !request.import_full_module && request.alias_name == "" {
for requested_item in request.requested_items {
match
find_wgsl_visible_alias_imported_item_binding(
bindings,
request.module_path,
requested_item,
) {
Some(binding) =>
push_wgsl_unqualified_import_binding_respecting_locals(
bindings, binding,
)
None =>
match
find_wgsl_visible_identity_imported_item_binding(
bindings,
request.rel_path,
requested_item,
) {
Some(binding) =>
push_wgsl_unqualified_import_binding_respecting_locals(
bindings, binding,
)
None =>
match
find_wgsl_cached_imported_item_name(
session,
request.rel_path,
requested_item,
) {
Some(imported_name) =>
match
WgslComposeBinding::for_unqualified_symbol(
request.rel_path,
requested_item,
imported_name,
UnqualifiedItemBinding,
) {
Some(binding) => {
push_wgsl_unqualified_import_binding_respecting_locals(
bindings, binding,
)
if !session.visited.contains(
wgsl_imported_item_emission_key(
request.rel_path,
requested_item,
),
) &&
!session.visited.contains(full_module_key) {
emission_requested_items.push(requested_item)
}
}
None => emission_requested_items.push(requested_item)
}
None => emission_requested_items.push(requested_item)
}
}
}
}
if request.requested_items.length() > 0 &&
emission_requested_items.length() == 0 {
continue
}
} else if !request.import_full_module {
for requested_item in request.requested_items {
match
find_wgsl_cached_imported_item_name(
session,
request.rel_path,
requested_item,
) {
Some(imported_name) =>
match
WgslComposeBinding::for_alias_symbol(
request.rel_path,
request.alias_name,
requested_item,
imported_name,
QualifiedAliasBinding,
) {
Some(binding) => {
bindings.push(binding)
if !session.visited.contains(
wgsl_imported_item_emission_key(
request.rel_path,
requested_item,
),
) &&
!session.visited.contains(full_module_key) {
emission_requested_items.push(requested_item)
}
}
None => emission_requested_items.push(requested_item)
}
None => emission_requested_items.push(requested_item)
}
}
if request.requested_items.length() > 0 &&
emission_requested_items.length() == 0 {
continue
}
} else {
for requested_item in request.requested_items {
emission_requested_items.push(requested_item)
}
}
let visit_key = wgsl_import_request_visit_key(current_rel_path, request)
if session.visited.contains(visit_key) {
continue
}
session.visited.add(visit_key)
let emitted_selected_items : Array[String] = []
let processed = self.processed_registered_wgsl_compose_module(
request.rel_path,
session,
Some(importer_defs),
)
session.record_processed_semantic_facts(processed)
let raw_source = processed.raw_source
let origin_start_index = session.symbols.source_origins.length()
let request_import_defs = processed.active_defs
let naga_pull_ranks = processed.naga_dependency_pull_ranks()
let source_decl_ranks = processed.declaration_source_ranks()
session.active_rel_paths.push(request.rel_path)
let module_source = if request.import_full_module {
record_wgsl_planned_final_names_from_processed(
session,
request.rel_path,
Some(request.module_path),
request_alias_prefixes,
processed,
)
WgslComposeEmitter(self, session).emit_source_with_path(
request.rel_path,
raw_source,
Some(importer_defs),
bindings,
false,
true,
request_alias_prefixes,
true,
false,
)
} else {
let import_defs = request_import_defs
let prepared = processed.prepared
let extraction = processed.item_extraction(emission_requested_items)
let has_missing_local_fallback = record_wgsl_missing_item_local_import_final_names(
current_rel_path, request, importer_facts, emission_requested_items, extraction,
session,
)
let extracted_source = extraction.source()
if extracted_source == "" {
if has_missing_local_fallback {
self.compose_wgsl_missing_item_local_dependency_imports(
request.rel_path,
prepared,
session,
import_defs,
request_alias_prefixes,
)
} else {
""
}
} else {
for origin in extraction.origins() {
if origin.name() != "" {
composer_string_list_push_unique(
emitted_selected_items,
origin.name(),
)
}
}
record_wgsl_source_origins_from_extraction(
session,
request.rel_path,
extraction,
)
record_wgsl_planned_final_names_from_extraction(
session,
request.rel_path,
Some(request.module_path),
request_alias_prefixes,
extraction,
)
let requests = self.build_wgsl_import_requests_from_emitted_item_slice(
request.rel_path,
extracted_source,
prepared.active_source,
Some(extraction),
session,
import_defs,
)
let item_bindings = WgslComposeBindingSet()
seed_wgsl_local_declaration_bindings(
item_bindings, current_rel_path, importer_facts,
)
let extracted_prepared = prepare_active_wgsl_compose_source(
extracted_source, session,
)
let imported_prefix = self.compose_wgsl_import_requests(
request.rel_path,
requests,
extracted_prepared,
item_bindings,
session,
import_defs,
request_alias_prefixes,
)
let local_source = extracted_prepared.importless_source
let emitted_slice = imported_prefix +
finalize_wgsl_composed_source(
local_source, item_bindings, import_defs, session, false, false,
)
for binding in item_bindings.bindings {
let referenced_by_importer = importer_facts.contains_reference_path(
binding.reference_path.text(),
)
if referenced_by_importer {
push_wgsl_unqualified_import_binding_respecting_locals(
bindings, binding,
)
}
}
emitted_slice
}
}
session.active_rel_paths.pop() |> ignore
if module_source == "" {
continue
}
let final_name_plan = WgslFinalNameAllocator(
session, request_alias_prefixes,
).application_plan(origin_start_index)
let final_module_source = if !final_name_plan.is_empty() {
rewrite_wgsl_declarations_with_binding_plan(
module_source,
final_name_plan.reference_rewrite_plan(),
) catch {
error => raise composer_error_from_wgsl_parse_error(error)
}
} else {
module_source
}
final_name_plan.apply_to_origins(session.symbols.source_origins)
let event_generated_symbols : Array[WgslComposeImportArenaSymbol] = []
let event_item_names = if request.import_full_module {
let names : Array[String] = []
for i in origin_start_index.. {
let source_decl_rank = source_decl_ranks
.get(origin.source_symbol_name)
.unwrap_or(-1)
let source_pull_rank = naga_pull_ranks
.get(origin.source_symbol_name)
.unwrap_or(-1)
let source_order_rank = if emitted_source_starts.contains(
source_pull_rank,
) {
-1
} else {
source_pull_rank
}
event_generated_symbols.push(
WgslComposeImportArenaSymbol(
kind,
origin.source_symbol_name,
origin.generated_symbol_name,
source_decl_rank~,
source_order_rank~,
),
)
}
None => ()
}
}
}
wgsl_sort_import_arena_function_symbols_by_dependency_pull(
event_generated_symbols,
)
let event_kind = if request.import_full_module {
if request.alias_name == "" {
WgslComposeImportEdgeKind::FullModule
} else {
AliasModule
}
} else {
ItemBinding
}
session.link_graph.record_import_arena_event(
current_rel_path,
request.rel_path,
request.module_path,
request.alias_name,
event_item_names,
event_kind,
event_generated_symbols,
)
session.symbols.import_arena_events.push(
WgslComposeImportArenaEvent(
session.symbols.import_arena_events.length(),
current_rel_path,
request.rel_path,
request.module_path,
request.alias_name,
event_item_names,
event_kind,
event_generated_symbols,
),
)
if request.alias_name == "" {
for i in origin_start_index.. {
push_wgsl_unqualified_import_binding_respecting_locals(
bindings, binding,
)
session.record_local_spelling_final_name(
current_rel_path,
origin.rel_path,
origin.source_symbol_name,
origin.generated_symbol_name,
)
}
None => ()
}
}
}
if request.alias_name != "" {
for i in origin_start_index.. {
bindings.push(binding)
session.global_alias_bindings.push(binding)
}
None => ()
}
}
}
} else if !request.import_full_module {
for i in origin_start_index.. {
bindings.push(binding)
session.record_local_spelling_final_name(
current_rel_path,
origin.rel_path,
origin.source_symbol_name,
origin.generated_symbol_name,
)
}
None => ()
}
}
}
}
for i in origin_start_index.. Unit {
let functions : Array[WgslComposeImportArenaSymbol] = []
for symbol in symbols {
if symbol.kind() == Function {
functions.push(symbol)
}
}
functions.sort_by(wgsl_compare_import_arena_symbols_by_dependency_pull)
let mut next_function = 0
for i in 0.. Unit {
for name in facts.global_variable_names() {
if name == "" {
continue
}
match
WgslComposeBinding::for_unqualified_symbol(
rel_path,
name,
name,
UnqualifiedItemBinding,
) {
Some(binding) => bindings.push(binding)
None => ()
}
}
}
///|
fn push_wgsl_unqualified_import_binding_respecting_locals(
bindings : WgslComposeBindingSet,
binding : WgslComposeBinding,
) -> Unit {
let reference_name = binding.reference_path.text()
if binding.scope == UnqualifiedItemBinding &&
binding.target.final_name != reference_name &&
bindings.has_unqualified_reference_name(reference_name) {
return
}
bindings.push(binding)
}
///|
fn record_wgsl_missing_item_local_import_final_names(
current_rel_path : String,
request : WgslImportRequest,
importer_facts : WgslComposeSemanticFacts,
emission_requested_items : Array[String],
extraction : WgslModuleItemExtraction,
session : WgslComposeSession,
) -> Bool {
let mut recorded = false
for requested_item in emission_requested_items {
if wgsl_item_extraction_contains_requested_item(extraction, requested_item) {
continue
}
let declares_local = importer_facts.declares_name(requested_item)
if !declares_local {
continue
}
let references_local = importer_facts.contains_reference_path(
requested_item,
)
if !references_local {
continue
}
session.record_local_import_final_name(
current_rel_path,
requested_item,
wgsl_naga_oil_decorated_final_name(request.module_path, requested_item),
)
recorded = true
}
recorded
}
///|
fn Composer::compose_wgsl_missing_item_local_dependency_imports(
self : Composer,
current_rel_path : String,
dependency : WgslPreparedComposeSource,
session : WgslComposeSession,
importer_defs : WgslActiveComposeDefs,
alias_prefixes : Array[String],
) -> String raise ComposerError {
let targets : Array[WgslImportTarget] = []
collect_wgsl_import_targets_from_source_directives(
session,
dependency.active_source,
targets,
)
if targets.length() == 0 {
return ""
}
let dependency_requests = self.build_wgsl_import_requests_from_targets(
current_rel_path, targets, dependency, session, importer_defs, false,
)
let requests : Array[WgslImportRequest] = []
let dependency_facts = dependency.active_semantic_facts(session)
self.merge_wgsl_non_resource_dependency_requests(
requests, dependency_requests, dependency_facts, session, importer_defs,
)
if requests.length() == 0 {
return ""
}
self.compose_wgsl_import_requests(
current_rel_path,
requests,
dependency,
WgslComposeBindingSet(),
session,
importer_defs,
alias_prefixes,
)
}