// This is a comment // 1. Basics // Functions func Add(X : Univ_Integer; Y : Univ_Integer) -> Univ_Integer is return X + Y; end func Add; // End of line semi-colons are optional // +, +=, -, -=, *, *=, /, /= // all do what you'd expect (/ is integer division) // If you find Univ_Integer to be too verbose you can import Short_Names // which defines aliases like Int for Univ_Integer and String for Univ_String import PSL::Short_Names::*, * func Greetings() is const S : String := "Hello, World!" Println(S) end func Greetings // All declarations are 'const', 'var', or 'ref' // Assignment is :=, equality checks are ==, and != is not equals func Boolean_Examples(B : Bool) is const And := B and #true // Parallel execution of operands const And_Then := B and then #true // Short-Circuit const Or := B or #false // Parallel execution of operands const Or_Else := B or else #false // Short-Cirtuit const Xor := B xor #true var Result : Bool := #true; Result and= #false; Result or= #true; Result xor= #false; end func Boolean_Examples // Booleans are a special type of enumeration // All enumerations are preceded by a sharp '#' func Fib(N : Int) {N >= 0} -> Int is if N <= 1 then return N else // Left and right side of '+' are computed in Parallel here return Fib(N - 1) + Fib(N - 2) end if end func Fib // '{N >= 0}' is a precondition to this function // Preconditions are built in to the language and checked by the compiler // ParaSail does not have mutable global variables // Instead, use 'var' parameters func Increment_All(var Nums : Vector) is for each Elem of Nums concurrent loop Elem += 1 end loop end func Increment_All // The 'concurrent' keyword in the loop header tells the compiler that // iterations of the loop can happen in any order. // It will choose the most optimal number of threads to use. // Other options are 'forward' and 'reverse'. func Sum_Of_Squares(N : Int) -> Int is // The type of Sum is inferred var Sum := 0 for I in 1 .. N forward loop Sum += I ** 2 // ** is exponentiation end loop end func Sum_Of_Squares func Sum_Of(N : Int; Map : func (Int) -> Int) -> Int is return (for I in 1 .. N => <0> + Map(I)) end func Sum_Of // It has functional aspects as well // Here, we're taking an (Int) -> Int function as a parameter // and using the inherently parallel map-reduce. // Initial value is enclosed with angle brackets func main(Args : Basic_Array) is Greetings() // Hello World Println(Fib(5)) // 5 // Container Comprehension var Vec : Vector := [for I in 0 .. 10 {I mod 2 == 0} => I ** 2] // Vec = [0, 4, 16, 36, 64, 100] Increment_All(Vec) // Vec = [1, 5, 17, 37, 65, 101] // '|' is an overloaded operator. // It's usually used for concatenation or adding to a container Println("First: " | Vec[1] | ", Last: " | Vec[Length(Vec)]); // Vectors are 1 indexed, 0 indexed ZVectors are also available Println(Sum_Of_Squares(3)) // Sum of fibs! Println(Sum_Of(10, Fib)) end func main // Preceding a type with 'optional' allows it to take the value 'null' func Divide(A, B, C : Real) -> optional Real is // Real is the floating point type const Epsilon := 1.0e-6; if B in -Epsilon .. Epsilon then return null elsif C in -Epsilon .. Epsilon then return null else return A / B + A / C end if end func Divide // 2. Modules // Modules are composed of an interface and a class // ParaSail has object orientation features // modules can be defined as 'concurrent' // which allows 'locked' and 'queued' parameters concurrent interface Locked_Box> is // Create a box with the given content func Create(C : optional Content_Type) -> Locked_Box; // Put something into the box func Put(locked var B : Locked_Box; C : Content_Type); // Get a copy of current content func Content(locked B : Locked_Box) -> optional Content_Type; // Remove current content, leaving it null func Remove(locked var B : Locked_Box) -> optional Content_Type; // Wait until content is non-null, then return it, leaving it null. func Get(queued var B : Locked_Box) -> Content_Type; end interface Locked_Box; concurrent class Locked_Box is var Content : optional Content_Type; exports func Create(C : optional Content_Type) -> Locked_Box is return (Content => C); end func Create; func Put(locked var B : Locked_Box; C : Content_Type) is B.Content := C; end func Put; func Content(locked B : Locked_Box) -> optional Content_Type is return B.Content; end func Content; func Remove(locked var B : Locked_Box) -> Result : optional Content_Type is // '<==' is the move operator // It moves the right operand into the left operand, // leaving the right null. Result <== B.Content; end func Remove; func Get(queued var B : Locked_Box) -> Result : Content_Type is queued until B.Content not null then Result <== B.Content; end func Get; end class Locked_Box; func Use_Box(Seed : Univ_Integer) is var U_Box : Locked_Box := Create(null); // The type of 'Ran' can be left out because // it is inferred from the return type of Random::Start var Ran := Random::Start(Seed); Println("Starting 100 pico-threads trying to put something in the box"); Println(" or take something out."); for I in 1..100 concurrent loop if I < 30 then Println("Getting out " | Get(U_Box)); else Println("Putting in " | I); U_Box.Put(I); // The first parameter can be moved to the front with a dot // X.Foo(Y) is equivalent to Foo(X, Y) end if; end loop; Println("And the winner is: " | Remove(U_Box)); Println("And the box is now " | Content(U_Box)); end func Use_Box;