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