|
|
1.1 ! root 1: { AN OPEN CHALLENGE TO ALL PASCAL COMPILERS: Compile this program ! 2: correctly and produce the correct output. ! 3: ! 4: Send responses, counter-challenges, etc., to: ! 5: Tom Pennello ! 6: Computer and Information Sciences ! 7: University of California ! 8: Santa Cruz, CA. 95064 ! 9: } ! 10: ! 11: program p(output); ! 12: type integer = -32767..32768; node = 0..4500; ! 13: var Debug: boolean; ! 14: ! 15: procedure EachUSCC( { of relation R } ! 16: { Pass in an iterator to generate the nodes to be searched, ! 17: the relation on the nodes, a procedure to do information ! 18: propagation when V R W is discovered, a procedure ! 19: to take each SCC found, and a procedure to yield each ! 20: node in the graph. ! 21: We require that the nodes be of a scalar type so that ! 22: an array may be indexed by them. Also passed in is the ! 23: upper bound of the node type. } ! 24: procedure EachUnode(procedure P(T:node)); { Yields each node in graph } ! 25: procedure EachUnodeUtoUsearch(procedure SearchU(V:node)); ! 26: procedure R(V:node; procedure DoUsuccessor(W:node)); ! 27: procedure Propagate(V,W:node); { called when V R W is discovered } ! 28: procedure TakeUSCC(Root:node; procedure Each(procedure P(T:node))); ! 29: LastUnode: integer ! 30: ); ! 31: ! 32: type ! 33: A = array[node] of integer; { range 0..Infinity (below) } ! 34: var N: ^A; SP: integer; ! 35: Stack: array[node {1..LastUnode}] of node; ! 36: Infinity: integer; { LastUnode+1 } ! 37: ! 38: procedure P(T:node); begin N^[T] := 0; end; ! 39: ! 40: procedure Search(V:node); ! 41: var I,T:integer; ! 42: procedure DoUsuccessor(W:node); ! 43: begin ! 44: Search(W); ! 45: if N^[W] < N^[V] then N^[V] := N^[W]; ! 46: Propagate(V,W); ! 47: end; ! 48: ! 49: { EachUmember is yielded by EachUSCC when an SCC has been found. } ! 50: procedure EachUmember(procedure P(TU:node)); ! 51: var I:integer; ! 52: begin { yield each member of current SCC } ! 53: for I := SP downto T do P(Stack[I]); ! 54: end; ! 55: ! 56: procedure YieldUSCC; ! 57: begin ! 58: if Debug then writeln('YieldUSCC passes',V,' to TakeUSCC'); ! 59: TakeUSCC(V,EachUmember); ! 60: end; ! 61: ! 62: begin ! 63: if N^[V] = 0 then begin { stack the node } ! 64: if Debug then writeln('stacking ',V); ! 65: SP := SP+1; ! 66: Stack[SP] := V; N^[V] := SP; ! 67: if Debug then writeln('Doing successors of ',V); ! 68: R(V,DoUsuccessor); ! 69: if Debug then writeln('Now checking if ',V,' is an SCC root'); ! 70: if V = Stack[N^[V]] then begin { V is root of an SCC } ! 71: T := N^[V]; ! 72: if Debug then writeln(V,' is an SCC root; SP=',SP,' T=',T); ! 73: for I := SP downto T do N^[Stack[I]] := Infinity; ! 74: if SP <> T then begin ! 75: if Debug then writeln('Yield SCC should pass ',V,' out to TakeUSCC'); ! 76: YieldUSCC; ! 77: end; ! 78: SP := T-1; ! 79: end; ! 80: end; ! 81: end; ! 82: begin ! 83: Infinity := LastUnode+1; ! 84: new(N); EachUnode(P); ! 85: SP := 0; ! 86: EachUnodeUtoUsearch(Search); ! 87: dispose(N); ! 88: end; ! 89: ! 90: procedure Outer; { needed to produce bug in Berkeley Pascal compiler } ! 91: procedure q; ! 92: procedure EachUnodeUtoUsearch(procedure Search(T:node)); ! 93: begin ! 94: Search(1); ! 95: end; ! 96: procedure EachUnode(procedure P(T:node)); ! 97: begin P(1); P(2); ! 98: end; ! 99: procedure R(V:node; procedure P(W:node)); ! 100: begin ! 101: { Defines graph with edges 1->2 and 2->1 } ! 102: { Thus, the graph contains one SCC: [1,2] } ! 103: case V of ! 104: 1: P(2); ! 105: 2: P(1); ! 106: end; ! 107: end; ! 108: procedure Propagate(V,W:node); begin end; ! 109: procedure TakeUSCC(Root:node; procedure Each(procedure P(T:node))); ! 110: procedure P(T:node); begin write(T); end; ! 111: begin ! 112: writeln('TakeUSCC receives V=',Root,' from YieldUSCC'); ! 113: writeln('The SCC''s constituents are:'); ! 114: Each(P); writeln; ! 115: end; ! 116: begin ! 117: EachUSCC(EachUnode,EachUnodeUtoUsearch,R,Propagate,TakeUSCC,2); ! 118: end; ! 119: ! 120: procedure Doit; ! 121: begin ! 122: q; ! 123: end; ! 124: ! 125: begin ! 126: Doit; ! 127: end; ! 128: ! 129: begin ! 130: Debug := true; ! 131: Outer; ! 132: end. ! 133: ! 134: {---------------------------------------------------------------- ! 135: An alternate version of this program, written in a language ! 136: supporting iterators, iterators as parameters, iterators ! 137: as yielded results of iterators, and the ability to yield more ! 138: than one thing, might be as follows: ! 139: ---------------------------------------------------------------- ! 140: ! 141: iterator EachUSCC( ! 142: iterator EachUnode:node; ! 143: iterator EachUnodeUtoUsearch:node; ! 144: iterator R(V:node):node; ! 145: procedure Propagate(V,W:node); ! 146: LastUnode:node ! 147: ): ! 148: (Root:node; iterator EachUnodeUinUSCC:node); ! 149: # EachUSCC yields two results: the Root of the SCC, ! 150: # and an iterator that yields each member of that SCC. ! 151: ! 152: type A = aray[node] of integer; ! 153: var N: ^A; SP: integer; ! 154: Stack: array[node] of node; ! 155: Infinity: integer; ! 156: ! 157: procedure Search(V); ! 158: var T: integer; ! 159: iterator EachUmember:node; ! 160: begin ! 161: for I := SP downto T do P(Stack[I]); ! 162: end; ! 163: begin ! 164: if N^[V] = 0 then begin ! 165: SP := SP+1; Stack[SP] := V; N^[V] := SP; ! 166: for W in R(V) do begin # Search successors of V. ! 167: Search(W); ! 168: if N^[W] < N^[V] then N^[V] := N^[W]; ! 169: Propagate(V,W); ! 170: end; ! 171: if V = Stack[N^[V]] then begin ! 172: T := N^[V]; # V is an SCC root. ! 173: for I := SP downto T do N^[Stack[I]] := Infinity; ! 174: if SP <> T then # Non-trivial SCC. ! 175: yield(V,EachUmember); ! 176: SP := T-1; ! 177: end; ! 178: end; ! 179: end; ! 180: ! 181: begin ! 182: Infinity := LastUnode+1; ! 183: new(N); ! 184: for T in EachUnode() do N^[T] := 0; # for loops declare their ! 185: SP := 0; # control variable as a constant. ! 186: for V in EachUnodeUtoUsearch() do Search(V); ! 187: dispose(N); ! 188: end; ! 189: ! 190: # Sample use of EachUSCC: ! 191: ! 192: iterator EachUnodeUtoUsearch:node; ! 193: begin ! 194: yield(1); ! 195: end; ! 196: iterator EachUnode:node; ! 197: begin ! 198: yield(1); yield(2); ! 199: end; ! 200: iterator R(V:node):node; ! 201: begin ! 202: if V = 1 then yield(2) else yield(1); ! 203: end; ! 204: procedure Propagate(V,W:node); begin end; ! 205: ! 206: procedure UseUEachUSCC; ! 207: begin ! 208: for (Root,EachUmember) in ! 209: EachUSCC(EachUnode,EachUnodeUtoUsearch,R,Propagate,TakeUSCC,2) do ! 210: begin ! 211: writeln('Root of received SCC is ',Root); ! 212: writeln('Constituents of the SCC are:'); ! 213: for I in EachUmember() do write(I); ! 214: writeln; ! 215: end; ! 216: end; ! 217: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.