///|
fn Resolver::validate_interface_cycles(
self : Resolver,
) -> Unit raise ParseError {
let states = Array::make(self.iface_builders.length(), 0)
for id in 0.. Unit raise ParseError {
if states[id] == 2 {
return
}
if states[id] == 1 {
raise ParseError::Message("cyclic interface dependency", 0)
}
states[id] = 1
for dep in self.iface_builders[id].uses {
self.visit_interface_dependency(dep, states)
}
states[id] = 2
}
///|
fn Resolver::add_dependency_import(
self : Resolver,
world : RWorld,
id : Int32,
allow_export : Bool,
seen : Array[Bool],
) -> Unit {
if seen[id] {
return
}
seen[id] = true
for dep in self.iface_builders[id].uses {
self.add_dependency_import(world, dep, allow_export, seen)
}
let key = "interface-" + id.to_string()
if allow_export && world.exports.contains(key) {
return
}
if !world.imports.contains(key) {
world.imports.set(
key,
Interface({ id, external_id: None, attributes: Attributes::empty(), }),
)
}
}
///|
fn Resolver::import_type_owners(
self : Resolver,
world : RWorld,
ty : RType,
seen : Array[Bool],
) -> Unit {
if ty is Id(id) {
if seen[id] {
return
}
seen[id] = true
let def = self.types[id]
if def.owner is Interface(owner) {
self.add_dependency_import(
world,
owner,
false,
Array::make(self.iface_builders.length(), false),
)
}
for ty in type_children(def.kind) {
self.import_type_owners(world, ty, seen)
}
}
}
///|
fn Resolver::complete_world_dependencies(self : Resolver) -> Unit {
for world in self.worlds {
// Snapshot explicit items before adding the transitive closure.
let imports = world.imports.values().to_array()
let exports = world.exports.values().to_array()
for item in imports {
match item {
Interface(iface_ref) =>
for dep in self.iface_builders[iface_ref.id].uses {
self.add_dependency_import(
world,
dep,
false,
Array::make(self.iface_builders.length(), false),
)
}
Type(id) =>
self.import_type_owners(
world,
Id(id),
Array::make(self.types.length(), false),
)
Function(func) => {
for (_, ty) in func.params {
self.import_type_owners(
world,
ty,
Array::make(self.types.length(), false),
)
}
if func.result is Some(ty) {
self.import_type_owners(
world,
ty,
Array::make(self.types.length(), false),
)
}
}
}
}
for item in exports {
match item {
Interface(iface_ref) =>
for dep in self.iface_builders[iface_ref.id].uses {
self.add_dependency_import(
world,
dep,
true,
Array::make(self.iface_builders.length(), false),
)
}
Function(func) => {
for (_, ty) in func.params {
self.import_type_owners(
world,
ty,
Array::make(self.types.length(), false),
)
}
if func.result is Some(ty) {
self.import_type_owners(
world,
ty,
Array::make(self.types.length(), false),
)
}
}
Type(id) =>
self.import_type_owners(
world,
Id(id),
Array::make(self.types.length(), false),
)
}
}
}
}