VertexRank:
PUBLIC
PROC [v: Vertex, d: DirectedDirection]
RETURNS [rank:
INT] = {
ra: REF ANY = Asserting.FnVal[ranks[d], v.GetVertexOther[]];
rank ←
WITH ra
SELECT
FROM
x: REF INT => x^,
ENDCASE => notRanked;
};
SetRank:
PROC [v: Vertex, d: DirectedDirection, rank:
INT] = {
Update:
PROC [old: Asserting.Assertions]
RETURNS [new: Asserting.Assertions] = {
new ← Asserting.AssertFn1[fn: ranks[d], val: NEW [INT ← rank], inAdditionTo: old, mayMute: TRUE]};
v.ChangeVertexOther[Update];
};
GraphRanked:
PUBLIC
PROC [g: Graph, d: DirectedDirection]
RETURNS [
BOOL] = {
RETURN [Asserting.FnVal[ranks[d], g.GetGraphOther[]] = $TRUE];
};
RankGraph:
PUBLIC
PROC [g: Graph, d: DirectedDirection] = {
filter: DirectionFilter = Only[d];
ClearRank: PROC [v: Vertex] = {SetRank[v, d, notRanked]};
EnsureRanked:
PROC [v: Vertex] = {
rank: INT ← 0;
RankProvider:
PROC [edge: Edge, direction: Direction, otherSide: Vertex] = {
w: Vertex = otherSide;
IF VertexRank[w, d] = ranking THEN ERROR--discovered cycle in graph--;
EnsureRanked[w];
rank ← MAX[rank, VertexRank[w, d]+1];
};
IF VertexRank[v, d] # notRanked THEN RETURN;
rank ← 0;
SetRank[v, d, ranking];
Expand[v, RankProvider, filter];
SetRank[v, d, rank]
};
SetRanked: PROC [old: Asserting.Assertions] RETURNS [new: Asserting.Assertions] = {new ← Asserting.AssertFn1[fn: ranks[d], val: $TRUE, inAdditionTo: old, mayMute: TRUE]};
EnumerateVertices[g, ClearRank];
EnumerateVertices[g, EnsureRanked];
g.ChangeGraphOther[SetRanked];
};
notRanked: INT = FIRST[INT];
ranking: INT = notRanked+1;