///|
priv struct WgslComposeIrSymbol {
identity : WgslComposeSymbolIdentity
final_name : String
declared : Bool
}
///|
priv struct WgslComposeIrReferenceBinding {
binding : WgslComposeBinding
target : WgslComposeIrSymbol
}
///|
priv struct WgslComposeIrSymbolKey {
text : String
}
///|
priv struct WgslComposeIrIdentityKey {
text : String
}
///|
priv struct WgslComposeSemanticIr {
declared_names : @set.Set[String]
reference_path_keys : @set.Set[String]
symbol_keys : @set.Set[String]
symbols : Array[WgslComposeIrSymbol]
emitted_final_name_by_identity : Map[String, String]
reference_bindings : Array[WgslComposeIrReferenceBinding]
}
///|
fn WgslComposeIrSymbolKey::WgslComposeIrSymbolKey(
identity : WgslComposeSymbolIdentity,
final_name : String,
declared : Bool,
) -> WgslComposeIrSymbolKey {
{ text: "\{identity.key()}|\{final_name}|\{declared}", }
}
///|
fn WgslComposeIrSymbolKey::text(self : WgslComposeIrSymbolKey) -> String {
self.text
}
///|
fn WgslComposeIrIdentityKey::WgslComposeIrIdentityKey(
identity : WgslComposeSymbolIdentity,
) -> WgslComposeIrIdentityKey {
{ text: identity.key(), }
}
///|
fn WgslComposeIrIdentityKey::text(self : WgslComposeIrIdentityKey) -> String {
self.text
}
///|
fn WgslComposeSemanticIr::WgslComposeSemanticIr() -> WgslComposeSemanticIr {
{
declared_names: Set([]),
reference_path_keys: Set([]),
symbol_keys: Set([]),
symbols: [],
emitted_final_name_by_identity: Map([]),
reference_bindings: [],
}
}
///|
fn WgslComposeSemanticIr::record_declared_name(
self : WgslComposeSemanticIr,
name : String,
) -> Unit {
let name = name.trim().to_owned()
if name != "" {
self.declared_names.add(name)
}
}
///|
fn WgslComposeSemanticIr::record_reference_path(
self : WgslComposeSemanticIr,
path : WgslReferencePath,
) -> Unit {
if path.segments().length() > 0 {
self.reference_path_keys.add(path.text())
}
}
///|
fn WgslComposeSemanticIr::record_symbol(
self : WgslComposeSemanticIr,
identity : WgslComposeSymbolIdentity,
final_name : String,
declared : Bool,
) -> Unit {
let final_name = final_name.trim().to_owned()
if final_name == "" {
return
}
let symbol_key = WgslComposeIrSymbolKey(identity, final_name, declared).text()
if self.symbol_keys.contains(symbol_key) {
return
}
self.symbol_keys.add(symbol_key)
self.symbols.push({ identity, final_name, declared, })
}
///|
fn WgslComposeSemanticIr::record_emitted_symbol_target(
self : WgslComposeSemanticIr,
binding : WgslComposeBinding,
) -> Unit {
let final_name = binding.target.final_name.trim().to_owned()
if final_name == "" || !self.declared_names.contains(final_name) {
return
}
let identity = binding.target.identity
self.record_symbol(identity, final_name, true)
let identity_key = binding.target.identity_key
if !self.emitted_final_name_by_identity.contains(identity_key) {
self.emitted_final_name_by_identity.set(identity_key, final_name)
}
}
///|
fn WgslComposeSemanticIr::resolved_binding_target_symbol(
self : WgslComposeSemanticIr,
binding : WgslComposeBinding,
) -> WgslComposeIrSymbol {
let requested_final_name = binding.target.final_name.trim().to_owned()
if requested_final_name == "" ||
self.declared_names.contains(requested_final_name) {
return {
identity: binding.target.identity,
final_name: requested_final_name,
declared: self.declared_names.contains(requested_final_name),
}
}
let identity_key = binding.target.identity_key
match self.emitted_final_name_by_identity.get(identity_key) {
Some(emitted_name) =>
{
identity: binding.target.identity,
final_name: emitted_name,
declared: true,
}
None =>
{
identity: binding.target.identity,
final_name: requested_final_name,
declared: false,
}
}
}
///|
fn WgslComposeSemanticIr::record_reference_binding(
self : WgslComposeSemanticIr,
binding : WgslComposeBinding,
) -> Unit {
let target = self.resolved_binding_target_symbol(binding)
self.record_symbol(target.identity, target.final_name, target.declared)
self.reference_bindings.push({ binding, target, })
}
///|
fn WgslComposeSemanticIr::from_facts_and_bindings(
facts : WgslComposeSemanticFacts,
bindings : WgslComposeBindingSet,
) -> WgslComposeSemanticIr {
let ir = WgslComposeSemanticIr()
for declaration in facts.declarations {
ir.record_declared_name(declaration)
}
for reference in facts.references {
ir.record_reference_path(reference)
}
for binding in bindings.bindings {
ir.record_emitted_symbol_target(binding)
}
for binding in bindings.bindings {
ir.record_reference_binding(binding)
}
ir
}
///|
fn WgslComposeSemanticIr::binding_is_referenced(
self : WgslComposeSemanticIr,
binding : WgslComposeBinding,
) -> Bool {
self.reference_path_keys.contains(binding.reference_path.text())
}
///|
fn WgslComposeSemanticIr::symbol_target_is_declared(
self : WgslComposeSemanticIr,
identity : WgslComposeSymbolIdentity,
final_name : String,
) -> Bool {
let final_name = final_name.trim().to_owned()
if final_name == "" {
return false
}
let identity_key = WgslComposeIrIdentityKey(identity).text()
for symbol in self.symbols {
if WgslComposeIrIdentityKey(symbol.identity).text() == identity_key &&
symbol.final_name == final_name {
return symbol.declared
}
}
false
}
///|
fn WgslComposeSemanticIr::binding_target_is_declared(
self : WgslComposeSemanticIr,
binding : WgslComposeBinding,
final_name : String,
) -> Bool {
self.symbol_target_is_declared(binding.target.identity, final_name)
}
///|
fn WgslComposeSemanticIr::live_binding_plan(
self : WgslComposeSemanticIr,
) -> WgslLiveBindingPlan {
let plan = WgslLiveBindingPlan()
let seen_binding_keys : @set.Set[String] = Set([])
for ir_binding in self.reference_bindings {
let resolved_binding = if ir_binding.target.final_name ==
ir_binding.binding.target.final_name.trim().to_owned() {
ir_binding.binding
} else {
ir_binding.binding.with_target(
WgslComposeSymbolTarget(
ir_binding.target.identity,
ir_binding.target.final_name,
),
)
}
let binding_key = resolved_binding.key
if seen_binding_keys.contains(binding_key) {
continue
}
seen_binding_keys.add(binding_key)
if !self.binding_is_referenced(resolved_binding) {
continue
}
if ir_binding.target.final_name != "" &&
(
self.binding_target_is_declared(
resolved_binding,
ir_binding.target.final_name,
) ||
ir_binding.binding.scope == UnqualifiedItemBinding ||
ir_binding.binding.scope == QualifiedAliasBinding
) {
plan.push(
resolved_binding.to_live_binding(
WgslComposeSymbolTarget(
ir_binding.target.identity,
ir_binding.target.final_name,
),
),
)
}
}
plan
}