idlize
121 строка · 4.3 Кб
1/*
2* Copyright (c) 2024 Huawei Device Co., Ltd.
3* Licensed under the Apache License, Version 2.0 (the "License");
4* you may not use this file except in compliance with the License.
5* You may obtain a copy of the License at
6*
7* http://www.apache.org/licenses/LICENSE-2.0
8*
9* Unless required by applicable law or agreed to in writing, software
10* distributed under the License is distributed on an "AS IS" BASIS,
11* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12* See the License for the specific language governing permissions and
13* limitations under the License.
14*/
15
16import { DeclarationTable, DeclarationTarget, PointerType } from "./DeclarationTable";
17
18export class DependencySorter {
19deps = new Set<DeclarationTarget>()
20
21constructor(private table: DeclarationTable) {
22}
23
24private fillDepsInDepth(target: DeclarationTarget, seen: Set<DeclarationTarget>) {
25if (seen.has(target)) return
26seen.add(target)
27// Need to request that declaration.
28this.deps.add(target)
29let struct = this.table.targetStruct(target)
30struct.supers.forEach(it => this.fillDepsInDepth(it, seen))
31struct.getFields().forEach(it => this.fillDepsInDepth(it.declaration, seen))
32struct.deps.forEach(dep => this.fillDepsInDepth(dep, seen))
33if (target instanceof PointerType)
34this.fillDepsInDepth(target.pointed, seen)
35}
36
37private getDeps(target: DeclarationTarget): DeclarationTarget[] {
38let result: DeclarationTarget[] = []
39let struct = this.table.targetStruct(target)
40struct.supers.forEach(it => result.push(it))
41struct.getFields().forEach(it => {
42result.push(it.declaration)
43})
44struct.deps.forEach(it => result.push(it))
45return result
46}
47
48addDep(declaration: DeclarationTarget) {
49let seen = new Set<DeclarationTarget>()
50this.deps.add(declaration)
51this.fillDepsInDepth(declaration, seen)
52// if (seen.size > 0) console.log(`${name}: depends on ${Array.from(seen.keys()).join(",")}`)
53}
54
55// Kahn's algorithm.
56getToposorted(): DeclarationTarget[] {
57let result: DeclarationTarget[] = []
58let input = Array.from(this.deps)
59let adjMap = new Map<DeclarationTarget, DeclarationTarget[]>()
60for (let key of input) {
61adjMap.set(key, this.getDeps(key))
62}
63let count = 0
64// Build adj map.
65let inDegree = new Map<DeclarationTarget, number>()
66for (let k of input) {
67let array: DeclarationTarget[] = []
68inDegree.set(k, 0)
69adjMap.get(k)?.forEach(it => {
70array.push(it)
71})
72count++
73}
74// Compute in-degrees.
75for (let k of input) {
76for (let it of adjMap.get(k)!) {
77let old = inDegree.get(it)
78if (old == undefined) {
79// throw new Error(`Forgotten type: ${it} of ${k}`)
80old = 0
81}
82inDegree.set(it, old + 1)
83}
84}
85let queue: DeclarationTarget[] = []
86// Insert elements with in-degree 0
87for (let k of input) {
88if (inDegree.get(k)! == 0) {
89queue.push(k)
90}
91}
92// Add all elements with 0
93while (queue.length > 0) {
94let e = queue.shift()!
95result.unshift(e)
96let kids = adjMap.get(e)
97if (kids != undefined) {
98for (let it of kids) {
99let old = inDegree.get(it)! - 1
100inDegree.set(it, old)
101if (old == 0) {
102queue.push(it)
103}
104}
105}
106}
107
108if (result.length < input.length) {
109let cycle = []
110for (let it of input) {
111if (!result.includes(it)) {
112cycle.push(it)
113}
114}
115console.log(`CYCLE:\n${cycle.map(it => `${this.table.computeTargetName(it, false)}: ${adjMap.get(it)?.map(it => this.table.computeTargetName(it, false)).join(",")}`).join("\n")}`)
116throw new Error("cycle detected")
117}
118// console.log("DEPS", result.map(it => this.table.computeTargetName(it, false)).join(","))
119return result
120}
121}