1/*********************************************************************** 2 * Chapel implementation of "99 bottles of beer" 3 * 4 * by Brad Chamberlain and Steve Deitz 5 * 07/13/2006 in Knoxville airport while waiting for flight home from 6 * HPLS workshop 7 * compiles and runs with chpl compiler version 1.12.0 8 * for more information, contact: chapel_info@cray.com 9 * 10 * 11 * Notes: 12 * o as in all good parallel computations, boundary conditions 13 * constitute the vast bulk of complexity in this code (invite Brad to 14 * tell you about his zany boundary condition simplification scheme) 15 * o uses type inference for variables, arguments 16 * o relies on integer->string coercions 17 * o uses named argument passing (for documentation purposes only) 18 ***********************************************************************/ 19 20// allow executable command-line specification of number of bottles 21// (e.g., ./a.out -snumBottles=999999) 22config const numBottles = 99; 23const numVerses = numBottles+1; 24 25// a domain to describe the space of lyrics 26var LyricsSpace: domain(1) = {1..numVerses}; 27 28// array of lyrics 29var Lyrics: [LyricsSpace] string; 30 31// parallel computation of lyrics array 32[verse in LyricsSpace] Lyrics(verse) = computeLyric(verse); 33 34// as in any good parallel language, I/O to stdout is serialized. 35// (Note that I/O to a file could be parallelized using a parallel 36// prefix computation on the verse strings' lengths with file seeking) 37writeln(Lyrics); 38 39 40// HELPER FUNCTIONS: 41 42proc computeLyric(verseNum) { 43 var bottleNum = numBottles - (verseNum - 1); 44 var nextBottle = (bottleNum + numVerses - 1)%numVerses; 45 return "\n" // disguise space used to separate elements in array I/O 46 + describeBottles(bottleNum, startOfVerse=true) + " on the wall, " 47 + describeBottles(bottleNum) + ".\n" 48 + computeAction(bottleNum) 49 + describeBottles(nextBottle) + " on the wall.\n"; 50} 51 52 53proc describeBottles(bottleNum, startOfVerse:bool = false) { 54 // NOTE: bool should not be necessary here (^^^^); working around bug 55 var bottleDescription = if (bottleNum) then bottleNum:string 56 else (if startOfVerse then "N" 57 else "n") 58 + "o more"; 59 return bottleDescription 60 + " bottle" + (if (bottleNum == 1) then "" else "s") 61 + " of beer"; 62} 63 64 65proc computeAction(bottleNum) { 66 return if (bottleNum == 0) then "Go to the store and buy some more, " 67 else "Take one down and pass it around, "; 68} 69 70 71// Modules... 72module M1 { 73 var x = 10; 74 75 var y = 13.0; 76} 77 78module M2 { 79 use M1 except y; 80 use M1 only y; 81 proc main() { 82 writeln("M2 -> M1 -> x " + x); 83 } 84} 85 86 87// Classes, records, unions... 88const PI: real = 3.14159; 89 90record Point { 91 var x, y: real; 92} 93var p: Point; 94writeln("Distance from origin: " + sqrt(p.x ** 2 + p.y ** 2)); 95p = new Point(1.0, 2.0); 96writeln("Distance from origin: " + sqrt(p.x ** 2 + p.y ** 2)); 97 98class Circle { 99 var p: Point; 100 var r: real; 101} 102var c = new Circle(r=2.0); 103proc Circle.area() 104 return PI * r ** 2; 105writeln("Area of circle: " + c.area()); 106 107class Oval: Circle { 108 var r2: real; 109} 110proc Oval.area() 111 return PI * r * r2; 112 113delete c; 114c = nil; 115c = new Oval(r=1.0, r2=2.0); 116writeln("Area of oval: " + c.area()); 117 118// This is a valid decimal integer: 119var x = 0000000000012; 120 121union U { 122 var i: int; 123 var r: real; 124} 125 126// chapel ranges are awesome. 127var r1 = 1..10, // 1 2 3 4 5 6 7 8 9 10 128 r2 = 10..1, // no values in this range 129 r3 = 1..10 by -1, // 10 9 8 7 6 5 4 3 2 1 130 r4 = 1..10 by 2, // 1 3 5 7 9 131 r5 = 1..10 by 2 align 0, // 2 4 6 8 10 132 r6 = 1..10 by 2 align 2, // 2 4 6 8 10 133 r7 = 1..10 # 3, // 1 2 3 134 r8 = 1..10 # -2, // 9 10 135 r9 = 1..100 # 10 by 2, // 1 3 5 7 9 136 ra = 1..100 by 2 # 10, // 1 3 5 7 9 11 13 15 17 19 137 rb = 1.. # 100 by 10; // 1 11 21 31 41 51 61 71 81 91 138 139// create a variable with default initialization 140var myVarWithoutInit: real = noinit; 141myVarWithoutInit = 1.0; 142 143// Chapel has <~> operator for read and write I/O operations. 144class IntPair { 145 var x: int; 146 var y: int; 147 proc readWriteThis(f) { 148 f <~> x <~> new ioLiteral(",") <~> y <~> new ioNewline(); 149 } 150} 151var ip = new IntPair(17,2); 152write(ip); 153 154var targetDom = {1..10}, 155 target: [targetDom] int; 156coforall i in targetDom with (ref target) { 157 target[i] = i ** 3; 158} 159 160var wideOpen = 0o777, 161 mememe = 0o600, 162 clique_y = 0O660, 163 zeroOct = 0o0, 164 minPosOct = 0O1; 165 166private module M3 { 167 private proc foo() { 168 169 } 170 171 private iter bar() { 172 for i in 1..10 { 173 yield i; 174 } 175 } 176 177 private var x: int; 178 179} 180prototype module X { 181 182 proc f() throws { 183 throw new Error(); 184 } 185 186 proc g() { 187 try { 188 f(); 189 try! f(); 190 } catch e { 191 writeln("Caught ", e); 192 } 193 } 194 195 proc int.add() { } 196 197 g(); 198 199 override proc test() throws { 200 var a = new borrowed IntPair(); 201 var b = new owned IntPair(); 202 var c = new shared IntPair(); 203 throw new unmanaged Error(); 204 } 205} 206 207