Monday, September 28, 2009

More on ParaSail interfaces

Here is the ParaSail example of an Array interface from the last installment:

 interface Array < Element_Type is Assignable<>;
                    Index_Type is Discrete<>>
   function First(Arr : Array) -> Index_Type;
   function Last(Arr : Array) -> Index_Type;
   function Element(Arr : ref Array;
     Index : Index_Type {Index in First(Arr)..Last(Arr)})
       -> ref Element_Type;
   function Create_Array(First, Last : Index_Type)
       -> Result:Array
           {First(Result) = First & Last(Result) = Last};
 end interface Array;

To make indexing into an Array look more familiar, we might want to use the "[]" operator instead of the function Element:

  operator "[]"(Arr : ref Array;
     Index : Index_Type {Index in First(Arr)..Last(Arr)})
       -> ref Element_Type;

Now we could use this interface roughly as follows:

   var Names: Array<String, Student_ID> := 
     Create_Array(First => First_Student_ID,
                  Last => Last_Student_ID);
   Names[ID_Of_Mike] := "Mike";

This kind of thing should look pretty familiar.

A few things to note:  There is no separate notion of a constructor.  A function that returns an object of the type defined by the enclosing interface is effectively a constructor.   A function that returns a ref is not a constructor, but may be used on the left-hand side of an assignment, provided the ref parameter(s) to the function can be used on the left-hand side.  Parameters are by default read-only, but ref parameters can be updated.  The result of a function is specified after a "->".  If the function has multiple results, they are enclosed in parentheses in the same way as the (input) parameters:

  function Two_Outputs(X : Input_Type) -> 
         (Y : Output_Type1; Z : Output_Type2);

Once we start talking about statements, we will see that in ParaSail, as in C++ and Java, declarations and executable statements may be interspersed.  All declarations start with a reserved word, such as var, const, interface, subtype, etc. so they are easy to distinguish from assignment statements, procedure calls, etc.

Next time we will discuss how a class implements an interface.


  1. I am finding it hard to distinguish which of your language design decisions are critical to the goals of the language (parallelism) and which are essentially arbitrary relative to those goals. For instance, surface syntax such as if, then, else, end if are arbitrary with respect to parallelism (even if important for readability, familiarity, etc.).

    As a concrete example, it is not clear to me at this stage what the implications are for an assignment to a ref returning function for parallelism.

    -Fred Mueller

  2. The goal is to create a language that has familiar capabilities but that also provides implicit parallelism. One of the keys to implicit parallelism is that there are no global variables -- the parameter list identifies all variable data that is read or updated by the operation. This means that the parameter list needs to be capable of supporting the kinds of references that might normally be done using global variables, including indirections through pointers. So the notion of a "ref" parameter or result is important to reduce the use of explicit pointer indirection.

  3. I might add that supporting annotations with a light-weight syntax (e.g. "{...}") is also important, as one fundamental goal of ParaSail is to be suitable for safety-critical software requiring stringent certification.