Some rewriting, hopefully the last commit before pull request

This commit is contained in:
ian.bertolacci 2015-07-14 19:07:59 -07:00
parent 2e7ebaa3b9
commit 7640ea4a30

View File

@ -25,29 +25,30 @@ writeln( "World!" );
// each thing is printed right next to each other, so include your spacing! // each thing is printed right next to each other, so include your spacing!
writeln( "There are ", 3, " commas (\",\") in this line of code" ); writeln( "There are ", 3, " commas (\",\") in this line of code" );
// Different output channels // Different output channels
stdout.writeln( "This goes to standard output (just like plain writeln() does)"); stdout.writeln( "This goes to standard output (just like plain writeln( ) does)");
stderr.writeln( "This goes to standard error" ); stderr.writeln( "This goes to standard error" );
// Variables dont have to be explicitly typed as long as // Variables dont have to be explicitly typed as long as
// the compiler can figure out the type that it will hold. // the compiler can figure out the type that it will hold.
var myVar = 10; // 10 is an int, so myVar is implicitly an int var myVar = 10; // 10 is an int, so myVar is implicitly an int
myVar = -10; myVar = -10;
var mySecondVar = myVar;
// var anError; // this would be a compile time error. // var anError; // this would be a compile time error.
// We can (and should) explicitly type things // We can (and should) explicitly type things
var mySecondVar: real; // define mySecondVar as a real var myThirdVar: real; // define mySecondVar as a real
var myThirdVar: real = -1.234; var myFourthVar: real = -1.234;
mySecondVar = myThirdVar; myThirdVar = myFourthVar;
// There are a number of basic types. // There are a number of basic types.
var myInt: int = -1000; // signed ints var myInt: int = -1000; // Signed ints
var myUint: uint = 1234; // unsigned ints var myUint: uint = 1234; // Unsigned ints
var myReal: real = 9.876; // floating point numbers var myReal: real = 9.876; // Floating point numbers
var myImag: imag = 5.0i; // imaginary numbers var myImag: imag = 5.0i; // Imaginary numbers
var myCplx: complex = 10 + 9i; // complex numbers var myCplx: complex = 10 + 9i; // Complex numbers
myCplx = myInt + myImag ; // another way to form complex numbers myCplx = myInt + myImag ; // Another way to form complex numbers
var myBool: bool = false; // booleans var myBool: bool = false; // Booleans
var myStr: string = "Some string..."; // strings var myStr: string = "Some string..."; // Strings
// Some types can have sizes // Some types can have sizes
var my8Int: int(8) = 10; // 8 bit (one byte) sized int; var my8Int: int(8) = 10; // 8 bit (one byte) sized int;
@ -59,6 +60,7 @@ var intFromReal2: int = myReal : int;
// consts are constants, they cannot be changed after set in runtime // consts are constants, they cannot be changed after set in runtime
const almostPi: real = 22.0/7.0; const almostPi: real = 22.0/7.0;
// params are constants whose value must be known statically at compile time // params are constants whose value must be known statically at compile time
// Like consts, they cannot be changed during runtime // Like consts, they cannot be changed during runtime
param compileTimeConst: int = 16; param compileTimeConst: int = 16;
@ -68,47 +70,47 @@ param compileTimeConst: int = 16;
// config vars and consts can be changed through the command line at run time // config vars and consts can be changed through the command line at run time
config var varCmdLineArg: int = -123; config var varCmdLineArg: int = -123;
config const constCmdLineArg: int = 777; config const constCmdLineArg: int = 777;
// set with --VarName=Value or --VarName Value at run time // Set with --VarName=Value or --VarName Value at run time
// config params can be set at compile time // config params can be set at compile time
config param paramCmdLineArg: bool = false; config param paramCmdLineArg: bool = false;
writeln( varCmdLineArg, ", ", constCmdLineArg, ", ", paramCmdLineArg ); writeln( varCmdLineArg, ", ", constCmdLineArg, ", ", paramCmdLineArg );
//set config with --set paramCmdLineArg=value at compile time // Set config with --set paramCmdLineArg=value at compile time
// Math operators // Math operators
var a: int, thisInt = 1234, thatInt = 5678; var a: int, thisInt = 1234, thatInt = 5678;
a = thisInt + thatInt; // Addition a = thisInt + thatInt; // Addition
a = thisInt * thatInt; // Multiplication a = thisInt * thatInt; // Multiplication
a = thisInt - thatInt; // Subtraction a = thisInt - thatInt; // Subtraction
a = thisInt / thatInt; // division a = thisInt / thatInt; // Division
a = thisInt ** thatInt; // exponentiation a = thisInt ** thatInt; // Exponentiation
a = thisInt % thatInt; // remainder (modulo) a = thisInt % thatInt; // Remainder (modulo)
// Logical Operators // Logical Operators
var b: bool, thisBool = false, thatBool = true; var b: bool, thisBool = false, thatBool = true;
b = thisBool && thatBool; // logical and b = thisBool && thatBool; // Logical and
b = thisBool || thatBool; // logical or b = thisBool || thatBool; // Logical or
b = !thisBool; // logical negation b = !thisBool; // Logical negation
// Relational Operators // Relational Operators
b = thisInt > thatInt; // greater-than b = thisInt > thatInt; // Greater-than
b = thisInt >= thatInt; // greater-than-or-equal-to b = thisInt >= thatInt; // Greater-than-or-equal-to
b = thisInt < a && a <= thatInt; // less-than, and, less-than-or-equal-to b = thisInt < a && a <= thatInt; // Less-than, and, less-than-or-equal-to
b = thisInt != thatInt; // not-equal-to b = thisInt != thatInt; // Not-equal-to
b = thisInt == thatInt; // equal-to b = thisInt == thatInt; // Equal-to
// Bitwise operations // Bitwise operations
a = thisInt << 10; // left-bit-shift by 10 bits; a = thisInt << 10; // Left-bit-shift by 10 bits;
a = thatInt >> 5; // right-bit-shift by 5 bits; a = thatInt >> 5; // Right-bit-shift by 5 bits;
a = ~thisInt; // bitwise-negation a = ~thisInt; // Bitwise-negation
a = thisInt ^ thatInt; // bitwise exclusive-or a = thisInt ^ thatInt; // Bitwise exclusive-or
// Compound assignment operations // Compound assignment operations
a += thisInt; // addition-equals ( a = a + thisInt;) a += thisInt; // Addition-equals ( a = a + thisInt;)
a *= thatInt; // times-equals ( a = a * thatInt; ) a *= thatInt; // Times-equals ( a = a * thatInt; )
b &&= thatBool; // logical-and-equals ( b = b && thatBool; ) b &&= thatBool; // Logical-and-equals ( b = b && thatBool; )
a <<= 3; // left-bit-shift-equals ( a = a << 10; ) a <<= 3; // LEft-bit-shift-equals ( a = a << 10; )
// and so on... // and many, many more.
// Unlike other C family languages there are no // Unlike other C family languages there are no
// pre/post-increment/decrement operators like // pre/post-increment/decrement operators like
// ++j, --j, j++, j-- // ++j, --j, j++, j--
@ -119,8 +121,7 @@ var old_that = thatInt;
thisInt <=> thatInt; // Swap the values of thisInt and thatInt thisInt <=> thatInt; // Swap the values of thisInt and thatInt
writeln( (old_this == thatInt) && (old_that == thisInt) ); writeln( (old_this == thatInt) && (old_that == thisInt) );
// We can also define operator overloads, // Operator overloads can also be defined, as we'll see with procedures
// which we'll cover with procedures.
// Tuples can be of the same type // Tuples can be of the same type
var sameTup: 2*int = (10,-1); var sameTup: 2*int = (10,-1);
@ -128,25 +129,29 @@ var sameTup2 = (11, -6);
// or different types // or different types
var diffTup: (int,real,complex) = (5, 1.928, myCplx); var diffTup: (int,real,complex) = (5, 1.928, myCplx);
var diffTupe2 = ( 7, 5.64, 6.0+1.5i ); var diffTupe2 = ( 7, 5.64, 6.0+1.5i );
// Accessed using array bracket notation // Accessed using array bracket notation
// However, tuples are all 1-indexed // However, tuples are all 1-indexed
writeln( "(", sameTup[1], ",", sameTup[2], ")" ); writeln( "(", sameTup[1], ",", sameTup[2], ")" );
writeln( diffTup ); writeln( diffTup );
// Tuples can also be written into. // Tuples can also be written into.
diffTup[1] = -1; diffTup[1] = -1;
// Can expand tuple values into their own variables // Can expand tuple values into their own variables
var (tupInt, tupReal, tupCplx) = diffTup; var (tupInt, tupReal, tupCplx) = diffTup;
writeln( diffTup == (tupInt, tupReal, tupCplx) ); writeln( diffTup == (tupInt, tupReal, tupCplx) );
// Useful for writing a list of variables ( as is common in debugging) // Useful for writing a list of variables ( as is common in debugging)
writeln( (a,b,thisInt,thatInt,thisBool,thatBool) ); writeln( (a,b,thisInt,thatInt,thisBool,thatBool) );
// Type aliasing // Type aliasing
type chroma = int; // type of a single hue type chroma = int; // Type of a single hue
type RGBColor = 3*chroma; // type representing a full color type RGBColor = 3*chroma; // Type representing a full color
var black: RGBColor = ( 0,0,0 ); var black: RGBColor = ( 0,0,0 );
var white: RGBColor = ( 255, 255, 255 ); var white: RGBColor = ( 255, 255, 255 );
// if-then-else works just like any other C-family language // If-then-else works just like any other C-family language
if 10 < 100 then if 10 < 100 then
writeln( "All is well" ); writeln( "All is well" );
@ -193,16 +198,16 @@ select( inputOption ){
} }
} }
// While loops and Do-While loops are basically the same in every language. // While and Do-While loops are basically the same in every language.
var j: int = 1; var j: int = 1;
var jSum: int = 0; var jSum: int = 0;
while( j <= 1000 ){ while( j <= 1000 ){
jSum += j; jSum += j;
j += 1; // there are no ++j, --j, j++, j--, operators j += 1;
} }
writeln( jSum ); writeln( jSum );
// basic Do-While loop // Do-While loop
do{ do{
jSum += j; jSum += j;
j += 1; j += 1;
@ -213,7 +218,7 @@ writeln( jSum );
// Ranges themselves are types, and can be stuffed into variables // Ranges themselves are types, and can be stuffed into variables
// (more about that later) // (more about that later)
for i in 1..10 do write( i , ", ") ; for i in 1..10 do write( i , ", ") ;
writeln(); writeln( );
var iSum: int = 0; var iSum: int = 0;
for i in 1..1000 { for i in 1..1000 {
@ -225,7 +230,7 @@ for x in 1..10 {
for y in 1..10 { for y in 1..10 {
write( (x,y), "\t" ); write( (x,y), "\t" );
} }
writeln(); writeln( );
} }
// Ranges and Domains // Ranges and Domains
@ -238,14 +243,16 @@ for x in 1..10 {
var range1to10: range = 1..10; // 1, 2, 3, ..., 10 var range1to10: range = 1..10; // 1, 2, 3, ..., 10
var range2to11 = 2..11; // 2, 3, 4, ..., 11 var range2to11 = 2..11; // 2, 3, 4, ..., 11
var rangeThistoThat: range = thisInt..thatInt; // using variables var rangeThistoThat: range = thisInt..thatInt; // using variables
var rangeEmpty: range = 100..-100 ; // this is a valid, but empty range var rangeEmpty: range = 100..-100 ; // this is valid but contains no indices
//ranges can be unbounded // Ranges can be unbounded
var range1toInf: range(boundedType=BoundedRangeType.boundedLow) = 1.. ; // 1, 2, 3, 4, 5, ... var range1toInf: range(boundedType=BoundedRangeType.boundedLow) = 1.. ;
var rangeNegInfto1 = ..1; // ..., -4, -3, -2, -1, 0, 1 // 1, 2, 3, 4, 5, ...
// Note: the range(boundedType= ... ) is only // Note: the range(boundedType= ... ) is only
// necessary if we explicitly type the variable // necessary if we explicitly type the variable
var rangeNegInfto1 = ..1; // ..., -4, -3, -2, -1, 0, 1
// Ranges can be strided using the 'by' operator. // Ranges can be strided using the 'by' operator.
var range2to10by2: range(stridable=true) = 2..10 by 2; // 2, 4, 6, 8, 10 var range2to10by2: range(stridable=true) = 2..10 by 2; // 2, 4, 6, 8, 10
// Note: the range(stridable=true) is only // Note: the range(stridable=true) is only
@ -280,24 +287,23 @@ var threeDims: domain(3) = {thirdDim, 1..10, 5..10}; // using a range variable
// Can iterate over the indices as tuples // Can iterate over the indices as tuples
for idx in twoDimensions do for idx in twoDimensions do
write( idx , ", "); write( idx , ", ");
writeln(); writeln( );
// Or can deconstruct the tuple // or can deconstruct the tuple
for (x,y) in twoDimensions { for (x,y) in twoDimensions {
write( "(", x, ", ", y, ")", ", " ); write( "(", x, ", ", y, ")", ", " );
} }
writeln(); writeln( );
// Associative domains act like sets // Associative domains act like sets
var stringSet: domain(string); // empty set of strings var stringSet: domain(string); // empty set of strings
stringSet += "a"; stringSet += "a";
stringSet += "b"; stringSet += "b";
stringSet += "c"; stringSet += "c";
stringSet += "a"; // redundant add "a" stringSet += "a"; // Redundant add "a"
stringSet -= "c"; // remove "c" stringSet -= "c"; // Remove "c"
writeln( stringSet ); writeln( stringSet );
// Array are similar to those of other languages. // Array are similar to those of other languages.
// Their sizes are defined using domains that represent their indices // Their sizes are defined using domains that represent their indices
var intArray: [1..10] int; var intArray: [1..10] int;
@ -307,35 +313,35 @@ var intArray2: [{1..10}] int; //equivalent
for i in 1..10 do for i in 1..10 do
intArray[i] = -i; intArray[i] = -i;
writeln( intArray ); writeln( intArray );
// we cannot access intArray[0] because it exists outside // We cannot access intArray[0] because it exists outside
// of the index set, {1..10}, we defined it to have // of the index set, {1..10}, we defined it to have.
// intArray[11] is illegal for the same reason. // intArray[11] is illegal for the same reason.
var realDomain: domain(2) = {1..5,1..7}; var realDomain: domain(2) = {1..5,1..7};
var realArray: [realDomain] real; var realArray: [realDomain] real;
var realArray2: [1..5,1..7] real; // equivalent var realArray2: [1..5,1..7] real; // Equivalent
var realArray3: [{1..5,1..7}] real; // equivalent var realArray3: [{1..5,1..7}] real; // Equivalent
for i in 1..5 { for i in 1..5 {
for j in realDomain.dim(2) { // only use the 2nd dimension of the domain for j in realDomain.dim(2) { // Only use the 2nd dimension of the domain
realArray[i,j] = -1.61803 * i + 0.5 * j; // access using index list realArray[i,j] = -1.61803 * i + 0.5 * j; // Access using index list
var idx: 2*int = (i,j); // note: 'index' is a keyword var idx: 2*int = (i,j); // Note: 'index' is a keyword
realArray[idx] = - realArray[(i,j)]; // index using tuples realArray[idx] = - realArray[(i,j)]; // Index using tuples
} }
} }
// arrays have domains as members that we can iterate over // Arrays have domains as members that we can iterate over
for idx in realArray.domain { // again, idx is a 2*int tuple for idx in realArray.domain { // Again, idx is a 2*int tuple
realArray[idx] = 1 / realArray[idx[1],idx[2]]; // access by tuple and list realArray[idx] = 1 / realArray[idx[1],idx[2]]; // Access by tuple and list
} }
writeln( realArray ); writeln( realArray );
// can also iterate over the values of an array // Can also iterate over the values of an array
var rSum: real = 0; var rSum: real = 0;
for value in realArray { for value in realArray {
rSum += value; // read a value rSum += value; // Read a value
value = rSum; // write a value value = rSum; // Write a value
} }
writeln( rSum, "\n", realArray ); writeln( rSum, "\n", realArray );
@ -351,12 +357,12 @@ proc fibonacci( n : int ) : int {
return fibonacci( n-1 ) + fibonacci( n-2 ); return fibonacci( n-1 ) + fibonacci( n-2 );
} }
// input parameters can be untyped (a generic procedure) // Input parameters can be untyped (a generic procedure)
proc doublePrint( thing ): void { proc doublePrint( thing ): void {
write( thing, " ", thing, "\n"); write( thing, " ", thing, "\n");
} }
// return type can be inferred (as long as the compiler can figure it out) // Return type can be inferred (as long as the compiler can figure it out)
proc addThree( n ) { proc addThree( n ) {
return n + 3; return n + 3;
} }
@ -372,12 +378,12 @@ proc maxOf( x ...?k ) {
} }
writeln( maxOf( 1, -10, 189, -9071982, 5, 17, 20001, 42 ) ); writeln( maxOf( 1, -10, 189, -9071982, 5, 17, 20001, 42 ) );
// the ? operator is called the query operator, and is used to take // The ? operator is called the query operator, and is used to take
// undetermined values (like tuple or array sizes, and generic types). // undetermined values (like tuple or array sizes, and generic types).
// Taking arrays as parameters. // Taking arrays as parameters.
// The query operator is used to determine the domain of A. // The query operator is used to determine the domain of A.
// this is important to define the return type (if you wanted to) // This is important to define the return type (if you wanted to)
proc invertArray( A: [?D] int ): [D] int{ proc invertArray( A: [?D] int ): [D] int{
for a in A do a = -a; for a in A do a = -a;
return A; return A;
@ -396,7 +402,7 @@ writeln( defaultsProc( x=11 ) );
writeln( defaultsProc( x=12, y=5.432 ) ); writeln( defaultsProc( x=12, y=5.432 ) );
writeln( defaultsProc( y=9.876, x=13 ) ); writeln( defaultsProc( y=9.876, x=13 ) );
// intent modifiers on the arguments convey how // Intent modifiers on the arguments convey how
// those arguments are passed to the procedure // those arguments are passed to the procedure
// in: copy arg in, but not out // in: copy arg in, but not out
// out: copy arg out, but not in // out: copy arg out, but not in
@ -426,7 +432,7 @@ proc makeArray( elems: int, startNumber: int ) ref : [1..#elems] int {
return array; return array;
} }
writeln( makeArray( 10, -1 ) ); writeln( makeArray( 10, -1 ) );
// this makes more practical sense for class methods where references to // This makes more practical sense for class methods where references to
// elements in a data-structure are returned via a method or iterator // elements in a data-structure are returned via a method or iterator
// We can query the type of arguments to generic procedures // We can query the type of arguments to generic procedures
@ -462,17 +468,17 @@ whereProc( 10 );
whereProc( -1 ); whereProc( -1 );
// whereProc( 0 ) would result in a compiler error because there // whereProc( 0 ) would result in a compiler error because there
// are no functions that satisfy the where clause's condition. // are no functions that satisfy the where clause's condition.
// We could have defined a whereProc without a where clause that would // We could have defined a whereProc without a where clause that would then have
// then have been called. // served as a catch all for all the other cases (of which there is only one).
// Operator definitions are through procedures as well // Operator definitions are through procedures as well.
// we can define the unary operators: // We can define the unary operators:
// + - ! ~ // + - ! ~
// and the binary operators: // and the binary operators:
// + - * / % ** == <= >= < > << >> & | ˆ by // + - * / % ** == <= >= < > << >> & | ˆ by
// += -= *= /= %= **= &= |= ˆ= <<= >>= <=> // += -= *= /= %= **= &= |= ˆ= <<= >>= <=>
// boolean exclusive or operator // Boolean exclusive or operator
proc ^( left : bool, right : bool ): bool { proc ^( left : bool, right : bool ): bool {
return (left || right) && !( left && right ); return (left || right) && !( left && right );
} }
@ -487,8 +493,8 @@ proc *( left : ?ltype, right : ?rtype): ( ltype, rtype ){
return (left, right ); return (left, right );
} }
writeln( 1 * "a" ); // uses our * operator writeln( 1 * "a" ); // Uses our * operator
writeln( 1 * 2 ); // uses the original * operator writeln( 1 * 2 ); // Uses the default * operator
/* /*
Note: You could break everything if you get careless with your overloads. Note: You could break everything if you get careless with your overloads.
@ -498,24 +504,21 @@ proc +( left: int, right: int ): int{
} }
*/ */
// iterators are a close cousin to the procedure. // Iterators are a sisters to the procedure, and almost
// everything about procedures also applies to iterators
// However, instead of returning a single value, // However, instead of returning a single value,
// iterators yield many values to a loop. // iterators yield many values to a loop.
// This is useful when a complicated set or order of iterations is needed but // This is useful when a complicated set or order of iterations is needed but
// allows the code defining the iterations to be separate from the loop body. // allows the code defining the iterations to be separate from the loop body.
iter oddsThenEvens( N: int ): int { iter oddsThenEvens( N: int ): int {
for i in 1..N by 2 { for i in 1..N by 2 do
yield i; // yield values instead of returning. yield i; // yield values instead of returning.
} for i in 2..N by 2 do
for i in 2..N by 2 {
yield i; yield i;
}
} }
for i in oddsThenEvens( 10 ) do write( i, ", " ); for i in oddsThenEvens( 10 ) do write( i, ", " );
writeln(); writeln( );
// Classes are similar to those in C++ and Java. // Classes are similar to those in C++ and Java.
// They currently lack privatization // They currently lack privatization
@ -548,7 +551,7 @@ class MyClass {
return this.memberInt; return this.memberInt;
} }
proc getMemberBool(): bool { proc getMemberBool( ): bool {
return this.memberBool; return this.memberBool;
} }
@ -556,30 +559,30 @@ class MyClass {
// Construct using default constructor, using default values // Construct using default constructor, using default values
var myObject = new MyClass( 10 ); var myObject = new MyClass( 10 );
myObject = new MyClass( memberInt = 10 ); // equivalent myObject = new MyClass( memberInt = 10 ); // Equivalent
writeln( myObject.getMemberInt() ); writeln( myObject.getMemberInt( ) );
// ... using our values // ... using our values
var myDiffObject = new MyClass( -1, true ); var myDiffObject = new MyClass( -1, true );
myDiffObject = new MyClass( memberInt = -1, myDiffObject = new MyClass( memberInt = -1,
memberBool = true ); // equivalent memberBool = true ); // Equivalent
writeln( myDiffObject ); writeln( myDiffObject );
// Construct using written constructor // Construct using written constructor
var myOtherObject = new MyClass( 1.95 ); var myOtherObject = new MyClass( 1.95 );
myOtherObject = new MyClass( val = 1.95 ); // equivalent myOtherObject = new MyClass( val = 1.95 ); // Equivalent
writeln( myOtherObject.getMemberInt() ); writeln( myOtherObject.getMemberInt( ) );
// We can define an operator on our class as well but // We can define an operator on our class as well but
// the definition has to be outside the class definition // the definition has to be outside the class definition
proc +( A : MyClass, B : MyClass) : MyClass { proc +( A : MyClass, B : MyClass) : MyClass {
return new MyClass( memberInt = A.getMemberInt() + B.getMemberInt(), return new MyClass( memberInt = A.getMemberInt( ) + B.getMemberInt( ),
memberBool = A.getMemberBool() || B.getMemberBool() ); memberBool = A.getMemberBool( ) || B.getMemberBool( ) );
} }
var plusObject = myObject + myDiffObject; var plusObject = myObject + myDiffObject;
writeln( plusObject ); writeln( plusObject );
// destruction // Destruction
delete myObject; delete myObject;
delete myDiffObject; delete myDiffObject;
delete myOtherObject; delete myOtherObject;
@ -620,10 +623,10 @@ class GenericClass {
return this.classArray[ i ]; return this.classArray[ i ];
} }
// Define an iterator for the class to // Define an implicit iterator for the class
// yield values from the array to a loop // to yield values from the array to a loop
// i.e. for i in objVar do .... // i.e. for i in objVar do ....
iter these() ref : classType { iter these( ) ref : classType {
for i in this.classDomain do for i in this.classDomain do
yield this[i]; yield this[i];
} }
@ -635,19 +638,19 @@ var realList = new GenericClass( real, 10 );
// notation that we defined ( proc this( i: int ){ ... } ) // notation that we defined ( proc this( i: int ){ ... } )
for i in realList.classDomain do realList[i] = i + 1.0; for i in realList.classDomain do realList[i] = i + 1.0;
// We can iterate over the values in our list with the iterator // We can iterate over the values in our list with the iterator
// we defined ( iter these(){ ... } ) // we defined ( iter these( ){ ... } )
for value in realList do write( value, ", " ); for value in realList do write( value, ", " );
writeln(); writeln( );
// Make a copy of realList using the copy constructor // Make a copy of realList using the copy constructor
var copyList = new GenericClass( realList ); var copyList = new GenericClass( realList );
for value in copyList do write( value, ", " ); for value in copyList do write( value, ", " );
writeln(); writeln( );
// make a copy of realList and change the type, also using the copy constructor // Make a copy of realList and change the type, also using the copy constructor
var copyNewTypeList = new GenericClass( realList, int ); var copyNewTypeList = new GenericClass( realList, int );
for value in copyNewTypeList do write( value, ", " ); for value in copyNewTypeList do write( value, ", " );
writeln(); writeln( );
// Parallelism // Parallelism
// In other languages, parallelism is typically this is done with // In other languages, parallelism is typically this is done with
@ -655,14 +658,14 @@ writeln();
// Chapel has it baked right into the language. // Chapel has it baked right into the language.
// A begin statement will spin the body of that statement off into one new task. // A begin statement will spin the body of that statement off into one new task.
// a sync statement will ensure that the progress of the // A sync statement will ensure that the progress of the main
// main task will not progress until the children have synced back up. // task will not progress until the children have synced back up.
sync { sync {
begin { // start of new task's body begin { // Start of new task's body
var a = 0; var a = 0;
for i in 1..1000 do a += 1; for i in 1..1000 do a += 1;
writeln( "Done: ", a); writeln( "Done: ", a);
} // end of new tasks body } // End of new tasks body
writeln( "spun off a task!"); writeln( "spun off a task!");
} }
writeln( "Back together" ); writeln( "Back together" );
@ -671,13 +674,13 @@ proc printFibb( n: int ){
writeln( "fibonacci(",n,") = ", fibonacci( n ) ); writeln( "fibonacci(",n,") = ", fibonacci( n ) );
} }
// a cobegin statement will spin each statement of the body into one new task // A cobegin statement will spin each statement of the body into one new task
cobegin { cobegin {
printFibb( 20 ); // new task printFibb( 20 ); // new task
printFibb( 10 ); // new task printFibb( 10 ); // new task
printFibb( 5 ); // new task printFibb( 5 ); // new task
{ {
// this is a nested statement body and thus is a single statement // This is a nested statement body and thus is a single statement
// to the parent statement and is executed by a single task // to the parent statement and is executed by a single task
writeln( "this gets" ); writeln( "this gets" );
writeln( "executed as" ); writeln( "executed as" );
@ -700,41 +703,41 @@ coforall taskID in 1..#num_tasks {
forall i in 1..100 { forall i in 1..100 {
write( i, ", "); write( i, ", ");
} }
writeln(); writeln( );
// Here we see that there are sections that are in order, followed by // Here we see that there are sections that are in order, followed by
// a section that would not follow ( e.g. 1, 2, 3, 7, 8, 9, 4, 5, 6, ) // a section that would not follow ( e.g. 1, 2, 3, 7, 8, 9, 4, 5, 6, ).
// this is because each task is taking on a chunk of the range 1..10 // This is because each task is taking on a chunk of the range 1..10
// (1..3, 4..6, or 7..9) doing that chunk serially, but each task happens // (1..3, 4..6, or 7..9) doing that chunk serially, but each task happens
// in parallel. // in parallel.
// Your results may depend on your machine and configuration // Your results may depend on your machine and configuration
// For both the forall and coforall loops, the execution of the parent task // For both the forall and coforall loops, the execution of the
// will not continue until all the children sync up. // parent task will not continue until all the children sync up.
// forall loops are particularly useful for parallel iteration over arrays // forall loops are particularly useful for parallel iteration over arrays.
// Lets run an experiment to see how much faster a parallel loop is // Lets run an experiment to see how much faster a parallel loop is
use Time; // Import the Time module to use Timer objects use Time; // Import the Time module to use Timer objects
var timer: Timer; var timer: Timer;
var myBigArray: [{1..4000,1..4000}] real; // large array we will write into var myBigArray: [{1..4000,1..4000}] real; // Large array we will write into
// Serial Experiment // Serial Experiment
timer.start(); // start timer timer.start( ); // Start timer
for (x,y) in myBigArray.domain { // serial iteration for (x,y) in myBigArray.domain { // Serial iteration
myBigArray[x,y] = (x:real) / (y:real); myBigArray[x,y] = (x:real) / (y:real);
} }
timer.stop(); // stop timer timer.stop( ); // Stop timer
writeln( "Serial: ", timer.elapsed() ); // print elapsed time writeln( "Serial: ", timer.elapsed( ) ); // Print elapsed time
timer.clear(); // clear timer for parallel loop timer.clear( ); // Clear timer for parallel loop
// Parallel Experiment // Parallel Experiment
timer.start(); // start timer timer.start( ); // start timer
forall (x,y) in myBigArray.domain { // parallel iteration forall (x,y) in myBigArray.domain { // Parallel iteration
myBigArray[x,y] = (x:real) / (y:real); myBigArray[x,y] = (x:real) / (y:real);
} }
timer.stop(); // stop timer timer.stop( ); // Stop timer
writeln( "Parallel: ", timer.elapsed() ); // print elapsed time writeln( "Parallel: ", timer.elapsed( ) ); // Print elapsed time
timer.clear(); timer.clear( );
// you may have noticed that (depending on how many cores you have) that // You may have noticed that (depending on how many cores you have)
// the parallel loop went faster than the serial loop // that the parallel loop went faster than the serial loop
// A succinct way of writing a forall loop over an array: // A succinct way of writing a forall loop over an array:
// iterate over values // iterate over values
@ -750,6 +753,17 @@ Refer to the [language specification](http://chapel.cray.com/language.html) and
Occasionally check back here and on the [Chapel site](http://chapel.cray.com) to see if more topics have been added or more tutorials created. Occasionally check back here and on the [Chapel site](http://chapel.cray.com) to see if more topics have been added or more tutorials created.
### What this tutorial is lacking:
* Modules and standard modules
* Synchronize and atomic variables
* Multiple Locales (distributed memory system)
* proc main(){ ... }
* Records
* Whole/sliced array assignment
* Reductions and scans
* Range and domain slicing
* Parallel iterators
Your input, questions, and discoveries are important to the developers! Your input, questions, and discoveries are important to the developers!
----------------------------------------------------------------------- -----------------------------------------------------------------------
The Chapel language is still in-development (version 1.11.0), so there are occasional hiccups with performance and language features. The Chapel language is still in-development (version 1.11.0), so there are occasional hiccups with performance and language features.