# # D E F I N E D C O N T R O L O P E R A T I O N S # # This program illustrates how programmer-control operations can be # implemented in Icon using co-expressions and the p{ ... } # syntax that facilitates their use. procedure main() if not(&features == "co-expressions") then stop("co-expressions not supported") write(Seqimage{1 to 10}) write(Seqimage{&fail}) write(Seqimage{(1 to 10 by 2) | (10 to 1 by -2)}) write(Seqimage{!"abc" || !"xy"}) write(Seqimage{Seqimage | main}) every write(Galt{1 to 10,!"abcd",1 to 10}) write(Seqimage{star("abc") \ 10}) write(Seqimage{1 to 50,5}) write("---") every write(Limit{1 to 100,3}) write("---") every write(Ranseq{!"abcd",1 to 10}) every Parallel{|write,!"abcd",1 to 10} every Allpar{|write,!"abcd",1 to 10} \ 20 every Rotate{|write,!"abcd",1 to 10} \ 20 end procedure star(s) suspend "" | (star(s) || !s) end procedure Galt(a) local e every e := !a do suspend |@e end procedure Limit(a) local i, x while i := @a[2] do { a[1] := ^a[1] every 1 to i do if x := @a[1] then suspend x else break } end procedure Ranseq(a) local x while x := @?a do suspend x end procedure Seqimage(L) local s s := "" while s ||:= ", " || image(@L[1]) return "{" || s[3:0] || "}" | "{}" end procedure Allpar(a) local i, x, done x := list(*a) done := list(*a,1) every i := 1 to *a do x[i] := @a[i] | fail repeat { suspend Call(x) every i := 1 to *a do if done[i] = 1 then ((x[i] := @a[i]) | (done[i] := 0)) if not(!done = 1) then fail } end procedure Call(a) suspend case *a of { 1 : a[1]() 2 : a[1](a[2]) 3 : a[1](a[2],a[3]) 4 : a[1](a[2],a[3],a[4]) 5 : a[1](a[2],a[3],a[4],a[5]) 6 : a[1](a[2],a[3],a[4],a[5],a[6]) 7 : a[1](a[2],a[3],a[4],a[5],a[6],a[7]) 8 : a[1](a[2],a[3],a[4],a[5],a[6],a[7],a[8]) 9 : a[1](a[2],a[3],a[4],a[5],a[6],a[7],a[8],a[9]) 10 : a[1](a[2],a[3],a[4],a[5],a[6],a[7],a[8],a[9],a[10]) default : stop("Call : too many args.") } end procedure Extract(a) local i, j, n, x x := list(*a/2) repeat { i := 1 while i < *a do { n := @a[i] | fail every 1 to n do x[(i + 1)/2] := @a[i + 1] | fail a[i + 1] := ^a[i + 1] i +:= 2 } suspend Call(x) } end procedure Lifo(a) local i, x, ptr x := list(*a) ptr := 1 repeat { repeat if x[ptr] := @a[ptr] then { ptr +:= 1 (a[ptr] := ^a[ptr]) | break } else if (ptr -:= 1) = 0 then fail suspend Call(x) ptr := *a } end procedure Parallel(a) local i, x x := list(*a) repeat { every i := 1 to *a do x[i] := @a[i] | fail suspend Call(x) } end procedure Reverse(a) local i, x, ptr x := list(*a) ptr := *a repeat { repeat if x[ptr] := @a[ptr] then { ptr -:= 1 (a[ptr] := ^a[ptr]) | break } else if (ptr +:= 1) > *a then fail suspend Call(x) ptr := 1 } end procedure Rotate(a) local i, x, done x := list(*a) done := list(*a,1) every i := 1 to *a do x[i] := @a[i] | fail repeat { suspend Call(x) every i := 1 to *a do if not(x[i] := @a[i]) then { done[i] := 0 if !done = 1 then { a[i] := ^a[i] x[i] := @a[i] | fail } else fail } } end procedure Simple(a) local i, x x := list(*a) every i := 1 to *a do x[i] := @a[i] | fail return Call(x) end