-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathtopsort.star
95 lines (81 loc) · 2.46 KB
/
topsort.star
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
topsort is package{
type topDef of (o,t) where equality over t and equality over o is topDef{
orig has type o
definitions has type set of t
references has type set of t
}
topological has type for all o,t such that
(list of topDef of (o,t))=>list of list of topDef of (o,t) where pPrint over t and pPrint over o
fun topological(definitions) is let{
type defEntry is dE{
df has type topDef of (o,t)
stackRef has type ref option of integer
}
var stack := list of []
def defs is list of { all dE{ df = d; stackRef := none} where d in definitions }
var groups := list of []
def index is buildIndex(defs)
analyseDef has type (defEntry)=>integer
fun analyseDef(D) is valof {
def low is push(D)
def point is analyseRefs(D.df.references,low)
if point = low then { -- we have a group
var group := list of []
while stack matches [Top,..Rest] and Top.stackRef has value off and off>= point do {
group := [Top.df,..group]
stack := Rest
}
if not isEmpty(group) then
groups := [groups..,group]
}
valis point
}
fun sort() is valof{
for D in defs do {
if D.stackRef=none then
ignore analyseDef(D)
}
valis groups
}
fun analyseRefs(refs,point) is valof {
var low := point
for rf in refs do {
low := minPoint(low,analyse(rf,low))
}
valis low
}
fun analyse(rf,low) is valof{
for D in stack do {
if rf in D.df.definitions and D.stackRef has value R then
valis minPoint(R,low)
}
if findDef(rf) has value df then
valis minPoint(low,analyseDef(df))
else
valis low
}
fun minPoint(x,y) where x=<y is x
| minPoint(_,y) default is y
fun push(D) is valof{
def count is size(stack)
D.stackRef := some(count)
stack := [D,..stack]
valis count
}
buildIndex has type (list of defEntry)=>dictionary of (t,list of defEntry)
fun buildIndex(Defs) is valof{
var Index := dictionary of []
for Ix->D in Defs do {
for d in D.df.definitions do {
if Index[d] has value links then
Index[d] := [D,..links]
else
Index[d] := [D]
}
}
valis Index
}
fun findDef(Ky) where index[Ky] has value L and D in L and D.stackRef=none is some(D)
| findDef(_) default is none
} in sort()
}