<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-8383004232931899216</id><updated>2012-02-13T10:51:12.308-05:00</updated><title type='text'>Designing ParaSail, a new programming language</title><subtitle type='html'>This blog will follow the trials and tribulations of designing a new programming language designed to allow productive development of parallel, high-integrity (safety-critical, high-security) software systems.  The language is tentatively named "ParaSail" for Parallel, Specification and Implementation Language.</subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://parasail-programming-language.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8383004232931899216/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://parasail-programming-language.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Tuck</name><uri>http://www.blogger.com/profile/08866496974237052847</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>72</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-8383004232931899216.post-7866983669672274879</id><published>2012-02-05T15:26:00.000-05:00</published><updated>2012-02-05T15:26:07.723-05:00</updated><title type='text'>Full Object-Oriented Programming support in rev 2.0 alpha 0.5</title><content type='html'>We have just made available a new alpha release of the prototype &lt;b&gt;ParaSail&lt;/b&gt; compiler and virtual machine, rev 2.0, alpha 0.5:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://bit.ly/zuSIz1"&gt;http://bit.ly/zuSIz1&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;This new release has full support for inheritance and polymorphism.&amp;nbsp; In ParaSail terms, this means that you can now use polymorphic types, using the &lt;b&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;T+&lt;/span&gt;&lt;/b&gt; syntax, and you can define one module as an extension of another, using the &lt;b&gt;extends&lt;/b&gt; keyword.&amp;nbsp; (The &lt;b&gt;implements&lt;/b&gt; keyword was already supported in earlier releases.)&amp;nbsp; This release includes a new example, "expr_tree.psl", which illustrates a hierarchy of types defined using module extension and polymorphic components.&amp;nbsp; As usual, we include executables for Mac, Linux, and Windows.&lt;br /&gt;&lt;br /&gt;The prior blog entry discussed the implementation of polymorphic objects.&amp;nbsp; An upcoming blog entry will discuss the implementation of the inheritance of operations and components.&amp;nbsp; As in Java, C#, and Ada, ParaSail supports single inheritance of implementation, and multiple inheritance of interfaces.&amp;nbsp; The multiple inheritance of interfaces was implemented from the very first ParaSail release, but this is the first ParaSail release that supports inheritance of the implementation of operations, and of components.&amp;nbsp; This involved some additions to the virtual machine instruction set, and significant work in the compiler.&lt;br /&gt;&lt;br /&gt;Both polymorphism and inheritance (of implementation) are handled by ParaSail in a somewhat non-traditional way, in part because there are no pointers in ParaSail, and in part because objects are expandable "in place" without the use of pointers.&amp;nbsp; Polymorphic objects in ParaSail can be assigned new values which are of different types in the hierarchy.&amp;nbsp; In most object-oriented languages, only pointers or references can be truly polymorphic; the type of a particular object is set when the object is created and cannot change during its lifetime.&amp;nbsp; See the prior and upcoming blog entries for more details, as well as the reference manual included with the above release in the "doc" subdirectory and the "expr_tree.psl" example in the "examples" subdirectory.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8383004232931899216-7866983669672274879?l=parasail-programming-language.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://parasail-programming-language.blogspot.com/feeds/7866983669672274879/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://parasail-programming-language.blogspot.com/2012/02/full-object-oriented-programming.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8383004232931899216/posts/default/7866983669672274879'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8383004232931899216/posts/default/7866983669672274879'/><link rel='alternate' type='text/html' href='http://parasail-programming-language.blogspot.com/2012/02/full-object-oriented-programming.html' title='Full Object-Oriented Programming support in rev 2.0 alpha 0.5'/><author><name>Tuck</name><uri>http://www.blogger.com/profile/08866496974237052847</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8383004232931899216.post-4603193734862043443</id><published>2012-01-24T18:57:00.001-05:00</published><updated>2012-01-24T19:56:55.129-05:00</updated><title type='text'>Implementing Polymorphic Objects</title><content type='html'>&lt;b&gt;ParaSail&lt;/b&gt; has a somewhat different approach to (run-time) polymorphism than is typical.&amp;nbsp; There is a separate notation for indicating an object is polymorphic.&amp;nbsp; If you declare "var X : T" then X is of type T.&amp;nbsp; If you declare "var X : T+" then X is a polymorphic object, meaning it can hold an object of type T or any type that &lt;i&gt;extends&lt;/i&gt; or &lt;i&gt;implements&lt;/i&gt; T.&amp;nbsp; Adding a "+" sign to the end of a type name is used to indicate a polymorphic type &lt;i&gt;rooted&lt;/i&gt; at the given type.&amp;nbsp; For a longer discussion of ParaSail's object-oriented model, see:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://parasail-programming-language.blogspot.com/2009/09/parasail-extension-inheritance-and.html"&gt;http://parasail-programming-language.blogspot.com/2009/09/parasail-extension-inheritance-and.html &lt;/a&gt;&lt;br /&gt;&lt;br /&gt;We have just completed the initial implementation of polymorphic objects, and there were some interesting trade-offs involved.&amp;nbsp; First we should recap the implementation of "regular" objects in ParaSail.&amp;nbsp; Some of this is covered in:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://parasail-programming-language.blogspot.com/2011/05/when-null-isnt-just-null-value.html"&gt;http://parasail-programming-language.blogspot.com/2011/05/when-null-isnt-just-null-value.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Regular objects come in two basic varieties, small and large.&amp;nbsp; A &lt;i&gt;small&lt;/i&gt; object is represented by a single 64-bit word.&amp;nbsp; It has no type information at run-time.&amp;nbsp; The compiler "knows" from context the type of the object.&amp;nbsp; One bit pattern is reserved to represent &lt;b&gt;null&lt;/b&gt; for a given small type.&amp;nbsp; As mentioned in the above blog entry, we use NaN for a floating point &lt;b&gt;null&lt;/b&gt;, and -2**63 for a 64-bit integer &lt;b&gt;null&lt;/b&gt;.&amp;nbsp; Other values can be used for types with fewer values, of course, and one less than the smallest normal value or one greater than the largest normal value would work.&lt;br /&gt;&lt;br /&gt;A &lt;i&gt;large&lt;/i&gt; object is represented by a 64-bit address, pointing to a sequence of 64-bit words, the first of which is a &lt;i&gt;header&lt;/i&gt;, followed by the components.&amp;nbsp; The &lt;i&gt;header&lt;/i&gt; identifies the object's &lt;i&gt;size&lt;/i&gt; (in 64-bit words), its structural &lt;i&gt;type-id&lt;/i&gt; (primarily an indication of which components are small and which are large), its storage &lt;i&gt;region-id&lt;/i&gt;, and a &lt;i&gt;lock-id&lt;/i&gt; if the object is a concurrent object.&lt;br /&gt;&lt;br /&gt;If a composite type has exactly one component, then rather than creating another level of indirection, we simply adopt the representation for the component as the representation for the composite type.&amp;nbsp; This means that a composite type whose only component is of a &lt;i&gt;small&lt;/i&gt; type is itself represented as a &lt;i&gt;small&lt;/i&gt; object.&amp;nbsp; Hence, there is no extra storage overhead in &lt;i&gt;wrapping&lt;/i&gt; an object in another type, just to give it a new interface.&amp;nbsp; So a user-defined numeric type, for instance, need be no bigger than the underlying component used to represent its value.&amp;nbsp; We call these &lt;i&gt;wrapper&lt;/i&gt; types.&amp;nbsp; Objects of a wrapper type are indistinguishable at run-time from objects of their component type, and if their component is large, then the &lt;i&gt;type-id&lt;/i&gt; in the header of an object of the wrapper type will be the same as the &lt;i&gt;type-id&lt;/i&gt; in the header of an object of the component type.&amp;nbsp; This is one reason we call the &lt;i&gt;type-id&lt;/i&gt; in the header of a large object its &lt;i&gt;structural&lt;/i&gt; type-id.&lt;br /&gt;&lt;br /&gt;A &lt;b&gt;null&lt;/b&gt; for a large type was originally represented by the 64-bit address of an object consisting only of a header, with a structural &lt;i&gt;type-id&lt;/i&gt; indicating it was a null object, and the storage&lt;i&gt; region-id&lt;/i&gt; indicating where to allocate storage for it when it is assigned a non-null value.&amp;nbsp; We have since switched over to a representation where the 64-bit address itself is recognizable as representing a large &lt;b&gt;null&lt;/b&gt; value, with the storage&lt;i&gt; region-id&lt;/i&gt; encoded in 16 bits of the 64-bit address representation, avoiding the extra level of indirection, and the need to create null objects when first creating a new region.&lt;br /&gt;&lt;br /&gt;So where does that leave us for &lt;i&gt;polymorphic&lt;/i&gt; objects?&amp;nbsp; Polymorphic objects need to carry around an indication of their &lt;i&gt;true&lt;/i&gt; run-time type-id, not just &lt;i&gt;structural&lt;/i&gt; information.&amp;nbsp; For example, a polymorphic object that started out as an object of a &lt;i&gt;wrapper&lt;/i&gt; type, needs to be distinguishable at run-time from a polymorphic object that started out as an object of the wrapper's component type.&amp;nbsp; So we choose to make polymorphic objects always use the &lt;i&gt;large&lt;/i&gt; representation, meaning they always have a header.&amp;nbsp; Furthermore, the &lt;i&gt;type-id&lt;/i&gt; in this header explicitly identifies this object as being a polymorphic object, with a single "component." The &lt;i&gt;true&lt;/i&gt; (run-time) &lt;i&gt;type-id&lt;/i&gt; of this single "component" is also identified by the polymorphic &lt;i&gt;type-id&lt;/i&gt;.&amp;nbsp; Furthermore, if this &lt;i&gt;true&lt;/i&gt; type &lt;i&gt;implements&lt;/i&gt; (rather than &lt;i&gt;extends&lt;/i&gt;) the &lt;i&gt;root&lt;/i&gt; type of the polymorphic type, an &lt;i&gt;operation map&lt;/i&gt; is provided to map the true type's operations to those of the root type.&amp;nbsp; For a discussion of these operation maps (called &lt;i&gt;slot-number mappings&lt;/i&gt; in the blog entry), see:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://parasail-programming-language.blogspot.com/2010/08/initial-implementation-model-for.html"&gt;http://parasail-programming-language.blogspot.com/2010/08/initial-implementation-model-for.html&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;So the representation of a polymorphic object is essentially a "real" wrapper object, to allow us to specify the &lt;i&gt;true&lt;/i&gt; type of the wrapped underlying object.&amp;nbsp; To some degree this is the price we pay for having small objects that don't carry around any type information, and for allowing wrapper types to be represented identically to their component types.&amp;nbsp; When we really need a &lt;i&gt;polymorphic&lt;/i&gt; object, we need to add an extra level of header, so we can record the &lt;i&gt;true&lt;/i&gt; type information.&lt;br /&gt;&lt;br /&gt;What can you do with polymorphic objects?&amp;nbsp; They can be assigned a value of any type that extends or implements the root type of the polymorphic type.&amp;nbsp; Furthermore, when passed as a parameter to an operation of the root type, the &lt;i&gt;true&lt;/i&gt; type-id of the wrapped object is consulted, and that type-id is used to find the actual &lt;i&gt;body&lt;/i&gt; to execute for this given operation.&lt;br /&gt;&lt;br /&gt;For example, if T has a visible "Print(X : T)" operation, then any type NT that extends or implements T must also have a corresponding Print operation, but taking NT rather than T (i.e. "Print(X : NT)").&amp;nbsp; If we pass a polymorphic object of type T+ to the Print operation of T, it will &lt;i&gt;dispatch&lt;/i&gt; to the &lt;i&gt;appropriate&lt;/i&gt; body for Print.&amp;nbsp; So if the true type-id for the polymorphic object passed identifies NT, then we will execute the "Print(X : NT)" operation.&lt;br /&gt;&lt;br /&gt;As part of passing the polymorphic object, the polymorphic "wrapper" is stripped off, so by the time we get to the appropriate operation's body, the representation for the parameter is back to the "normal" representation expected by that operation.&amp;nbsp; For example, this means that operations designed to take "small" representations for values, will work fine in this context, because the large-object, polymorphic header will have been stripped off, and just the small value will be passed to the operation's body, as expected.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8383004232931899216-4603193734862043443?l=parasail-programming-language.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://parasail-programming-language.blogspot.com/feeds/4603193734862043443/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://parasail-programming-language.blogspot.com/2012/01/implementing-polymorphic-objects.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8383004232931899216/posts/default/4603193734862043443'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8383004232931899216/posts/default/4603193734862043443'/><link rel='alternate' type='text/html' href='http://parasail-programming-language.blogspot.com/2012/01/implementing-polymorphic-objects.html' title='Implementing Polymorphic Objects'/><author><name>Tuck</name><uri>http://www.blogger.com/profile/08866496974237052847</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8383004232931899216.post-2925458664068533717</id><published>2012-01-06T18:23:00.000-05:00</published><updated>2012-01-06T18:23:09.334-05:00</updated><title type='text'>Rev 1.8 of alpha 0.3 release of ParaSail compiler and virtual machine</title><content type='html'>Rev 1.8 of the 0.3 Alpha release of &lt;b&gt;ParaSail&lt;/b&gt; is now available at:&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;a href="http://bit.ly/AAWk7Y" target="_blank"&gt;http://bit.ly/AAWk7Y&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;This  release has initial support for &lt;i&gt;generic&lt;/i&gt; operations, where the type of  one of the operands is not specified exactly, but merely as being any  type that implements a given interface.&amp;nbsp; For example, to declare a  concatenation operator between Univ_String and any type that implements  the Imageable interface, you can write:&lt;br /&gt;&lt;br /&gt;&lt;div style="margin-left: 40px;"&gt;&lt;b&gt;op&lt;/b&gt; "|"(Left : Univ_String; Right : Right_Type &lt;b&gt;is&lt;/b&gt; Imageable&amp;lt;&amp;gt;) -&amp;gt; Univ_String;&lt;/div&gt;&lt;br /&gt;This operator can be implemented using operations on Right that are defined in the Imageable interface, such as To_String.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8383004232931899216-2925458664068533717?l=parasail-programming-language.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://parasail-programming-language.blogspot.com/feeds/2925458664068533717/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://parasail-programming-language.blogspot.com/2012/01/rev-18-of-alpha-03-release-of-parasail.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8383004232931899216/posts/default/2925458664068533717'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8383004232931899216/posts/default/2925458664068533717'/><link rel='alternate' type='text/html' href='http://parasail-programming-language.blogspot.com/2012/01/rev-18-of-alpha-03-release-of-parasail.html' title='Rev 1.8 of alpha 0.3 release of ParaSail compiler and virtual machine'/><author><name>Tuck</name><uri>http://www.blogger.com/profile/08866496974237052847</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8383004232931899216.post-150139029730472673</id><published>2011-11-07T06:03:00.000-05:00</published><updated>2011-11-07T06:03:14.995-05:00</updated><title type='text'>Rev 1.6 of alpha 0.2 release of ParaSail compiler and VM</title><content type='html'>Here is a new revision (rev 1.6) of the alpha 0.2 release of the &lt;b&gt;ParaSail&lt;/b&gt; compiler and virtual machine&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;a href="http://bit.ly/tJyc5E"&gt;http://bit.ly/tJyc5E&lt;/a&gt; &lt;br /&gt;&lt;br /&gt;The big addition here is a new example, the "drinking philosophers" example (drinking_phils.psl).&amp;nbsp; This example is a variant on the classic "dining philosophers" example, and makes heavy use of timers and complex dequeue conditions.&amp;nbsp; A lot of changes under the hood, but no major new features.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8383004232931899216-150139029730472673?l=parasail-programming-language.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://parasail-programming-language.blogspot.com/feeds/150139029730472673/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://parasail-programming-language.blogspot.com/2011/11/rev-16-of-alpha-02-release-of-parasail.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8383004232931899216/posts/default/150139029730472673'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8383004232931899216/posts/default/150139029730472673'/><link rel='alternate' type='text/html' href='http://parasail-programming-language.blogspot.com/2011/11/rev-16-of-alpha-02-release-of-parasail.html' title='Rev 1.6 of alpha 0.2 release of ParaSail compiler and VM'/><author><name>Tuck</name><uri>http://www.blogger.com/profile/08866496974237052847</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8383004232931899216.post-5133164189895530779</id><published>2011-10-24T19:33:00.000-04:00</published><updated>2011-10-24T19:33:47.163-04:00</updated><title type='text'>Alpha release 0.2 of ParaSail Compiler and Virtual Machine</title><content type='html'>We are now making available alpha release 0.2 (rev 1.5) of the ParaSail Compiler and Virtual Machine:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://bit.ly/rsxQDX"&gt;http://bit.ly/rsxQDX&lt;/a&gt; &lt;br /&gt;&lt;br /&gt;This release implements several important additional features, including &lt;b&gt;queued&lt;/b&gt; parameters for operations on concurrent objects, floating-point and fixed-point numbers along with the universal type &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;Univ_Real&lt;/span&gt;, and timers supporting delay for a time interval and delay until a specified timer value, or until a specific wall clock time.&amp;nbsp;&lt;br /&gt;&lt;br /&gt;This release also includes two different version of the VM, one which simulates multi-threading on a single O/S thread, and another which uses multiple O/S threads to provide true parallelism on a multi-core/multi-processor machine.&lt;br /&gt;&lt;br /&gt;Please read the release notes included in the above download for additional information.&lt;br /&gt;-Tuck&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8383004232931899216-5133164189895530779?l=parasail-programming-language.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://parasail-programming-language.blogspot.com/feeds/5133164189895530779/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://parasail-programming-language.blogspot.com/2011/10/alpha-release-02-of-parasail-compiler.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8383004232931899216/posts/default/5133164189895530779'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8383004232931899216/posts/default/5133164189895530779'/><link rel='alternate' type='text/html' href='http://parasail-programming-language.blogspot.com/2011/10/alpha-release-02-of-parasail-compiler.html' title='Alpha release 0.2 of ParaSail Compiler and Virtual Machine'/><author><name>Tuck</name><uri>http://www.blogger.com/profile/08866496974237052847</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8383004232931899216.post-9140339101424550095</id><published>2011-10-14T16:35:00.000-04:00</published><updated>2011-10-14T16:35:23.060-04:00</updated><title type='text'>Upcoming panels, tutorials, and workshops on ParaSail</title><content type='html'>&lt;b&gt;ParaSail&lt;/b&gt; will be discussed at two panels at the upcoming SPLASH/OOPSLA conference in Portland, Oregon, and will be covered in depth in a tutorial and workshop/birds-of-a-feather session at the upcoming SIGAda conference in Denver.&amp;nbsp;&lt;br /&gt;&lt;br /&gt;The panels at SPLASH/OOPSLA are:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;A panel that is part of the &lt;i&gt;Transitioning to Multicore&lt;/i&gt; (TMC) workshop, on Sunday Oct. 23rd, at 2:00PM -- see &lt;a href="http://tmc.supertriceratops.com/"&gt;http://tmc.supertriceratops.com/&lt;/a&gt;&lt;/li&gt;&lt;li&gt;A panel on &lt;i&gt;Multicore, Manycore, and Cloud computing -- Is a new programming language paradigm required?&lt;/i&gt;, on Wednesday Oct. 26th, at 4:00PM -- see &lt;a href="http://splashcon.org/2011/program/229"&gt;http://splashcon.org/2011/program/229&lt;/a&gt;&amp;nbsp;&amp;nbsp;&lt;/li&gt;&lt;/ul&gt;The events at the upcoming SIGAda conference in Denver are:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;A tutorial on &lt;i&gt;Experimenting with ParaSail&lt;/i&gt;, which will be held Monday November 7th, from 9:00AM to 12:30PM -- see &lt;a href="http://www.sigada.org/conf/sigada2011/tutorials-descriptions.html#MA1"&gt;http://www.sigada.org/conf/sigada2011/tutorials-descriptions.html#MA1&lt;/a&gt; &lt;/li&gt;&lt;li&gt;A workshop/birds-of-a-feather session on ParaSail, which will be on Tuesday, November 8th, from 4:30PM to 5:30PM -- see &lt;a href="http://www.sigada.org/conf/sigada2011/workshops.html"&gt;http://www.sigada.org/conf/sigada2011/workshops.html&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;I believe all of these event are still open for additional attendees.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8383004232931899216-9140339101424550095?l=parasail-programming-language.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://parasail-programming-language.blogspot.com/feeds/9140339101424550095/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://parasail-programming-language.blogspot.com/2011/10/upcoming-panels-tutorials-and-workshops.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8383004232931899216/posts/default/9140339101424550095'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8383004232931899216/posts/default/9140339101424550095'/><link rel='alternate' type='text/html' href='http://parasail-programming-language.blogspot.com/2011/10/upcoming-panels-tutorials-and-workshops.html' title='Upcoming panels, tutorials, and workshops on ParaSail'/><author><name>Tuck</name><uri>http://www.blogger.com/profile/08866496974237052847</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8383004232931899216.post-1889918825826386772</id><published>2011-10-13T16:56:00.000-04:00</published><updated>2011-10-13T16:56:25.238-04:00</updated><title type='text'>Deadlocking the Virtual Machine</title><content type='html'>As mentioned in an earlier posting, &lt;b&gt;ParaSail&lt;/b&gt; has its own virtual machine which directly supports the notion of &lt;i&gt;picothreads&lt;/i&gt;, very light-weight threads which are served by heavier-weight server processes (see &lt;a href="http://parasail-programming-language.blogspot.com/2010/11/virtual-machine-for-parasail-with.html"&gt;http://parasail-programming-language.blogspot.com/2010/11/virtual-machine-for-parasail-with.html&lt;/a&gt;).&amp;nbsp; We are now compiling and executing various interesting ParaSail examples, and we recently began to see some apparent deadlocks in the virtual machine implementation.&amp;nbsp;&lt;br /&gt;&lt;br /&gt;The actual ParaSail program (N Queens -- see &lt;a href="http://parasail-programming-language.blogspot.com/2011/09/n-queens-join-party.html"&gt;http://parasail-programming-language.blogspot.com/2011/09/n-queens-join-party.html&lt;/a&gt;) does not have any inherent deadlock itself.&amp;nbsp; In fact, it only has one concurrent object, a vector of solutions, and the only locking operation used is to add another solution on to the end of the vector.&amp;nbsp; Nevertheless, we are seeing with a true multi-threaded virtual machine implementation, a deadlock in the virtual machine, such that all forward progress stops.&amp;nbsp; Like many situations in concurrent programs (at least pre-ParaSail...), these kinds of problems are timing dependent.&amp;nbsp; In some cases we can get the N-Queens solver for 8 queens to finish, sometimes not.&amp;nbsp; The version using a single-kernel-thread virtual machine, which merely simulates multi-threading, never has a problem.&lt;br /&gt;&lt;br /&gt;So what could be causing the deadlock?&amp;nbsp; After lots of debugging, a hypothesis has emerged.&amp;nbsp; We are now in the process of acting on this hypothesis, so we don't know whether it is correct, or whether making a corresponding fix will solve the entire problem.&amp;nbsp; So here is the hypothesis:&lt;br /&gt;&lt;br /&gt;As explained in the posting about the virtual machine (actually, in a comment on that posting), we serve the queue of picothreads associated with a particular server process in a LIFO manner.&amp;nbsp; But when a server &lt;i&gt;steals&lt;/i&gt; threads from another server, it picks up the &lt;i&gt;oldest&lt;/i&gt; picothread, i.e. uses FIFO.&amp;nbsp; This is essentially identical to the approach used in the Cilk thread scheduler (see &lt;br /&gt;&lt;a href="http://supertech.csail.mit.edu/papers/steal.pdf" rel="nofollow"&gt;http://supertech.csail.mit.edu/papers/steal.pdf&lt;/a&gt;).&amp;nbsp; Our hypothesis is that it is the stealing of picothreads which is creating the deadlock.&lt;br /&gt;&lt;br /&gt;So how could the stealing of threads create a deadlock?&amp;nbsp; The hypothesized mechanism begins with a server executing a pictothread that gets a lock on an object.&amp;nbsp; This happens when there is a call on an operation with a &lt;b&gt;locked&lt;/b&gt; or &lt;b&gt;queued&lt;/b&gt; parameter, or when an individual &lt;b&gt;concurrent&lt;/b&gt; object (such as the Solutions vector in N-Queens) is passed to an operation where it is not known to be concurrent (such as the "|=" operation in the Vectors module).&amp;nbsp;&lt;br /&gt;&lt;br /&gt;In the virtual machine implementation, getting a lock means acquiring a &lt;i&gt;mutex&lt;/i&gt; or equivalent.&amp;nbsp; This mutex is automatically released when the operation completes.&amp;nbsp; However, suppose the operation has internal parallelism.&amp;nbsp; In ParaSail, parallelism is everywhere, and any operation of any complexity is likely to have some internal parallelism.&amp;nbsp; The "|=" operation is relatively complex, particularly if the underlying array needs to be expanded before adding on another element to the vector.&amp;nbsp; So there is plenty of opportunity for some internal parallelism.&amp;nbsp; That is manifested in the virtual machine by one or more additional picothreads being created and queued on the same server's thread, and then eventually, the server waits for the parallel picothreads to complete.&lt;br /&gt;&lt;br /&gt;As soon as new picothreads show up on the server's queue, other servers may start stealing them.&amp;nbsp; As mentioned above, stealing works FIFO, i.e. oldest first, but if the original server's queue is essentially empty at the moment when a picothread from the locked operation is queued, then it will be the oldest thread on the queue, and so is a candidate for stealing.&amp;nbsp;&amp;nbsp; So let's presume that this new sub-picothread gets stolen.&amp;nbsp; And perhaps that was the only picothread spawned by the original server.&amp;nbsp; When it gets around to waiting for it to complete, it finds it is not yet done, and in fact its own queue is now empty, so it steals from a third server.&amp;nbsp; So now we have our original server thread which is executing a picothread which is waiting for a subthread, going off and stealing work from some random third server's queue.&amp;nbsp; Now let's suppose that the thread on that third server's queue wants to get the original lock.&amp;nbsp; So the original server is now waiting on the lock that it already holds on behalf of some other picothread.&amp;nbsp; A classic tail-chasing deadlock.&amp;nbsp; Pretty soon all of the other servers stack up behind this same lock and everything grinds to a halt.&lt;br /&gt;&lt;br /&gt;So how do we avoid this problem?&amp;nbsp; Fundamentally we don't want a server that is holding a lock, to go off and start executing a thread which is not a sub-thread of the original thread which acquired the lock.&amp;nbsp; If each server and each picothread keeps track of the innermost lock it holds, and locks are chained together so that an inner lock points to the next outer lock, if any, held, then we should be able to avoid the problem.&amp;nbsp; Whenever a server goes looking for a thread, if it holds a lock, then the thread it chooses must also hold that same lock.&amp;nbsp; It might also have some additional lock, but it must, somewhere on the chain of locks starting at the innermost one, have the same lock as that held by the server.&amp;nbsp; This argues for having at least two queues per server, one of picothreads holding no locks, and one of picothreads holding at least one lock.&amp;nbsp; Then when a queue is served by a server holding a lock, either FIFO or LIFO, it will only look at the queue of picothreads holding at least one lock, and it will ignore those on that queue that don't have the server's lock somewhere in their chain of locks.&lt;br /&gt;&lt;br /&gt;Deadlocks are fun -- no doubt about it...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8383004232931899216-1889918825826386772?l=parasail-programming-language.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://parasail-programming-language.blogspot.com/feeds/1889918825826386772/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://parasail-programming-language.blogspot.com/2011/10/deadlocking-virtual-machine.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8383004232931899216/posts/default/1889918825826386772'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8383004232931899216/posts/default/1889918825826386772'/><link rel='alternate' type='text/html' href='http://parasail-programming-language.blogspot.com/2011/10/deadlocking-virtual-machine.html' title='Deadlocking the Virtual Machine'/><author><name>Tuck</name><uri>http://www.blogger.com/profile/08866496974237052847</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8383004232931899216.post-3140725819534190003</id><published>2011-10-03T11:46:00.000-04:00</published><updated>2011-10-03T11:46:42.241-04:00</updated><title type='text'>Alpha release of ParaSail Compiler and Virtual Machine</title><content type='html'>We are very pleased to announce the first, &lt;i&gt;alpha&lt;/i&gt;, release of the &lt;b&gt;ParaSail&lt;/b&gt; prototype &lt;i&gt;Compiler and Virtual Machine&lt;/i&gt;.&amp;nbsp;  This release includes executables for the Mac, Linux, and Windows.&amp;nbsp; Please visit the ParaSail Google Group to download this release:&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;a href="http://groups.google.com/group/parasail-programming-language"&gt;http://groups.google.com/group/parasail-programming-language&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8383004232931899216-3140725819534190003?l=parasail-programming-language.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://parasail-programming-language.blogspot.com/feeds/3140725819534190003/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://parasail-programming-language.blogspot.com/2011/10/alpha-release-of-parasail-compiler-and.html#comment-form' title='8 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8383004232931899216/posts/default/3140725819534190003'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8383004232931899216/posts/default/3140725819534190003'/><link rel='alternate' type='text/html' href='http://parasail-programming-language.blogspot.com/2011/10/alpha-release-of-parasail-compiler-and.html' title='Alpha release of ParaSail Compiler and Virtual Machine'/><author><name>Tuck</name><uri>http://www.blogger.com/profile/08866496974237052847</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8383004232931899216.post-1895349579699593908</id><published>2011-09-14T12:44:00.001-04:00</published><updated>2011-09-14T13:02:25.052-04:00</updated><title type='text'>N Queens Join the Party</title><content type='html'>We are continuing to work on the &lt;b&gt;ParaSail&lt;/b&gt; compiler.  Our latest program to compile and run is a parallel but non-recursive version of a solution to the "N Queens" problem.  There is an N_Queens module, with a nested Solution_State module used to represent a partial solution.  The algorithm starts at column 1 and works toward column N, branching into parallel threads to evaluate each possibility for the next row, and when finding an acceptable one, circling back to the outer loop to march onto the next column.  There is a simple Test_N_Queens &lt;b&gt;func&lt;/b&gt; at the bottom.&amp;nbsp; Below that is the result of running the program.&lt;br /&gt;&lt;br /&gt;Enjoy!&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;b&gt;interface&lt;/b&gt; N_Queens &amp;lt;N : Univ_Integer := 8&amp;gt; &lt;b&gt;is&lt;/b&gt;&lt;br /&gt;    &lt;i&gt;// Place N queens on an NxN checkerboard so that none of them can&lt;/i&gt;&lt;br /&gt;    &lt;i&gt;// "take" each other.&lt;/i&gt;&lt;br /&gt;    &lt;b&gt;type&lt;/b&gt; Chess_Unit &lt;b&gt;is&lt;/b&gt; &lt;b&gt;new&lt;/b&gt; Integer_Range&amp;lt;-100 .. 100&amp;gt;;&lt;br /&gt;        &lt;i&gt;// An integer type sufficiently big to represent values -100 to +100&lt;/i&gt;&lt;br /&gt;    &lt;b&gt;const&lt;/b&gt; Rows : Range&amp;lt;Chess_Unit&amp;gt; := 1..N;&lt;br /&gt;    &lt;b&gt;const&lt;/b&gt; Columns : Range&amp;lt;Chess_Unit&amp;gt; := 1..N;&lt;br /&gt;    &lt;b&gt;type&lt;/b&gt; Row &lt;b&gt;is&lt;/b&gt; Chess_Unit {Row &lt;b&gt;in&lt;/b&gt; Rows};  &lt;i&gt;// A subrange in 1..N&lt;/i&gt;&lt;br /&gt;    &lt;b&gt;type&lt;/b&gt; Column &lt;b&gt;is&lt;/b&gt; Chess_Unit {Column &lt;b&gt;in&lt;/b&gt; Columns};  &lt;i&gt;// A subrange in 1..N&lt;/i&gt;&lt;br /&gt;    &lt;b&gt;type&lt;/b&gt; Solution &lt;b&gt;is&lt;/b&gt; Array&amp;lt;&lt;b&gt;optional&lt;/b&gt; Column, Row&amp;gt;;  &lt;br /&gt;      &lt;i&gt;// A "solution" is an array of Column's, indexed by "Row."&lt;/i&gt;&lt;br /&gt;      &lt;i&gt;// It indicates in which Column a queen of the given Row is located&lt;/i&gt;&lt;br /&gt;      &lt;i&gt;// An example solution would be:  2 8 6 1 3 5 7 4&lt;/i&gt;&lt;br /&gt;      &lt;i&gt;//   meaning that the queen in row 1 is at column 2,&lt;/i&gt;&lt;br /&gt;      &lt;i&gt;//   the queen in row 2 is at column 8, the queen in&lt;/i&gt;&lt;br /&gt;      &lt;i&gt;//   row 3 is at column 6, and so on.&lt;/i&gt;&lt;br /&gt;     &lt;br /&gt;    &lt;b&gt;func&lt;/b&gt; Place_Queens() -&amp;gt; Vector&amp;lt;Solution&amp;gt; &lt;br /&gt;      {&lt;b&gt;for&lt;/b&gt; &lt;b&gt;all&lt;/b&gt; Sol &lt;b&gt;of&lt;/b&gt; Place_Queens =&amp;gt; &lt;b&gt;for&lt;/b&gt; &lt;b&gt;all&lt;/b&gt; Col &lt;b&gt;of&lt;/b&gt; Sol =&amp;gt; Col &lt;b&gt;not&lt;/b&gt; &lt;b&gt;null&lt;/b&gt;};&lt;br /&gt;        &lt;i&gt;// Produce a vector of solutions, with the requirement&lt;/i&gt;&lt;br /&gt;        &lt;i&gt;// that for each solution, there are non-null column numbers&lt;/i&gt;&lt;br /&gt;        &lt;i&gt;// specified for each row of the checkerboard.&lt;/i&gt;&lt;br /&gt;&lt;b&gt;end&lt;/b&gt; &lt;b&gt;interface&lt;/b&gt; N_Queens;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;class&lt;/b&gt; N_Queens &lt;b&gt;is&lt;/b&gt;&lt;br /&gt;    &lt;b&gt;type&lt;/b&gt; Sum_Range &lt;b&gt;is&lt;/b&gt; Chess_Unit {Sum_Range &lt;b&gt;in&lt;/b&gt; 2..2*N};&lt;br /&gt;        &lt;i&gt;// Sum_Range is used for diagonals where the row+column is the&lt;/i&gt;&lt;br /&gt;        &lt;i&gt;// same throughout the diagonal.&lt;/i&gt;&lt;br /&gt;    &lt;b&gt;type&lt;/b&gt; Diff_Range &lt;b&gt;is&lt;/b&gt; Chess_Unit {Diff_Range &lt;b&gt;in&lt;/b&gt; (1-N) .. (N-1)};&lt;br /&gt;        &lt;i&gt;// Diff_Range is used for diagonals where row-column is the&lt;/i&gt;&lt;br /&gt;        &lt;i&gt;// same throughout the diagonal.&lt;/i&gt;&lt;br /&gt;    &lt;b&gt;type&lt;/b&gt; Sum &lt;b&gt;is&lt;/b&gt; Countable_Set&amp;lt;Sum_Range&amp;gt;;&lt;br /&gt;        &lt;i&gt;// This type of set keeps track of which Sum_Range diagonals&lt;/i&gt;&lt;br /&gt;        &lt;i&gt;// have a queen on them already.&lt;/i&gt;&lt;br /&gt;    &lt;b&gt;type&lt;/b&gt; Diff &lt;b&gt;is&lt;/b&gt; Countable_Set&amp;lt;Diff_Range&amp;gt;;&lt;br /&gt;        &lt;i&gt;// This type of set keeps track of which Diff_Range diagonals&lt;/i&gt;&lt;br /&gt;        &lt;i&gt;// have a queen on them already.&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;    &lt;b&gt;interface&lt;/b&gt; Solution_State&amp;lt;&amp;gt; &lt;b&gt;is&lt;/b&gt;&lt;br /&gt;        &lt;i&gt;// We build up a solution state progressively as we move&lt;/i&gt;&lt;br /&gt;        &lt;i&gt;// across the checkerboard, one column at a time.&lt;/i&gt;&lt;br /&gt;        &lt;b&gt;func&lt;/b&gt; Initial_State() -&amp;gt; Solution_State;&lt;br /&gt;        &lt;b&gt;func&lt;/b&gt; Is_Acceptable(S : Solution_State; R : Row) -&amp;gt; Boolean;&lt;br /&gt;          &lt;i&gt;// Is_Acceptable returns True if the next queen could be&lt;/i&gt;&lt;br /&gt;          &lt;i&gt;// place in row R.&lt;/i&gt;&lt;br /&gt;        &lt;b&gt;func&lt;/b&gt; Current_Column(S : Solution_State) -&amp;gt; Column;&lt;br /&gt;          &lt;i&gt;// Current_Column indicates which column we are working on.&lt;/i&gt;&lt;br /&gt;        &lt;b&gt;func&lt;/b&gt; Next_State(S : Solution_State; R : Row) -&amp;gt; Solution_State;&lt;br /&gt;          &lt;i&gt;// Next_State returns a Solution_State produced by&lt;/i&gt;&lt;br /&gt;          &lt;i&gt;// adding a queen at (Current_Column(S), R).&lt;/i&gt;&lt;br /&gt;        &lt;b&gt;func&lt;/b&gt; Final_Result(S : Solution_State; R : Row) -&amp;gt; Solution;&lt;br /&gt;          &lt;i&gt;// Final_Result returns a result produced by adding a queen&lt;/i&gt;&lt;br /&gt;          &lt;i&gt;// at (Columns.Last, R) to a solution with all other columns&lt;/i&gt;&lt;br /&gt;          &lt;i&gt;// placed.&lt;/i&gt;&lt;br /&gt;    &lt;b&gt;end&lt;/b&gt; &lt;b&gt;interface&lt;/b&gt; Solution_State;&lt;br /&gt;&lt;br /&gt;    &lt;b&gt;class&lt;/b&gt; Solution_State &lt;b&gt;is&lt;/b&gt;&lt;br /&gt;        &lt;b&gt;const&lt;/b&gt; C : Column;    &lt;i&gt;// Current column&lt;/i&gt;&lt;br /&gt;        &lt;b&gt;const&lt;/b&gt; Trial : Solution;  &lt;i&gt;// Trial solution, some col#s still null&lt;/i&gt;&lt;br /&gt;        &lt;b&gt;const&lt;/b&gt; Diag_Sum : Sum;   &lt;i&gt;// Set of "sum" diagonals in use&lt;/i&gt;&lt;br /&gt;        &lt;b&gt;const&lt;/b&gt; Diag_Diff : Diff; &lt;i&gt;// Set of "diff" diagnoals in use&lt;/i&gt;&lt;br /&gt;      &lt;b&gt;exports&lt;/b&gt;&lt;br /&gt;        &lt;b&gt;func&lt;/b&gt; Initial_State() -&amp;gt; Solution_State &lt;b&gt;is&lt;/b&gt;&lt;br /&gt;            &lt;b&gt;return&lt;/b&gt; (C =&amp;gt; 1, Trial =&amp;gt; Create(Rows, &lt;b&gt;null&lt;/b&gt;), &lt;br /&gt;              Diag_Sum =&amp;gt; [], Diag_Diff =&amp;gt; []);&lt;br /&gt;        &lt;b&gt;end&lt;/b&gt; &lt;b&gt;func&lt;/b&gt; Initial_State;&lt;br /&gt;&lt;br /&gt;        &lt;b&gt;func&lt;/b&gt; Is_Acceptable(S : Solution_State; R : Row) -&amp;gt; Boolean &lt;b&gt;is&lt;/b&gt;&lt;br /&gt;          &lt;i&gt;// Is_Acceptable returns True if the next queen could be&lt;/i&gt;&lt;br /&gt;          &lt;i&gt;// place in row R.&lt;/i&gt;&lt;br /&gt;            &lt;b&gt;return&lt;/b&gt; S.Trial[R] &lt;b&gt;is&lt;/b&gt; &lt;b&gt;null&lt;/b&gt; &lt;b&gt;and&lt;/b&gt; &lt;b&gt;then&lt;/b&gt;&lt;br /&gt;              (R+S.C) &lt;b&gt;not&lt;/b&gt; &lt;b&gt;in&lt;/b&gt; S.Diag_Sum &lt;b&gt;and&lt;/b&gt; &lt;b&gt;then&lt;/b&gt; &lt;br /&gt;              (R-S.C) &lt;b&gt;not&lt;/b&gt; &lt;b&gt;in&lt;/b&gt; S.Diag_Diff;&lt;br /&gt;        &lt;b&gt;end&lt;/b&gt; &lt;b&gt;func&lt;/b&gt; Is_Acceptable;&lt;br /&gt;        &lt;br /&gt;        &lt;b&gt;func&lt;/b&gt; Current_Column(S : Solution_State) -&amp;gt; Column &lt;b&gt;is&lt;/b&gt;&lt;br /&gt;          &lt;i&gt;// Current_Column indicates which column we are working on.&lt;/i&gt;&lt;br /&gt;            &lt;b&gt;return&lt;/b&gt; S.C;&lt;br /&gt;        &lt;b&gt;end&lt;/b&gt; &lt;b&gt;func&lt;/b&gt; Current_Column;&lt;br /&gt;&lt;br /&gt;        &lt;b&gt;func&lt;/b&gt; Next_State(S : Solution_State; R : Row) -&amp;gt; Solution_State &lt;b&gt;is&lt;/b&gt;&lt;br /&gt;          &lt;i&gt;// Next_State returns a Solution_State produced by&lt;/i&gt;&lt;br /&gt;          &lt;i&gt;// adding a queen at (Current_Column(S), R).&lt;/i&gt;&lt;br /&gt;            &lt;b&gt;return&lt;/b&gt; (C =&amp;gt; S.C+1, &lt;br /&gt;              Trial     =&amp;gt; S.Trial | [R =&amp;gt; S.C],&lt;br /&gt;              Diag_Sum  =&amp;gt; S.Diag_Sum | (R+S.C),&lt;br /&gt;              Diag_Diff =&amp;gt; S.Diag_Diff | (R-S.C));&lt;br /&gt;        &lt;b&gt;end&lt;/b&gt; &lt;b&gt;func&lt;/b&gt; Next_State;&lt;br /&gt;&lt;br /&gt;        &lt;b&gt;func&lt;/b&gt; Final_Result(S : Solution_State; R : Row) -&amp;gt; Solution &lt;b&gt;is&lt;/b&gt;&lt;br /&gt;          &lt;i&gt;// Final_Result returns a result produced by adding a queen&lt;/i&gt;&lt;br /&gt;          &lt;i&gt;// at (Columns.Last, R) to a solution with all other columns&lt;/i&gt;&lt;br /&gt;          &lt;i&gt;// placed.&lt;/i&gt;&lt;br /&gt;            &lt;b&gt;return&lt;/b&gt; S.Trial | [R =&amp;gt; S.C];&lt;br /&gt;        &lt;b&gt;end&lt;/b&gt; &lt;b&gt;func&lt;/b&gt; Final_Result;&lt;br /&gt;&lt;br /&gt;    &lt;b&gt;end&lt;/b&gt; &lt;b&gt;class&lt;/b&gt; Solution_State;&lt;br /&gt;&lt;br /&gt;  &lt;b&gt;exports&lt;/b&gt;&lt;br /&gt;    &lt;b&gt;func&lt;/b&gt; Place_Queens() -&amp;gt; Vector&amp;lt;Solution&amp;gt; &lt;br /&gt;      {&lt;b&gt;for&lt;/b&gt; &lt;b&gt;all&lt;/b&gt; Sol &lt;b&gt;of&lt;/b&gt; Place_Queens =&amp;gt; &lt;b&gt;for&lt;/b&gt; &lt;b&gt;all&lt;/b&gt; Col &lt;b&gt;of&lt;/b&gt; Sol =&amp;gt; Col &lt;b&gt;not&lt;/b&gt; &lt;b&gt;null&lt;/b&gt;}&lt;br /&gt;        &lt;i&gt;// Produce a vector of solutions, with the requirement&lt;/i&gt;&lt;br /&gt;        &lt;i&gt;// that for each solution, there are non-null column numbers&lt;/i&gt;&lt;br /&gt;        &lt;i&gt;// specified for each row of the checkerboard.&lt;/i&gt;&lt;br /&gt;    &lt;b&gt;is&lt;/b&gt;&lt;br /&gt;      &lt;b&gt;var&lt;/b&gt; Solutions : &lt;b&gt;concurrent&lt;/b&gt; Vector&amp;lt;Solution&amp;gt; := [];&lt;br /&gt;      &lt;br /&gt;     *Outer_Loop*&lt;br /&gt;      &lt;b&gt;for&lt;/b&gt; State : Solution_State := Initial_State() &lt;b&gt;loop&lt;/b&gt;&lt;br /&gt;          &lt;i&gt;// Iterate over the columns&lt;/i&gt;&lt;br /&gt;        &lt;br /&gt;          &lt;b&gt;for&lt;/b&gt; R &lt;b&gt;in&lt;/b&gt; Rows &lt;b&gt;concurrent&lt;/b&gt; &lt;b&gt;loop&lt;/b&gt;&lt;br /&gt;              &lt;i&gt;// Iterate over the rows&lt;/i&gt;&lt;br /&gt;              &lt;b&gt;if&lt;/b&gt; Is_Acceptable(State, R) &lt;b&gt;then&lt;/b&gt;&lt;br /&gt;                  &lt;i&gt;// Found a Row/Column combination that is not on any diagonal&lt;/i&gt;&lt;br /&gt;                  &lt;i&gt;// already occupied.&lt;/i&gt;&lt;br /&gt;                  &lt;b&gt;if&lt;/b&gt; Current_Column(State) &amp;lt; N &lt;b&gt;then&lt;/b&gt;&lt;br /&gt;                      &lt;i&gt;// Keep going since haven't reached Nth column.&lt;/i&gt;&lt;br /&gt;                      &lt;b&gt;continue&lt;/b&gt; &lt;b&gt;loop&lt;/b&gt; Outer_Loop &lt;b&gt;with&lt;/b&gt; Next_State(State, R);&lt;br /&gt;                  &lt;b&gt;else&lt;/b&gt;&lt;br /&gt;                      &lt;i&gt;// All done, remember trial result with last queen placed&lt;/i&gt;&lt;br /&gt;                      Solutions |= Final_Result(State, R); &lt;br /&gt;                  &lt;b&gt;end&lt;/b&gt; &lt;b&gt;if&lt;/b&gt;;&lt;br /&gt;              &lt;b&gt;end&lt;/b&gt; &lt;b&gt;if&lt;/b&gt;;&lt;br /&gt;          &lt;b&gt;end&lt;/b&gt; &lt;b&gt;loop&lt;/b&gt;;&lt;br /&gt;      &lt;b&gt;end&lt;/b&gt; &lt;b&gt;loop&lt;/b&gt; Outer_Loop;&lt;br /&gt;      &lt;b&gt;return&lt;/b&gt; Solutions;&lt;br /&gt;      &lt;br /&gt;    &lt;b&gt;end&lt;/b&gt; &lt;b&gt;func&lt;/b&gt; Place_Queens;&lt;br /&gt;&lt;b&gt;end&lt;/b&gt; &lt;b&gt;class&lt;/b&gt; N_Queens;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;func&lt;/b&gt; Test_N_Queens() &lt;b&gt;is&lt;/b&gt;&lt;br /&gt;    &lt;b&gt;type&lt;/b&gt; Eight_Queens &lt;b&gt;is&lt;/b&gt; N_Queens&amp;lt;8&amp;gt;;&lt;br /&gt;    &lt;b&gt;var&lt;/b&gt; Results := Eight_Queens::Place_Queens();&lt;br /&gt;    Println("Number of results = " | Length(Results));&lt;br /&gt;    &lt;b&gt;for&lt;/b&gt; I &lt;b&gt;in&lt;/b&gt; 1..Length(Results) &lt;b&gt;forward&lt;/b&gt; &lt;b&gt;loop&lt;/b&gt;&lt;br /&gt;        &lt;b&gt;const&lt;/b&gt; Result := Results[I];&lt;br /&gt;        Print("Result #" | I);&lt;br /&gt;        &lt;b&gt;for&lt;/b&gt; J &lt;b&gt;in&lt;/b&gt; 1..Length(Result) &lt;b&gt;forward&lt;/b&gt; &lt;b&gt;loop&lt;/b&gt;&lt;br /&gt;            Print(" " | [[Result[J]]]);&lt;br /&gt;        &lt;b&gt;end&lt;/b&gt; &lt;b&gt;loop&lt;/b&gt;;&lt;br /&gt;        Print('\n');&lt;br /&gt;    &lt;b&gt;end&lt;/b&gt; &lt;b&gt;loop&lt;/b&gt;;&lt;br /&gt;&lt;b&gt;end&lt;/b&gt; &lt;b&gt;func&lt;/b&gt; Test_N_Queens;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Here is the result of running Test_N_Queens, which is set up to solve the 8-queens problem.  It has also been verified to work with 4 queens (2 solutions), 5 queens (10 solutions), and 9 queens (352 solutions).  After "quit"ing, a display of threading statistics is provided.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;Parsing aaa.psi&lt;br /&gt;Parsing n_queens4.psl&lt;br /&gt;---- Beginning semantic analysis ----&lt;br /&gt; 58 trees in library.&lt;br /&gt;Done with First pass.&lt;br /&gt;Done with Second pass.&lt;br /&gt;Done with Pre codegen pass.&lt;br /&gt;Done with Code gen.&lt;br /&gt;&lt;br /&gt;Command to execute: Test_N_Queens&lt;br /&gt;&lt;br /&gt;Number of results = 92&lt;br /&gt;Result #1 4 2 5 8 6 1 3 7&lt;br /&gt;Result #2 1 7 4 6 8 2 5 3&lt;br /&gt;Result #3 4 2 8 5 7 1 3 6&lt;br /&gt;Result #4 1 5 8 6 3 7 2 4&lt;br /&gt;Result #5 4 1 5 8 6 3 7 2&lt;br /&gt;Result #6 2 7 3 6 8 5 1 4&lt;br /&gt;Result #7 7 1 3 8 6 4 2 5&lt;br /&gt;Result #8 5 2 4 6 8 3 1 7&lt;br /&gt;Result #9 5 7 1 3 8 6 4 2&lt;br /&gt;Result #10 5 1 8 6 3 7 2 4&lt;br /&gt;Result #11 1 6 8 3 7 4 2 5&lt;br /&gt;Result #12 4 2 7 3 6 8 1 5&lt;br /&gt;Result #13 3 1 7 5 8 2 4 6&lt;br /&gt;Result #14 3 6 2 7 5 1 8 4&lt;br /&gt;Result #15 5 1 4 6 8 2 7 3&lt;br /&gt;Result #16 6 4 2 8 5 7 1 3&lt;br /&gt;Result #17 3 6 2 5 8 1 7 4&lt;br /&gt;Result #18 1 7 5 8 2 4 6 3&lt;br /&gt;Result #19 3 7 2 8 5 1 4 6&lt;br /&gt;Result #20 2 6 1 7 4 8 3 5&lt;br /&gt;Result #21 3 7 2 8 6 4 1 5&lt;br /&gt;Result #22 4 6 8 2 7 1 3 5&lt;br /&gt;Result #23 4 1 5 8 2 7 3 6&lt;br /&gt;Result #24 7 4 2 8 6 1 3 5&lt;br /&gt;Result #25 3 6 8 2 4 1 7 5&lt;br /&gt;Result #26 5 1 8 4 2 7 3 6&lt;br /&gt;Result #27 7 4 2 5 8 1 3 6&lt;br /&gt;Result #28 4 7 5 2 6 1 3 8&lt;br /&gt;Result #29 7 3 8 2 5 1 6 4&lt;br /&gt;Result #30 5 7 2 6 3 1 8 4&lt;br /&gt;Result #31 5 7 2 4 8 1 3 6&lt;br /&gt;Result #32 4 7 3 8 2 5 1 6&lt;br /&gt;Result #33 4 7 1 8 5 2 6 3&lt;br /&gt;Result #34 7 3 1 6 8 5 2 4&lt;br /&gt;Result #35 6 3 7 2 8 5 1 4&lt;br /&gt;Result #36 6 1 5 2 8 3 7 4&lt;br /&gt;Result #37 4 8 1 5 7 2 6 3&lt;br /&gt;Result #38 6 3 1 7 5 8 2 4&lt;br /&gt;Result #39 6 3 7 2 4 8 1 5&lt;br /&gt;Result #40 6 4 1 5 8 2 7 3&lt;br /&gt;Result #41 5 7 2 6 3 1 4 8&lt;br /&gt;Result #42 5 7 1 4 2 8 6 3&lt;br /&gt;Result #43 3 5 2 8 1 7 4 6&lt;br /&gt;Result #44 4 6 1 5 2 8 3 7&lt;br /&gt;Result #45 2 7 5 8 1 4 6 3&lt;br /&gt;Result #46 5 3 1 6 8 2 4 7&lt;br /&gt;Result #47 4 2 7 5 1 8 6 3&lt;br /&gt;Result #48 6 3 1 8 5 2 4 7&lt;br /&gt;Result #49 3 8 4 7 1 6 2 5&lt;br /&gt;Result #50 6 8 2 4 1 7 5 3&lt;br /&gt;Result #51 5 3 1 7 2 8 6 4&lt;br /&gt;Result #52 2 5 7 4 1 8 6 3&lt;br /&gt;Result #53 3 6 2 7 1 4 8 5&lt;br /&gt;Result #54 6 3 1 8 4 2 7 5&lt;br /&gt;Result #55 4 2 8 6 1 3 5 7&lt;br /&gt;Result #56 8 3 1 6 2 5 7 4&lt;br /&gt;Result #57 3 5 8 4 1 7 2 6&lt;br /&gt;Result #58 4 8 1 3 6 2 7 5&lt;br /&gt;Result #59 6 3 5 8 1 4 2 7&lt;br /&gt;Result #60 6 3 7 4 1 8 2 5&lt;br /&gt;Result #61 8 4 1 3 6 2 7 5&lt;br /&gt;Result #62 8 2 5 3 1 7 4 6&lt;br /&gt;Result #63 6 3 5 7 1 4 2 8&lt;br /&gt;Result #64 4 8 5 3 1 7 2 6&lt;br /&gt;Result #65 7 2 6 3 1 4 8 5&lt;br /&gt;Result #66 2 4 6 8 3 1 7 5&lt;br /&gt;Result #67 5 2 4 7 3 8 6 1&lt;br /&gt;Result #68 3 5 2 8 6 4 7 1&lt;br /&gt;Result #69 4 6 8 3 1 7 5 2&lt;br /&gt;Result #70 4 7 5 3 1 6 8 2&lt;br /&gt;Result #71 3 6 4 2 8 5 7 1&lt;br /&gt;Result #72 2 6 8 3 1 4 7 5&lt;br /&gt;Result #73 5 7 4 1 3 8 6 2&lt;br /&gt;Result #74 7 5 3 1 6 8 2 4&lt;br /&gt;Result #75 4 2 7 3 6 8 5 1&lt;br /&gt;Result #76 6 4 7 1 8 2 5 3&lt;br /&gt;Result #77 5 2 6 1 7 4 8 3&lt;br /&gt;Result #78 7 2 4 1 8 5 3 6&lt;br /&gt;Result #79 6 2 7 1 3 5 8 4&lt;br /&gt;Result #80 8 2 4 1 7 5 3 6&lt;br /&gt;Result #81 3 6 8 1 5 7 2 4&lt;br /&gt;Result #82 5 2 8 1 4 7 3 6&lt;br /&gt;Result #83 5 3 8 4 7 1 6 2&lt;br /&gt;Result #84 3 6 8 1 4 7 5 2&lt;br /&gt;Result #85 5 8 4 1 7 2 6 3&lt;br /&gt;Result #86 3 6 4 1 8 5 7 2&lt;br /&gt;Result #87 3 5 7 1 4 2 8 6&lt;br /&gt;Result #88 6 2 7 1 4 8 5 3&lt;br /&gt;Result #89 6 4 7 1 3 5 2 8&lt;br /&gt;Result #90 5 8 4 1 3 6 2 7&lt;br /&gt;Result #91 2 5 7 1 3 8 6 4&lt;br /&gt;Result #92 2 8 6 1 3 5 7 4&lt;br /&gt;&lt;br /&gt;Command to execute: quit&lt;br /&gt;&lt;br /&gt;Threading Statistics:&lt;br /&gt; Num_Initial_Thread_Servers : 10&lt;br /&gt; Num_Dynamically_Allocated_Thread_Servers : 0&lt;br /&gt; Max_Waiting_Threads (for server task): 74&lt;br /&gt; Max_Active : 118&lt;br /&gt; Max_Active_Masters : 133&lt;br /&gt; Max_Sub_Threads_Per_Master : 87&lt;br /&gt; Max_Waiting_For_Threads (to finish): 37171&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8383004232931899216-1895349579699593908?l=parasail-programming-language.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://parasail-programming-language.blogspot.com/feeds/1895349579699593908/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://parasail-programming-language.blogspot.com/2011/09/n-queens-join-party.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8383004232931899216/posts/default/1895349579699593908'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8383004232931899216/posts/default/1895349579699593908'/><link rel='alternate' type='text/html' href='http://parasail-programming-language.blogspot.com/2011/09/n-queens-join-party.html' title='N Queens Join the Party'/><author><name>Tuck</name><uri>http://www.blogger.com/profile/08866496974237052847</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8383004232931899216.post-3623210585256019287</id><published>2011-09-08T15:04:00.000-04:00</published><updated>2011-09-08T15:04:28.139-04:00</updated><title type='text'>Another ParaSail example that compiles and runs</title><content type='html'>Here is a version of parallel Quicksort that now compiles and runs through the &lt;b&gt;ParaSail&lt;/b&gt; compiler.  This is parallel but non-recursive.  It uses a parallel pair of &lt;b&gt;continue loop&lt;/b&gt; statements rather than recursion.&amp;nbsp; It uses "slicing" on the array.&amp;nbsp; &lt;b&gt;A[..]&lt;/b&gt; takes an array and returns a "slice" of the array that contains all elements of the array.&amp;nbsp; After partitioning the array, the code splits into two threads and then continues with a left "slice" and a right "slice" of the array.&amp;nbsp; The "&lt;b&gt;&amp;lt;=&amp;gt;&lt;/b&gt;" operator performs a swap operation.&lt;br /&gt;&lt;br /&gt;There is a simple Test_Sort test function at the bottom.&amp;nbsp; It uses a very simple random number generator to populate an array and then sort it (twice).&lt;br /&gt;&lt;br /&gt;At the very bottom we have the result of running the program.&lt;br /&gt;&lt;pre&gt;&lt;b&gt;interface&lt;/b&gt; Sorting&amp;lt;Array_Type &lt;b&gt;is&lt;/b&gt; Indexable&amp;lt;Comparable&amp;lt;&amp;gt;, Countable&amp;lt;&amp;gt;&amp;gt;&amp;gt; &lt;b&gt;is&lt;/b&gt;&lt;br /&gt;    &lt;b&gt;func&lt;/b&gt; Quicksort(&lt;b&gt;var&lt;/b&gt; A : Array_Type);&lt;br /&gt;          &lt;i&gt;// Sort Arr according to the sorting op "&amp;lt;" which returns&lt;/i&gt;&lt;br /&gt;          &lt;i&gt;// True if Left must appear before Right in the sorted order.&lt;/i&gt;&lt;br /&gt;          &lt;i&gt;// Before returns False if Left = Right.&lt;/i&gt;&lt;br /&gt;&lt;b&gt;end&lt;/b&gt; &lt;b&gt;interface&lt;/b&gt; Sorting;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;class&lt;/b&gt; Sorting &lt;b&gt;is&lt;/b&gt;&lt;br /&gt;  &lt;b&gt;exports&lt;/b&gt;&lt;br /&gt;    &lt;b&gt;func&lt;/b&gt; Quicksort(&lt;b&gt;var&lt;/b&gt; A : Array_Type) &lt;b&gt;is&lt;/b&gt;&lt;br /&gt;        &lt;i&gt;// Handle short arrays directly.  Partition longer arrays.&lt;/i&gt;&lt;br /&gt;        &lt;b&gt;for&lt;/b&gt; Arr : Slice&amp;lt;Array_Type&amp;gt; =&amp;gt; A[..] &lt;b&gt;while&lt;/b&gt; Length(Arr) &amp;gt; 1 &lt;b&gt;loop&lt;/b&gt;&lt;br /&gt;            &lt;b&gt;if&lt;/b&gt; Length(Arr) == 2 &lt;b&gt;then&lt;/b&gt;&lt;br /&gt;               &lt;b&gt;if&lt;/b&gt; Arr[Arr.Last] &amp;lt; Arr[Arr.First] &lt;b&gt;then&lt;/b&gt;&lt;br /&gt;                   &lt;i&gt;// Swap elements&lt;/i&gt;&lt;br /&gt;                   Arr[Arr.First] &amp;lt;=&amp;gt; Arr[Arr.Last];&lt;br /&gt;               &lt;b&gt;end&lt;/b&gt; &lt;b&gt;if&lt;/b&gt;;&lt;br /&gt;            &lt;b&gt;else&lt;/b&gt;&lt;br /&gt;               &lt;i&gt;// Partition array&lt;/i&gt;&lt;br /&gt;               &lt;b&gt;const&lt;/b&gt; Mid := Arr[Arr.First + Length(Arr)/2];&lt;br /&gt;               &lt;b&gt;var&lt;/b&gt; Left := Arr.First;&lt;br /&gt;               &lt;b&gt;var&lt;/b&gt; Right := Arr.Last;&lt;br /&gt;               &lt;b&gt;until&lt;/b&gt; Left &amp;gt; Right &lt;b&gt;loop&lt;/b&gt;&lt;br /&gt;                 &lt;b&gt;var&lt;/b&gt; New_Left := Right+1;&lt;br /&gt;                 &lt;b&gt;var&lt;/b&gt; New_Right := Left-1;&lt;br /&gt;                 &lt;b&gt;block&lt;/b&gt;&lt;br /&gt;                   &lt;i&gt;// Find item in left half to swap&lt;/i&gt;&lt;br /&gt;                   &lt;b&gt;for&lt;/b&gt; I &lt;b&gt;in&lt;/b&gt; Left .. Right &lt;b&gt;forward&lt;/b&gt; &lt;b&gt;loop&lt;/b&gt;&lt;br /&gt;                       &lt;b&gt;if&lt;/b&gt; &lt;b&gt;not&lt;/b&gt; (Arr[I] &amp;lt; Mid) &lt;b&gt;then&lt;/b&gt;&lt;br /&gt;                           &lt;i&gt;// Found an item that can go into right partitition&lt;/i&gt;&lt;br /&gt;                           New_Left := I;&lt;br /&gt;                           &lt;b&gt;if&lt;/b&gt; Mid &amp;lt; Arr[I] &lt;b&gt;then&lt;/b&gt;&lt;br /&gt;                               &lt;i&gt;// Found an item that *must* go into right part&lt;/i&gt;&lt;br /&gt;                               &lt;b&gt;exit&lt;/b&gt; &lt;b&gt;loop&lt;/b&gt;;&lt;br /&gt;                           &lt;b&gt;end&lt;/b&gt; &lt;b&gt;if&lt;/b&gt;;&lt;br /&gt;                       &lt;b&gt;end&lt;/b&gt; &lt;b&gt;if&lt;/b&gt;;&lt;br /&gt;                   &lt;b&gt;end&lt;/b&gt; &lt;b&gt;loop&lt;/b&gt;;&lt;br /&gt;                 ||  &lt;br /&gt;                   &lt;i&gt;// Find item in right half to swap&lt;/i&gt;&lt;br /&gt;                   &lt;b&gt;for&lt;/b&gt; J &lt;b&gt;in&lt;/b&gt; Left .. Right &lt;b&gt;reverse&lt;/b&gt; &lt;b&gt;loop&lt;/b&gt;&lt;br /&gt;                       &lt;b&gt;if&lt;/b&gt; &lt;b&gt;not&lt;/b&gt; (Mid &amp;lt; Arr[J]) &lt;b&gt;then&lt;/b&gt;&lt;br /&gt;                           &lt;i&gt;// Found an item that can go into left partitition&lt;/i&gt;&lt;br /&gt;                           New_Right := J;&lt;br /&gt;                           &lt;b&gt;if&lt;/b&gt; Arr[J] &amp;lt; Mid &lt;b&gt;then&lt;/b&gt;&lt;br /&gt;                               &lt;i&gt;// Found an item that *must* go into left part&lt;/i&gt;&lt;br /&gt;                               &lt;b&gt;exit&lt;/b&gt; &lt;b&gt;loop&lt;/b&gt;;&lt;br /&gt;                           &lt;b&gt;end&lt;/b&gt; &lt;b&gt;if&lt;/b&gt;;&lt;br /&gt;                       &lt;b&gt;end&lt;/b&gt; &lt;b&gt;if&lt;/b&gt;;&lt;br /&gt;                   &lt;b&gt;end&lt;/b&gt; &lt;b&gt;loop&lt;/b&gt;;&lt;br /&gt;                 &lt;b&gt;end&lt;/b&gt; &lt;b&gt;block&lt;/b&gt;;&lt;br /&gt;                 &lt;br /&gt;                 &lt;b&gt;if&lt;/b&gt; New_Left &amp;gt; New_Right &lt;b&gt;then&lt;/b&gt;&lt;br /&gt;                     &lt;i&gt;// Nothing more to swap&lt;/i&gt;&lt;br /&gt;                     &lt;i&gt;// Exit loop and recurse on two partitions&lt;/i&gt;&lt;br /&gt;                     Left := New_Left;&lt;br /&gt;                     Right := New_Right;&lt;br /&gt;                     &lt;b&gt;exit&lt;/b&gt; &lt;b&gt;loop&lt;/b&gt;;&lt;br /&gt;                 &lt;b&gt;end&lt;/b&gt; &lt;b&gt;if&lt;/b&gt;;&lt;br /&gt;                 &lt;br /&gt;                 &lt;i&gt;// Swap items&lt;/i&gt;&lt;br /&gt;                 Arr[New_Left] &amp;lt;=&amp;gt; Arr[New_Right];&lt;br /&gt;                 &lt;br /&gt;                 &lt;i&gt;// continue looking for items to swap&lt;/i&gt;&lt;br /&gt;                 Left := New_Left + 1;&lt;br /&gt;                 Right := New_Right - 1;&lt;br /&gt;               &lt;b&gt;end&lt;/b&gt; &lt;b&gt;loop&lt;/b&gt;;&lt;br /&gt;               &lt;br /&gt;               &lt;i&gt;// At this point, "Right" is right end of left partition&lt;/i&gt;&lt;br /&gt;               &lt;i&gt;// and "Left" is left end of right partition&lt;/i&gt;&lt;br /&gt;               &lt;i&gt;// and the partitions don't overlap&lt;/i&gt;&lt;br /&gt;               &lt;i&gt;// and neither is the whole array&lt;/i&gt;&lt;br /&gt;               &lt;i&gt;// and everything in the left partition can precede Mid&lt;/i&gt;&lt;br /&gt;               &lt;i&gt;// and everything in the right partition can follow Mid&lt;/i&gt;&lt;br /&gt;               &lt;i&gt;// and everything between the partitions is equal to Mid.&lt;/i&gt;&lt;br /&gt;               {Left &amp;gt; Right;&lt;br /&gt;                Right &amp;lt; Arr.Last;&lt;br /&gt;                Left &amp;gt; Arr.First;&lt;br /&gt;                (&lt;b&gt;for&lt;/b&gt; &lt;b&gt;all&lt;/b&gt; I &lt;b&gt;in&lt;/b&gt; Arr.First .. Right =&amp;gt; &lt;b&gt;not&lt;/b&gt; (Mid &amp;lt; Arr[I]));&lt;br /&gt;                (&lt;b&gt;for&lt;/b&gt; &lt;b&gt;all&lt;/b&gt; J &lt;b&gt;in&lt;/b&gt; Left .. Arr.Last =&amp;gt; &lt;b&gt;not&lt;/b&gt; (Arr[J] &amp;lt; Mid));&lt;br /&gt;                (&lt;b&gt;for&lt;/b&gt; &lt;b&gt;all&lt;/b&gt; K &lt;b&gt;in&lt;/b&gt; Right+1 .. Left-1 =&amp;gt; &lt;br /&gt;                  &lt;b&gt;not&lt;/b&gt; (Mid &amp;lt; Arr[K]) &lt;b&gt;and&lt;/b&gt; &lt;b&gt;not&lt;/b&gt; (Arr[K] &amp;lt; Mid))}&lt;br /&gt;               &lt;br /&gt;             &lt;b&gt;then&lt;/b&gt;&lt;br /&gt;               &lt;i&gt;// continue with two halves in parallel&lt;/i&gt;&lt;br /&gt;               &lt;b&gt;continue&lt;/b&gt; &lt;b&gt;loop&lt;/b&gt; &lt;b&gt;with&lt;/b&gt; Arr[Arr.First .. Right];&lt;br /&gt;             ||&lt;br /&gt;               &lt;b&gt;continue&lt;/b&gt; &lt;b&gt;loop&lt;/b&gt; &lt;b&gt;with&lt;/b&gt; Arr[Left .. Arr.Last];&lt;br /&gt;            &lt;b&gt;end&lt;/b&gt; &lt;b&gt;if&lt;/b&gt;;&lt;br /&gt;        &lt;b&gt;end&lt;/b&gt; &lt;b&gt;loop&lt;/b&gt;;&lt;br /&gt;   &lt;b&gt;end&lt;/b&gt; &lt;b&gt;func&lt;/b&gt; Quicksort;&lt;br /&gt;&lt;b&gt;end&lt;/b&gt; &lt;b&gt;class&lt;/b&gt; Sorting;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;func&lt;/b&gt; Random(&lt;b&gt;var&lt;/b&gt; Seed : Univ_Integer; Mult, Mod : Univ_Integer) &lt;br /&gt;  -&amp;gt; Univ_Integer &lt;b&gt;is&lt;/b&gt;&lt;br /&gt;    Seed := Seed * Mult &lt;b&gt;mod&lt;/b&gt; Mod;&lt;br /&gt;    &lt;b&gt;return&lt;/b&gt; Seed;&lt;br /&gt;&lt;b&gt;end&lt;/b&gt; &lt;b&gt;func&lt;/b&gt; Random;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;func&lt;/b&gt; Test_Sort(Len : Univ_Integer) &lt;b&gt;is&lt;/b&gt;&lt;br /&gt;    &lt;i&gt;// For Random&lt;/i&gt;&lt;br /&gt;    &lt;b&gt;const&lt;/b&gt; Mult := 7**5;&lt;br /&gt;    &lt;b&gt;const&lt;/b&gt; Mod := 2**31 - 1;&lt;br /&gt;    &lt;b&gt;var&lt;/b&gt; Seed := Len;&lt;br /&gt;    Println("Seed = " | Seed | ", Mult = " | Mult | ", Mod = " | Mod);&lt;br /&gt;&lt;br /&gt;    &lt;b&gt;type&lt;/b&gt; My_Sorter &lt;b&gt;is&lt;/b&gt; Sorting&amp;lt;Vector&amp;lt;Univ_Integer&amp;gt;&amp;gt;;&lt;br /&gt;    &lt;b&gt;var&lt;/b&gt; Vec : Vector&amp;lt;Univ_Integer&amp;gt; := [];&lt;br /&gt;&lt;br /&gt;    &lt;b&gt;for&lt;/b&gt; I &lt;b&gt;in&lt;/b&gt; 1..Len &lt;b&gt;loop&lt;/b&gt;&lt;br /&gt;        Vec |= Random(Seed, Mult, Mod) &lt;b&gt;mod&lt;/b&gt; 100;&lt;br /&gt;    &lt;b&gt;end&lt;/b&gt; &lt;b&gt;loop&lt;/b&gt;;&lt;br /&gt;&lt;br /&gt;    &lt;b&gt;var&lt;/b&gt; Vec2 := Vec;&lt;br /&gt;&lt;br /&gt;    Println("Before sort, Vec = ");&lt;br /&gt;    &lt;b&gt;for&lt;/b&gt; I &lt;b&gt;in&lt;/b&gt; 1 .. Length(Vec) &lt;b&gt;forward&lt;/b&gt; &lt;b&gt;loop&lt;/b&gt;&lt;br /&gt;        Print(" " | Vec[I]);&lt;br /&gt;        &lt;b&gt;if&lt;/b&gt; I &amp;lt; Length(Vec) &lt;b&gt;then&lt;/b&gt;&lt;br /&gt;            Print(",");&lt;br /&gt;        &lt;b&gt;end&lt;/b&gt; &lt;b&gt;if&lt;/b&gt;;&lt;br /&gt;    &lt;b&gt;end&lt;/b&gt; &lt;b&gt;loop&lt;/b&gt;;&lt;br /&gt;    Print("\n");&lt;br /&gt;&lt;br /&gt;    My_Sorter::Quicksort(Vec);&lt;br /&gt;&lt;br /&gt;    Println("After sort, Vec = ");&lt;br /&gt;    &lt;b&gt;for&lt;/b&gt; I &lt;b&gt;in&lt;/b&gt; 1 .. Length(Vec) &lt;b&gt;forward&lt;/b&gt; &lt;b&gt;loop&lt;/b&gt;&lt;br /&gt;        Print(" " | Vec[I]);&lt;br /&gt;        &lt;b&gt;if&lt;/b&gt; I &amp;lt; Length(Vec) &lt;b&gt;then&lt;/b&gt;&lt;br /&gt;            Print(",");&lt;br /&gt;        &lt;b&gt;end&lt;/b&gt; &lt;b&gt;if&lt;/b&gt;;&lt;br /&gt;    &lt;b&gt;end&lt;/b&gt; &lt;b&gt;loop&lt;/b&gt;;&lt;br /&gt;    Print("\n");&lt;br /&gt;&lt;br /&gt;    My_Sorter::Quicksort(Vec2);&lt;br /&gt;&lt;br /&gt;    Println("After 2nd sort, Vec2 = ");&lt;br /&gt;    &lt;b&gt;for&lt;/b&gt; I &lt;b&gt;in&lt;/b&gt; 1 .. Length(Vec2) &lt;b&gt;forward&lt;/b&gt; &lt;b&gt;loop&lt;/b&gt;&lt;br /&gt;        Print(" " | Vec2[I]);&lt;br /&gt;        &lt;b&gt;if&lt;/b&gt; I &amp;lt; Length(Vec2) &lt;b&gt;then&lt;/b&gt;&lt;br /&gt;            Print(",");&lt;br /&gt;        &lt;b&gt;end&lt;/b&gt; &lt;b&gt;if&lt;/b&gt;;&lt;br /&gt;    &lt;b&gt;end&lt;/b&gt; &lt;b&gt;loop&lt;/b&gt;;&lt;br /&gt;    Print("\n");&lt;br /&gt;&lt;br /&gt;&lt;b&gt;end&lt;/b&gt; &lt;b&gt;func&lt;/b&gt; Test_Sort;&lt;br /&gt;&lt;/pre&gt;Here is the result of compiling and running the program.  "aaa.psi" contains the standard ParaSail library of modules.  "qsort6.psl" is given above.  We are using the compiler interactively here, so we can run stand-alone ParaSail operations.  It also can run non-interactively, by giving "-command &amp;lt;operation&amp;gt; &amp;lt;param1&amp;gt; ..." after the list of source file names on the command line.  When in interactive mode, it dumps out some virtual machine threading statistics after the user "quit"s.  These are at the very bottom.  In this example, we have 21 threads active simultaneously at one point during execution.&lt;br /&gt;&lt;pre&gt;% pslc aaa.psi qsort6.psl&lt;br /&gt;Parsing aaa.psi&lt;br /&gt;Parsing qsort6.psl&lt;br /&gt;---- Beginning semantic analysis ----&lt;br /&gt; 52 trees in library.&lt;br /&gt;Done with First pass.&lt;br /&gt;Done with Second pass.&lt;br /&gt;Done with Pre codegen pass.&lt;br /&gt;Done with Code gen.&lt;br /&gt;Command to execute: Test_Sort 20&lt;br /&gt;&lt;br /&gt;Seed = 20, Mult = 16807, Mod = 2147483647&lt;br /&gt;Before sort, Vec = &lt;br /&gt; 40, 86, 55, 37, 30, 52, 80, 49, 49, 34, 71, 30, 88, 40, 93, 90, 29, 80, 71, 93&lt;br /&gt;After sort, Vec = &lt;br /&gt; 29, 30, 30, 34, 37, 40, 40, 49, 49, 52, 55, 71, 71, 80, 80, 86, 88, 90, 93, 93&lt;br /&gt;After 2nd sort, Vec2 = &lt;br /&gt; 29, 30, 30, 34, 37, 40, 40, 49, 49, 52, 55, 71, 71, 80, 80, 86, 88, 90, 93, 93&lt;br /&gt;Command to execute: quit&lt;br /&gt;&lt;br /&gt;Threading Statistics:&lt;br /&gt; Num_Initial_Thread_Servers : 10&lt;br /&gt; Num_Dynamically_Allocated_Thread_Servers : 0&lt;br /&gt; Max_Waiting_Threads (for server task): 6&lt;br /&gt; Max_Active : 21&lt;br /&gt; Max_Active_Masters : 17&lt;br /&gt; Max_Sub_Threads_Per_Master : 6&lt;br /&gt; Max_Waiting_For_Threads (to finish): 113&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8383004232931899216-3623210585256019287?l=parasail-programming-language.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://parasail-programming-language.blogspot.com/feeds/3623210585256019287/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://parasail-programming-language.blogspot.com/2011/09/another-parasail-example-that-compiles.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8383004232931899216/posts/default/3623210585256019287'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8383004232931899216/posts/default/3623210585256019287'/><link rel='alternate' type='text/html' href='http://parasail-programming-language.blogspot.com/2011/09/another-parasail-example-that-compiles.html' title='Another ParaSail example that compiles and runs'/><author><name>Tuck</name><uri>http://www.blogger.com/profile/08866496974237052847</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8383004232931899216.post-7106435721311334740</id><published>2011-09-07T15:34:00.000-04:00</published><updated>2011-09-07T15:34:54.169-04:00</updated><title type='text'>ParaSail compiler reaches a milestone</title><content type='html'>The &lt;b&gt;ParaSail&lt;/b&gt; compiler has reached a bit of a milestone, in that it now can compile and run what might be considered to be "interesting" programs.&amp;nbsp; Annotations are not yet enforced, and explicitly concurrent lock-based objects are not yet there, but many other things are working, including implicit and explicit parallelism, dynamic storage management using expandable/shrinkable objects (rather than pointers and garbage collection), fully-shared generic template instantiations, etc.&amp;nbsp; We are trying to solidify the features that are currently supported so we can make a version of the prototype compiler available for experimentation by others within the next couple of weeks.&lt;br /&gt;&lt;br /&gt;Below is one of the "interesting" programs.&amp;nbsp; This one is an implementation of balanced "AA" trees.&amp;nbsp; This doesn't illustrate any explicit parallelism, but does illustrate creating and updating interesting data structures without using explicit pointers.  Pointer-free data structures allow the compiler to easily understand any aliasing, since there is no hidden sharing between distinct objects.  That allows the compiler to eliminate race conditions at compile-time.&lt;br /&gt;&lt;br /&gt;Here is the &lt;b&gt;interface&lt;/b&gt; to the AA_Tree module.  (As a side-note, the program that "HTML"-ized this code was itself written in ParaSail.  I've included it at the bottom of this posting.)&lt;pre&gt;&lt;b&gt;interface&lt;/b&gt; AA_Tree&amp;lt;Element &lt;b&gt;is&lt;/b&gt; Comparable&amp;lt;&amp;gt;&amp;gt; &lt;b&gt;is&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;    &lt;i&gt;// This module implements a balanced "AA" tree, originally&lt;/i&gt;&lt;br /&gt;    &lt;i&gt;// described by Arne Andersson in the "Proceedings of the Workshop&lt;/i&gt;&lt;br /&gt;    &lt;i&gt;// on Algorithms and Data Structures," pp 60-71, Springer Verlag, 1993.&lt;/i&gt;&lt;br /&gt;    &lt;i&gt;// The following algorithm and descriptions were taken from the&lt;/i&gt;&lt;br /&gt;    &lt;i&gt;// WikiPedia article on AA_Tree: &lt;/i&gt;&lt;br /&gt;    &lt;i&gt;//       http://en.wikipedia.org/wiki/AA_tree&lt;/i&gt;&lt;br /&gt;    &lt;i&gt;// Note that various additional checks for a null tree have been added.&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;    &lt;i&gt;// Only two operations are needed for maintaining balance in an AA tree.&lt;/i&gt;&lt;br /&gt;    &lt;i&gt;// These operations are called skew and split. Skew is a right rotation&lt;/i&gt;&lt;br /&gt;    &lt;i&gt;// when an insertion or deletion creates a left horizontal link. Split&lt;/i&gt;&lt;br /&gt;    &lt;i&gt;// is a conditional left rotation when an insertion or deletion creates two&lt;/i&gt;&lt;br /&gt;    &lt;i&gt;// horizontal right links, which once again corresponds to two&lt;/i&gt;&lt;br /&gt;    &lt;i&gt;// consecutive red links in red-black trees.&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;    &lt;b&gt;op&lt;/b&gt; "[]"() -&amp;gt; &lt;b&gt;optional&lt;/b&gt; AA_Tree;&lt;br /&gt;        &lt;i&gt;// Create an empty tree&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;    &lt;b&gt;func&lt;/b&gt; Insert(&lt;b&gt;var&lt;/b&gt; T : &lt;b&gt;optional&lt;/b&gt; AA_Tree; X : Element);&lt;br /&gt;        &lt;i&gt;// input: X, the value to be inserted, and &lt;/i&gt;&lt;br /&gt;        &lt;i&gt;// T, the root of the tree to insert it into.&lt;/i&gt;&lt;br /&gt;        &lt;i&gt;// output: A balanced T' including X.&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;    &lt;b&gt;func&lt;/b&gt; Delete(&lt;b&gt;var&lt;/b&gt; T : &lt;b&gt;optional&lt;/b&gt; AA_Tree; X : Element);&lt;br /&gt;        &lt;i&gt;// input: X, the value to delete, and T, &lt;/i&gt;&lt;br /&gt;        &lt;i&gt;// the root of the tree from which it should be deleted.&lt;/i&gt;&lt;br /&gt;        &lt;i&gt;// output: T', balanced, without the value X.&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;    &lt;b&gt;op&lt;/b&gt; "in"(X : Element; T : &lt;b&gt;optional&lt;/b&gt; AA_Tree) -&amp;gt; Boolean;&lt;br /&gt;&lt;br /&gt;    &lt;b&gt;func&lt;/b&gt; Overlapping(T : &lt;b&gt;optional&lt;/b&gt; AA_Tree; X : Element) -&amp;gt; &lt;b&gt;optional&lt;/b&gt; Element;&lt;br /&gt;        &lt;i&gt;// input: X, the value to find, and T, &lt;/i&gt;&lt;br /&gt;        &lt;i&gt;// the root of the tree to be searched.&lt;/i&gt;&lt;br /&gt;        &lt;i&gt;// output: the element equal to or "unordered" relative to X.&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;    &lt;b&gt;op&lt;/b&gt; "|="(&lt;b&gt;var&lt;/b&gt; T : &lt;b&gt;optional&lt;/b&gt; AA_Tree; X : Element);&lt;br /&gt;&lt;br /&gt;    &lt;b&gt;func&lt;/b&gt; First(T : &lt;b&gt;optional&lt;/b&gt; AA_Tree) -&amp;gt; &lt;b&gt;optional&lt;/b&gt; Element;&lt;br /&gt;      &lt;i&gt;// Return first (smallest) element in tree&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;    &lt;b&gt;func&lt;/b&gt; Last(T : &lt;b&gt;optional&lt;/b&gt; AA_Tree) -&amp;gt; &lt;b&gt;optional&lt;/b&gt; Element;&lt;br /&gt;      &lt;i&gt;// Return last (greatest) element in tree&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;    &lt;b&gt;func&lt;/b&gt; Remove_First(&lt;b&gt;var&lt;/b&gt; T : &lt;b&gt;optional&lt;/b&gt; AA_Tree) -&amp;gt; &lt;b&gt;optional&lt;/b&gt; Element;&lt;br /&gt;      &lt;i&gt;// Remove first (smallest) element in tree&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;    &lt;b&gt;func&lt;/b&gt; Remove_Last(&lt;b&gt;var&lt;/b&gt; T : &lt;b&gt;optional&lt;/b&gt; AA_Tree) -&amp;gt; &lt;b&gt;optional&lt;/b&gt; Element;&lt;br /&gt;      &lt;i&gt;// Remove last (greatest) element in tree&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;    &lt;b&gt;func&lt;/b&gt; Remove_Any(&lt;b&gt;var&lt;/b&gt; T : &lt;b&gt;optional&lt;/b&gt; AA_Tree) -&amp;gt; &lt;b&gt;optional&lt;/b&gt; Element;&lt;br /&gt;      &lt;i&gt;// Remove some element from tree&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;    &lt;b&gt;func&lt;/b&gt; Count(T : &lt;b&gt;optional&lt;/b&gt; AA_Tree) -&amp;gt; Univ_Integer;&lt;br /&gt;      &lt;i&gt;// Return a count of the nodes in the tree&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;end&lt;/b&gt; &lt;b&gt;interface&lt;/b&gt; AA_Tree;&lt;br /&gt;&lt;/pre&gt;Here is the &lt;b&gt;class&lt;/b&gt; that provides the implementation for the AA_Tree module:&lt;br /&gt;&lt;pre&gt;&lt;b&gt;class&lt;/b&gt; AA_Tree &lt;b&gt;is&lt;/b&gt;&lt;br /&gt;    &lt;b&gt;var&lt;/b&gt; Left : &lt;b&gt;optional&lt;/b&gt; AA_Tree;&lt;br /&gt;    &lt;b&gt;var&lt;/b&gt; Right : &lt;b&gt;optional&lt;/b&gt; AA_Tree;&lt;br /&gt;    &lt;b&gt;var&lt;/b&gt; Value : Element;&lt;br /&gt;    &lt;b&gt;var&lt;/b&gt; Level : Univ_Integer := 0;&lt;br /&gt;&lt;br /&gt;    &lt;b&gt;func&lt;/b&gt; Node(Value : Element; Level : Univ_Integer; Left : &lt;b&gt;optional&lt;/b&gt; AA_Tree;&lt;br /&gt;      Right : &lt;b&gt;optional&lt;/b&gt; AA_Tree) -&amp;gt; AA_Tree &lt;b&gt;is&lt;/b&gt;&lt;br /&gt;        &lt;i&gt;// Create a new tree.&lt;/i&gt;&lt;br /&gt;        &lt;b&gt;return&lt;/b&gt; (Left =&amp;gt; Left, Right =&amp;gt; Right, Value =&amp;gt; Value,&lt;br /&gt;          Level =&amp;gt; Level);&lt;br /&gt;    &lt;b&gt;end&lt;/b&gt; &lt;b&gt;func&lt;/b&gt; Node;&lt;br /&gt;&lt;br /&gt;    &lt;b&gt;func&lt;/b&gt; Is_Leaf(T : &lt;b&gt;optional&lt;/b&gt; AA_Tree) -&amp;gt; Boolean &lt;b&gt;is&lt;/b&gt;&lt;br /&gt;        &lt;b&gt;return&lt;/b&gt; T &lt;b&gt;not&lt;/b&gt; &lt;b&gt;null&lt;/b&gt; &lt;b&gt;and&lt;/b&gt; &lt;b&gt;then&lt;/b&gt;&lt;br /&gt;          T.Left &lt;b&gt;is&lt;/b&gt; &lt;b&gt;null&lt;/b&gt; &lt;b&gt;and&lt;/b&gt; &lt;b&gt;then&lt;/b&gt; T.Right &lt;b&gt;is&lt;/b&gt; &lt;b&gt;null&lt;/b&gt;;&lt;br /&gt;    &lt;b&gt;end&lt;/b&gt; &lt;b&gt;func&lt;/b&gt; Is_Leaf;&lt;br /&gt;&lt;br /&gt;    &lt;b&gt;func&lt;/b&gt; Leftmost(&lt;b&gt;ref&lt;/b&gt; T : &lt;b&gt;optional&lt;/b&gt; AA_Tree) -&amp;gt; &lt;b&gt;ref&lt;/b&gt; &lt;b&gt;optional&lt;/b&gt; AA_Tree &lt;b&gt;is&lt;/b&gt;&lt;br /&gt;        &lt;b&gt;for&lt;/b&gt; L =&amp;gt; T &lt;b&gt;loop&lt;/b&gt;&lt;br /&gt;            &lt;b&gt;if&lt;/b&gt; L &lt;b&gt;not&lt;/b&gt; &lt;b&gt;null&lt;/b&gt; &lt;b&gt;and&lt;/b&gt; &lt;b&gt;then&lt;/b&gt; L.Left &lt;b&gt;not&lt;/b&gt; &lt;b&gt;null&lt;/b&gt; &lt;b&gt;then&lt;/b&gt;&lt;br /&gt;                &lt;i&gt;// Continue with Left until we reach null&lt;/i&gt;&lt;br /&gt;                &lt;b&gt;continue&lt;/b&gt; &lt;b&gt;loop&lt;/b&gt; &lt;b&gt;with&lt;/b&gt; L.Left;&lt;br /&gt;            &lt;b&gt;else&lt;/b&gt;&lt;br /&gt;                &lt;i&gt;// Found left-most&lt;/i&gt;&lt;br /&gt;                &lt;b&gt;return&lt;/b&gt; L;&lt;br /&gt;            &lt;b&gt;end&lt;/b&gt; &lt;b&gt;if&lt;/b&gt;;&lt;br /&gt;        &lt;b&gt;end&lt;/b&gt; &lt;b&gt;loop&lt;/b&gt;;&lt;br /&gt;    &lt;b&gt;end&lt;/b&gt; &lt;b&gt;func&lt;/b&gt; Leftmost;&lt;br /&gt;&lt;br /&gt;    &lt;b&gt;func&lt;/b&gt; Successor(T : &lt;b&gt;optional&lt;/b&gt; AA_Tree) -&amp;gt; &lt;b&gt;optional&lt;/b&gt; Element &lt;b&gt;is&lt;/b&gt;&lt;br /&gt;        &lt;i&gt;// Return element in tree greater than but closest to T.Value&lt;/i&gt;&lt;br /&gt;        &lt;b&gt;if&lt;/b&gt; T.Right &lt;b&gt;not&lt;/b&gt; &lt;b&gt;null&lt;/b&gt; &lt;b&gt;then&lt;/b&gt;&lt;br /&gt;            &lt;b&gt;return&lt;/b&gt; Leftmost(T.Right).Value;&lt;br /&gt;        &lt;b&gt;else&lt;/b&gt;&lt;br /&gt;            &lt;b&gt;return&lt;/b&gt; &lt;b&gt;null&lt;/b&gt;;&lt;br /&gt;        &lt;b&gt;end&lt;/b&gt; &lt;b&gt;if&lt;/b&gt;;&lt;br /&gt;    &lt;b&gt;end&lt;/b&gt; &lt;b&gt;func&lt;/b&gt; Successor;&lt;br /&gt;&lt;br /&gt;    &lt;b&gt;func&lt;/b&gt; Rightmost(&lt;b&gt;ref&lt;/b&gt; T : &lt;b&gt;optional&lt;/b&gt; AA_Tree) -&amp;gt; &lt;b&gt;ref&lt;/b&gt; &lt;b&gt;optional&lt;/b&gt; AA_Tree &lt;b&gt;is&lt;/b&gt;&lt;br /&gt;        &lt;b&gt;for&lt;/b&gt; R =&amp;gt; T &lt;b&gt;loop&lt;/b&gt;&lt;br /&gt;            &lt;b&gt;if&lt;/b&gt; R &lt;b&gt;not&lt;/b&gt; &lt;b&gt;null&lt;/b&gt; &lt;b&gt;and&lt;/b&gt; &lt;b&gt;then&lt;/b&gt; R.Right &lt;b&gt;not&lt;/b&gt; &lt;b&gt;null&lt;/b&gt; &lt;b&gt;then&lt;/b&gt;&lt;br /&gt;                &lt;i&gt;// Keep following down Right side&lt;/i&gt;&lt;br /&gt;                &lt;b&gt;continue&lt;/b&gt; &lt;b&gt;loop&lt;/b&gt; &lt;b&gt;with&lt;/b&gt; R.Right;&lt;br /&gt;            &lt;b&gt;else&lt;/b&gt;&lt;br /&gt;                &lt;i&gt;// Found right-most&lt;/i&gt;&lt;br /&gt;                &lt;b&gt;return&lt;/b&gt; R;&lt;br /&gt;            &lt;b&gt;end&lt;/b&gt; &lt;b&gt;if&lt;/b&gt;;&lt;br /&gt;        &lt;b&gt;end&lt;/b&gt; &lt;b&gt;loop&lt;/b&gt;;&lt;br /&gt;    &lt;b&gt;end&lt;/b&gt; &lt;b&gt;func&lt;/b&gt; Rightmost;&lt;br /&gt;&lt;br /&gt;    &lt;b&gt;func&lt;/b&gt; Predecessor(T : &lt;b&gt;optional&lt;/b&gt; AA_Tree) -&amp;gt; &lt;b&gt;optional&lt;/b&gt; Element &lt;b&gt;is&lt;/b&gt;&lt;br /&gt;        &lt;i&gt;// Return element in tree less than but closest to T.Value&lt;/i&gt;&lt;br /&gt;        &lt;b&gt;if&lt;/b&gt; T.Left &lt;b&gt;not&lt;/b&gt; &lt;b&gt;null&lt;/b&gt; &lt;b&gt;then&lt;/b&gt;&lt;br /&gt;            &lt;b&gt;return&lt;/b&gt; Rightmost(T.Left).Value;&lt;br /&gt;        &lt;b&gt;else&lt;/b&gt;&lt;br /&gt;            &lt;b&gt;return&lt;/b&gt; &lt;b&gt;null&lt;/b&gt;;&lt;br /&gt;        &lt;b&gt;end&lt;/b&gt; &lt;b&gt;if&lt;/b&gt;;&lt;br /&gt;    &lt;b&gt;end&lt;/b&gt; &lt;b&gt;func&lt;/b&gt; Predecessor;&lt;br /&gt;&lt;br /&gt;    &lt;b&gt;func&lt;/b&gt; Skew(&lt;b&gt;var&lt;/b&gt; T : &lt;b&gt;optional&lt;/b&gt; AA_Tree) &lt;b&gt;is&lt;/b&gt;&lt;br /&gt;      &lt;i&gt;// input: T, a node representing an AA tree that needs to be rebalanced.&lt;/i&gt;&lt;br /&gt;      &lt;i&gt;// output: T' Another node representing the rebalanced AA tree.&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;        &lt;b&gt;if&lt;/b&gt; T &lt;b&gt;not&lt;/b&gt; &lt;b&gt;null&lt;/b&gt; &lt;b&gt;and&lt;/b&gt; &lt;b&gt;then&lt;/b&gt;&lt;br /&gt;          T.Left &lt;b&gt;not&lt;/b&gt; &lt;b&gt;null&lt;/b&gt; &lt;b&gt;and&lt;/b&gt; &lt;b&gt;then&lt;/b&gt;&lt;br /&gt;          T.Left.Level == T.Level &lt;b&gt;then&lt;/b&gt;&lt;br /&gt;            &lt;i&gt;// The current T.Left becomes new root&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;            &lt;i&gt;// Exchange value of T.Left with root&lt;/i&gt;&lt;br /&gt;            T.Value &amp;lt;=&amp;gt; T.Left.Value;&lt;br /&gt;           &lt;br /&gt;            &lt;i&gt;// Move old root and T.Left.Right over to right side of tree&lt;/i&gt;&lt;br /&gt;            T.Left.Right &amp;lt;=&amp;gt; T.Right;&lt;br /&gt;            T.Left.Left &amp;lt;=&amp;gt; T.Right;&lt;br /&gt;            T.Left &amp;lt;=&amp;gt; T.Right;&lt;br /&gt;        &lt;b&gt;end&lt;/b&gt; &lt;b&gt;if&lt;/b&gt;;&lt;br /&gt;    &lt;b&gt;end&lt;/b&gt; &lt;b&gt;func&lt;/b&gt; Skew;&lt;br /&gt;&lt;br /&gt;    &lt;b&gt;func&lt;/b&gt; Split(&lt;b&gt;var&lt;/b&gt; T : &lt;b&gt;optional&lt;/b&gt; AA_Tree) &lt;b&gt;is&lt;/b&gt;&lt;br /&gt;        &lt;i&gt;// input: T, a node representing an AA tree that needs to be rebalanced.&lt;/i&gt;&lt;br /&gt;        &lt;i&gt;// output: T' Another node representing the rebalanced AA tree.&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;        &lt;b&gt;if&lt;/b&gt; T &lt;b&gt;not&lt;/b&gt; &lt;b&gt;null&lt;/b&gt; &lt;b&gt;and&lt;/b&gt; &lt;b&gt;then&lt;/b&gt;&lt;br /&gt;          T.Right &lt;b&gt;not&lt;/b&gt; &lt;b&gt;null&lt;/b&gt; &lt;b&gt;and&lt;/b&gt; &lt;b&gt;then&lt;/b&gt;&lt;br /&gt;          T.Right.Right &lt;b&gt;not&lt;/b&gt; &lt;b&gt;null&lt;/b&gt; &lt;b&gt;and&lt;/b&gt; &lt;b&gt;then&lt;/b&gt;&lt;br /&gt;          T.Level == T.Right.Right.Level &lt;b&gt;then&lt;/b&gt;&lt;br /&gt;            &lt;i&gt;// T.Right becomes the new root&lt;/i&gt;&lt;br /&gt;            &lt;i&gt;// Exchange value and level between root and T.Right&lt;/i&gt;&lt;br /&gt;            T.Value &amp;lt;=&amp;gt; T.Right.Value;&lt;br /&gt;            T.Level &amp;lt;=&amp;gt; T.Right.Level;&lt;br /&gt;&lt;br /&gt;            &lt;i&gt;// Move old root and T.Right.Left to left side of tree&lt;/i&gt;&lt;br /&gt;            T.Left &amp;lt;=&amp;gt; T.Right.Right;&lt;br /&gt;            T.Right.Left &amp;lt;=&amp;gt; T.Right.Right;&lt;br /&gt;            T.Left &amp;lt;=&amp;gt; T.Right;&lt;br /&gt;&lt;br /&gt;            &lt;i&gt;// Increment level&lt;/i&gt;&lt;br /&gt;            T.Level += 1;&lt;br /&gt;        &lt;b&gt;end&lt;/b&gt; &lt;b&gt;if&lt;/b&gt;;&lt;br /&gt;    &lt;b&gt;end&lt;/b&gt; &lt;b&gt;func&lt;/b&gt; Split;&lt;br /&gt;&lt;br /&gt;    &lt;b&gt;func&lt;/b&gt; Decrease_Level(&lt;b&gt;var&lt;/b&gt; T : &lt;b&gt;optional&lt;/b&gt; AA_Tree) &lt;b&gt;is&lt;/b&gt;&lt;br /&gt;        &lt;i&gt;// input: T, a tree for which we want to remove links that skip levels.&lt;/i&gt;&lt;br /&gt;        &lt;i&gt;// output: T with its level decreased.&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;        &lt;b&gt;if&lt;/b&gt; T &lt;b&gt;is&lt;/b&gt; &lt;b&gt;null&lt;/b&gt; &lt;b&gt;then&lt;/b&gt;&lt;br /&gt;            &lt;b&gt;return&lt;/b&gt;;&lt;br /&gt;        &lt;b&gt;end&lt;/b&gt; &lt;b&gt;if&lt;/b&gt;;&lt;br /&gt;           &lt;br /&gt;        &lt;b&gt;var&lt;/b&gt; Should_Be : Univ_Integer := 1;&lt;br /&gt;&lt;br /&gt;        &lt;b&gt;if&lt;/b&gt; T.Left &lt;b&gt;not&lt;/b&gt; &lt;b&gt;null&lt;/b&gt; &lt;b&gt;then&lt;/b&gt;&lt;br /&gt;            Should_Be := T.Left.Level + 1;&lt;br /&gt;        &lt;b&gt;end&lt;/b&gt; &lt;b&gt;if&lt;/b&gt;;&lt;br /&gt;&lt;br /&gt;        &lt;b&gt;if&lt;/b&gt; T.Right &lt;b&gt;not&lt;/b&gt; &lt;b&gt;null&lt;/b&gt; &lt;b&gt;then&lt;/b&gt;&lt;br /&gt;            Should_Be := Min(Should_Be, T.Right.Level + 1);&lt;br /&gt;        &lt;b&gt;end&lt;/b&gt; &lt;b&gt;if&lt;/b&gt;;&lt;br /&gt;            &lt;br /&gt;        &lt;b&gt;if&lt;/b&gt; Should_Be &amp;lt; T.Level &lt;b&gt;then&lt;/b&gt;&lt;br /&gt;            T.Level := Should_Be;&lt;br /&gt;            &lt;b&gt;if&lt;/b&gt; T.Right &lt;b&gt;not&lt;/b&gt; &lt;b&gt;null&lt;/b&gt; &lt;b&gt;and&lt;/b&gt; &lt;b&gt;then&lt;/b&gt;&lt;br /&gt;              Should_Be &amp;lt; T.Right.Level &lt;b&gt;then&lt;/b&gt;&lt;br /&gt;                T.Right.Level := Should_Be;&lt;br /&gt;            &lt;b&gt;end&lt;/b&gt; &lt;b&gt;if&lt;/b&gt;;&lt;br /&gt;        &lt;b&gt;end&lt;/b&gt; &lt;b&gt;if&lt;/b&gt;;&lt;br /&gt;    &lt;b&gt;end&lt;/b&gt; &lt;b&gt;func&lt;/b&gt; Decrease_Level;&lt;br /&gt;&lt;br /&gt;  &lt;b&gt;exports&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;    &lt;b&gt;op&lt;/b&gt; "[]"() -&amp;gt; &lt;b&gt;optional&lt;/b&gt; AA_Tree &lt;b&gt;is&lt;/b&gt;&lt;br /&gt;        &lt;i&gt;// Create an empty tree&lt;/i&gt;&lt;br /&gt;        &lt;b&gt;return&lt;/b&gt; &lt;b&gt;null&lt;/b&gt;;&lt;br /&gt;    &lt;b&gt;end&lt;/b&gt; &lt;b&gt;op&lt;/b&gt; "[]";&lt;br /&gt;&lt;br /&gt;    &lt;i&gt;// Insertion begins with the normal binary tree search and insertion&lt;/i&gt;&lt;br /&gt;    &lt;i&gt;// procedure. Then, as the call stack unwinds (assuming a recursive&lt;/i&gt;&lt;br /&gt;    &lt;i&gt;// implementation of the search), it's easy to check the validity of the&lt;/i&gt;&lt;br /&gt;    &lt;i&gt;// tree and perform any rotations as necessary. If a horizontal left link&lt;/i&gt;&lt;br /&gt;    &lt;i&gt;// arises, a skew will be performed, and if two horizontal right links&lt;/i&gt;&lt;br /&gt;    &lt;i&gt;// arise, a split will be performed, possibly incrementing the level of the&lt;/i&gt;&lt;br /&gt;    &lt;i&gt;// new root node of the current subtree. Note, in the code as given above,&lt;/i&gt;&lt;br /&gt;    &lt;i&gt;// the increment of T.Level. This makes it necessary to continue checking&lt;/i&gt;&lt;br /&gt;    &lt;i&gt;// the validity of the tree as the modifications bubble up from the leaves.&lt;/i&gt;&lt;br /&gt;    &lt;br /&gt;    &lt;b&gt;func&lt;/b&gt; Insert(&lt;b&gt;var&lt;/b&gt; T : &lt;b&gt;optional&lt;/b&gt; AA_Tree; X : Element) &lt;b&gt;is&lt;/b&gt;&lt;br /&gt;        &lt;i&gt;// input: X, the value to be inserted, and &lt;/i&gt;&lt;br /&gt;        &lt;i&gt;// T, the root of the tree to insert it into.&lt;/i&gt;&lt;br /&gt;        &lt;i&gt;// output: A balanced T' including X.&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;        &lt;i&gt;// Do the normal binary tree insertion procedure. &lt;/i&gt;&lt;br /&gt;        &lt;i&gt;// Set the result of the recursive call to the correct &lt;/i&gt;&lt;br /&gt;        &lt;i&gt;// child in case a new node was created or the&lt;/i&gt;&lt;br /&gt;        &lt;i&gt;// root of the subtree changes.&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;        &lt;b&gt;if&lt;/b&gt; T &lt;b&gt;is&lt;/b&gt; &lt;b&gt;null&lt;/b&gt; &lt;b&gt;then&lt;/b&gt;&lt;br /&gt;            &lt;i&gt;// Create a new leaf node with X.&lt;/i&gt;&lt;br /&gt;            T := Node(X, 1, &lt;b&gt;null&lt;/b&gt;, &lt;b&gt;null&lt;/b&gt;);&lt;br /&gt;            &lt;b&gt;return&lt;/b&gt;;&lt;br /&gt;        &lt;b&gt;end&lt;/b&gt; &lt;b&gt;if&lt;/b&gt;;&lt;br /&gt;&lt;br /&gt;        &lt;b&gt;case&lt;/b&gt; X =? T.Value &lt;b&gt;of&lt;/b&gt;&lt;br /&gt;          [#less] =&amp;gt;&lt;br /&gt;            Insert(T.Left, X);&lt;br /&gt;          [#greater] =&amp;gt;&lt;br /&gt;            Insert(T.Right, X);&lt;br /&gt;          [#equal | #unordered] =&amp;gt;&lt;br /&gt;            &lt;i&gt;// Note that the case of X == T.Value is unspecified. &lt;/i&gt;&lt;br /&gt;            &lt;i&gt;// As given, an insert will have no effect. &lt;/i&gt;&lt;br /&gt;            &lt;i&gt;// The implementor may desire different behavior.&lt;/i&gt;&lt;br /&gt;            &lt;b&gt;return&lt;/b&gt;;&lt;br /&gt;        &lt;b&gt;end&lt;/b&gt; &lt;b&gt;case&lt;/b&gt;;&lt;br /&gt;&lt;br /&gt;        &lt;i&gt;// Perform skew and then split. &lt;/i&gt;&lt;br /&gt;        &lt;i&gt;// The conditionals that determine whether or&lt;/i&gt;&lt;br /&gt;        &lt;i&gt;// not a rotation will occur or not are inside &lt;/i&gt;&lt;br /&gt;        &lt;i&gt;// of the procedures, as given above.&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;        Skew(T);&lt;br /&gt;        Split(T);&lt;br /&gt;    &lt;b&gt;end&lt;/b&gt; &lt;b&gt;func&lt;/b&gt; Insert;&lt;br /&gt;&lt;br /&gt;    &lt;i&gt;// As in most balanced binary trees, the deletion of an internal node can&lt;/i&gt;&lt;br /&gt;    &lt;i&gt;// be turned into the deletion of a leaf node by swapping the internal node&lt;/i&gt;&lt;br /&gt;    &lt;i&gt;// with either its closest predecessor or successor, depending on which are&lt;/i&gt;&lt;br /&gt;    &lt;i&gt;// in the tree or on the implementor's whims. Retrieving a predecessor is&lt;/i&gt;&lt;br /&gt;    &lt;i&gt;// simply a matter of following one left link and then all of the remaining&lt;/i&gt;&lt;br /&gt;    &lt;i&gt;// right links. Similarly, the successor can be found by going right once&lt;/i&gt;&lt;br /&gt;    &lt;i&gt;// and left until a null pointer is found. Because of the AA property of&lt;/i&gt;&lt;br /&gt;    &lt;i&gt;// all nodes of level greater than one having two children, the successor&lt;/i&gt;&lt;br /&gt;    &lt;i&gt;// or predecessor node will be in level 1, making their removal trivial.&lt;/i&gt;&lt;br /&gt;    &lt;i&gt;// &lt;/i&gt;&lt;br /&gt;    &lt;i&gt;// To re-balance a tree, there are a few approaches. The one described by&lt;/i&gt;&lt;br /&gt;    &lt;i&gt;// Andersson in his original paper is the simplest, and it is described&lt;/i&gt;&lt;br /&gt;    &lt;i&gt;// here, although actual implementations may opt for a more optimized&lt;/i&gt;&lt;br /&gt;    &lt;i&gt;// approach. After a removal, the first step to maintaining tree validity&lt;/i&gt;&lt;br /&gt;    &lt;i&gt;// is to lower the level of any nodes whose children are two levels below&lt;/i&gt;&lt;br /&gt;    &lt;i&gt;// them, or who are missing children. Then, the entire level must be skewed&lt;/i&gt;&lt;br /&gt;    &lt;i&gt;// and split. This approach was favored, because when laid down&lt;/i&gt;&lt;br /&gt;    &lt;i&gt;// conceptually, it has three easily understood separate steps:&lt;/i&gt;&lt;br /&gt;    &lt;i&gt;// &lt;/i&gt;&lt;br /&gt;    &lt;i&gt;//     Decrease the level, if appropriate.&lt;/i&gt;&lt;br /&gt;    &lt;i&gt;//     Skew the level.&lt;/i&gt;&lt;br /&gt;    &lt;i&gt;//     Split the level.&lt;/i&gt;&lt;br /&gt;    &lt;i&gt;// &lt;/i&gt;&lt;br /&gt;    &lt;i&gt;// However, we have to skew and split the entire level this time instead of&lt;/i&gt;&lt;br /&gt;    &lt;i&gt;// just a node, complicating our code.&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;    &lt;b&gt;func&lt;/b&gt; Delete(&lt;b&gt;var&lt;/b&gt; T : &lt;b&gt;optional&lt;/b&gt; AA_Tree; X : Element) &lt;b&gt;is&lt;/b&gt;&lt;br /&gt;        &lt;i&gt;// input: X, the value to delete, and T, &lt;/i&gt;&lt;br /&gt;        &lt;i&gt;// the root of the tree from which it should be deleted.&lt;/i&gt;&lt;br /&gt;        &lt;i&gt;// output: T', balanced, without the value X.&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;        &lt;b&gt;if&lt;/b&gt; T &lt;b&gt;is&lt;/b&gt; &lt;b&gt;null&lt;/b&gt; &lt;b&gt;then&lt;/b&gt;&lt;br /&gt;            &lt;i&gt;// Not in tree -- should we complain?&lt;/i&gt;&lt;br /&gt;            &lt;b&gt;return&lt;/b&gt;;&lt;br /&gt;        &lt;b&gt;end&lt;/b&gt; &lt;b&gt;if&lt;/b&gt;;&lt;br /&gt;&lt;br /&gt;        &lt;b&gt;case&lt;/b&gt; X =? T.Value &lt;b&gt;of&lt;/b&gt;&lt;br /&gt;          [#less] =&amp;gt;&lt;br /&gt;            Delete(T.Left, X);&lt;br /&gt;          [#greater] =&amp;gt;&lt;br /&gt;            Delete(T.Right, X);&lt;br /&gt;          [#equal] =&amp;gt;&lt;br /&gt;            &lt;i&gt;// If we're a leaf, easy, otherwise reduce to leaf case. &lt;/i&gt;&lt;br /&gt;            &lt;b&gt;if&lt;/b&gt; Is_Leaf(T) &lt;b&gt;then&lt;/b&gt;&lt;br /&gt;                T := &lt;b&gt;null&lt;/b&gt;;&lt;br /&gt;            &lt;b&gt;elsif&lt;/b&gt; T.Left &lt;b&gt;is&lt;/b&gt; &lt;b&gt;null&lt;/b&gt; &lt;b&gt;then&lt;/b&gt;&lt;br /&gt;                &lt;i&gt;// Get successor value and delete it from right tree,&lt;/i&gt;&lt;br /&gt;                &lt;i&gt;// and set root to have that value&lt;/i&gt;&lt;br /&gt;                &lt;b&gt;const&lt;/b&gt; Succ := Successor(T);&lt;br /&gt;                Delete(T.Right, Succ);&lt;br /&gt;                T.Value := Succ;&lt;br /&gt;            &lt;b&gt;else&lt;/b&gt;&lt;br /&gt;                &lt;i&gt;// Get predecessor value and delete it from left tree,&lt;/i&gt;&lt;br /&gt;                &lt;i&gt;// and set root to have that value&lt;/i&gt;&lt;br /&gt;                &lt;b&gt;const&lt;/b&gt; Pred := Predecessor(T);&lt;br /&gt;                Delete(T.Left, Pred);&lt;br /&gt;                T.Value := Pred;&lt;br /&gt;            &lt;b&gt;end&lt;/b&gt; &lt;b&gt;if&lt;/b&gt;;&lt;br /&gt;          [#unordered] =&amp;gt;&lt;br /&gt;            &lt;i&gt;// Not in tree; should we complain?&lt;/i&gt;&lt;br /&gt;            &lt;b&gt;return&lt;/b&gt;;  &lt;br /&gt;        &lt;b&gt;end&lt;/b&gt; &lt;b&gt;case&lt;/b&gt;;&lt;br /&gt;&lt;br /&gt;        &lt;i&gt;// Rebalance the tree. Decrease the level of all nodes in this level if&lt;/i&gt;&lt;br /&gt;        &lt;i&gt;// necessary, and then skew and split all nodes in the new level.&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;        &lt;b&gt;if&lt;/b&gt; T &lt;b&gt;is&lt;/b&gt; &lt;b&gt;null&lt;/b&gt; &lt;b&gt;then&lt;/b&gt;&lt;br /&gt;            &lt;b&gt;return&lt;/b&gt;;&lt;br /&gt;        &lt;b&gt;end&lt;/b&gt; &lt;b&gt;if&lt;/b&gt;;&lt;br /&gt;&lt;br /&gt;        Decrease_Level(T);&lt;br /&gt;        Skew(T);&lt;br /&gt;        Skew(T.Right);&lt;br /&gt;        &lt;b&gt;if&lt;/b&gt; T.Right &lt;b&gt;not&lt;/b&gt; &lt;b&gt;null&lt;/b&gt; &lt;b&gt;then&lt;/b&gt;&lt;br /&gt;            Skew(T.Right.Right);&lt;br /&gt;        &lt;b&gt;end&lt;/b&gt; &lt;b&gt;if&lt;/b&gt;;&lt;br /&gt;        Split(T);&lt;br /&gt;        Split(T.Right);&lt;br /&gt;    &lt;b&gt;end&lt;/b&gt; &lt;b&gt;func&lt;/b&gt; Delete;&lt;br /&gt;&lt;br /&gt;    &lt;b&gt;op&lt;/b&gt; "in"(X : Element; T : &lt;b&gt;optional&lt;/b&gt; AA_Tree) -&amp;gt; Result : Boolean &lt;b&gt;is&lt;/b&gt;&lt;br /&gt;        &lt;b&gt;for&lt;/b&gt; P =&amp;gt; T &lt;b&gt;while&lt;/b&gt; P &lt;b&gt;not&lt;/b&gt; &lt;b&gt;null&lt;/b&gt; &lt;b&gt;loop&lt;/b&gt;&lt;br /&gt;            &lt;b&gt;case&lt;/b&gt; X =? P.Value &lt;b&gt;of&lt;/b&gt;&lt;br /&gt;              [#less] =&amp;gt;&lt;br /&gt;                &lt;b&gt;continue&lt;/b&gt; &lt;b&gt;loop&lt;/b&gt; &lt;b&gt;with&lt;/b&gt; P.Left;&lt;br /&gt;              [#greater] =&amp;gt;&lt;br /&gt;                &lt;b&gt;continue&lt;/b&gt; &lt;b&gt;loop&lt;/b&gt; &lt;b&gt;with&lt;/b&gt; P.Right;&lt;br /&gt;              [#equal] =&amp;gt;&lt;br /&gt;                &lt;b&gt;return&lt;/b&gt; #true;&lt;br /&gt;              [#unordered] =&amp;gt;&lt;br /&gt;                &lt;b&gt;return&lt;/b&gt; #false;&lt;br /&gt;            &lt;b&gt;end&lt;/b&gt; &lt;b&gt;case&lt;/b&gt;;&lt;br /&gt;        &lt;b&gt;end&lt;/b&gt; &lt;b&gt;loop&lt;/b&gt;;&lt;br /&gt;        &lt;b&gt;return&lt;/b&gt; #false;  &lt;i&gt;// Not found&lt;/i&gt;&lt;br /&gt;    &lt;b&gt;end&lt;/b&gt; &lt;b&gt;op&lt;/b&gt; "in";&lt;br /&gt;&lt;br /&gt;    &lt;b&gt;func&lt;/b&gt; First(T : &lt;b&gt;optional&lt;/b&gt; AA_Tree) -&amp;gt; &lt;b&gt;optional&lt;/b&gt; Element &lt;b&gt;is&lt;/b&gt;&lt;br /&gt;      &lt;i&gt;// Return first (smallest) element in tree&lt;/i&gt;&lt;br /&gt;        &lt;b&gt;if&lt;/b&gt; T &lt;b&gt;is&lt;/b&gt; &lt;b&gt;null&lt;/b&gt; &lt;b&gt;then&lt;/b&gt;&lt;br /&gt;            &lt;b&gt;return&lt;/b&gt; &lt;b&gt;null&lt;/b&gt;;&lt;br /&gt;        &lt;b&gt;else&lt;/b&gt; &lt;br /&gt;            &lt;b&gt;return&lt;/b&gt; Leftmost(T).Value;&lt;br /&gt;        &lt;b&gt;end&lt;/b&gt; &lt;b&gt;if&lt;/b&gt;;&lt;br /&gt;    &lt;b&gt;end&lt;/b&gt; &lt;b&gt;func&lt;/b&gt; First;&lt;br /&gt;&lt;br /&gt;    &lt;b&gt;func&lt;/b&gt; Last(T : &lt;b&gt;optional&lt;/b&gt; AA_Tree) -&amp;gt; &lt;b&gt;optional&lt;/b&gt; Element &lt;b&gt;is&lt;/b&gt;&lt;br /&gt;      &lt;i&gt;// Return last (greatest) element in tree&lt;/i&gt;&lt;br /&gt;        &lt;b&gt;if&lt;/b&gt; T &lt;b&gt;is&lt;/b&gt; &lt;b&gt;null&lt;/b&gt; &lt;b&gt;then&lt;/b&gt;&lt;br /&gt;            &lt;b&gt;return&lt;/b&gt; &lt;b&gt;null&lt;/b&gt;;&lt;br /&gt;        &lt;b&gt;else&lt;/b&gt;&lt;br /&gt;            &lt;b&gt;return&lt;/b&gt; Rightmost(T).Value;&lt;br /&gt;        &lt;b&gt;end&lt;/b&gt; &lt;b&gt;if&lt;/b&gt;;&lt;br /&gt;    &lt;b&gt;end&lt;/b&gt; &lt;b&gt;func&lt;/b&gt; Last;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    &lt;b&gt;func&lt;/b&gt; Remove_First(&lt;b&gt;var&lt;/b&gt; T : &lt;b&gt;optional&lt;/b&gt; AA_Tree) -&amp;gt; Result : &lt;b&gt;optional&lt;/b&gt; Element &lt;b&gt;is&lt;/b&gt;&lt;br /&gt;      &lt;i&gt;// Remove first (smallest) element in tree&lt;/i&gt;&lt;br /&gt;        Result := First(T);&lt;br /&gt;        &lt;b&gt;if&lt;/b&gt; Result &lt;b&gt;not&lt;/b&gt; &lt;b&gt;null&lt;/b&gt; &lt;b&gt;then&lt;/b&gt;&lt;br /&gt;            Delete(T, Result);&lt;br /&gt;        &lt;b&gt;end&lt;/b&gt; &lt;b&gt;if&lt;/b&gt;;&lt;br /&gt;    &lt;b&gt;end&lt;/b&gt; &lt;b&gt;func&lt;/b&gt; Remove_First;&lt;br /&gt;&lt;br /&gt;    &lt;b&gt;func&lt;/b&gt; Remove_Last(&lt;b&gt;var&lt;/b&gt; T : &lt;b&gt;optional&lt;/b&gt; AA_Tree) -&amp;gt; Result : &lt;b&gt;optional&lt;/b&gt; Element &lt;b&gt;is&lt;/b&gt;&lt;br /&gt;      &lt;i&gt;// Remove last (greatest) element in tree&lt;/i&gt;&lt;br /&gt;        Result := Last(T);&lt;br /&gt;        &lt;b&gt;if&lt;/b&gt; Result &lt;b&gt;not&lt;/b&gt; &lt;b&gt;null&lt;/b&gt; &lt;b&gt;then&lt;/b&gt;&lt;br /&gt;            Delete(T, Result);&lt;br /&gt;        &lt;b&gt;end&lt;/b&gt; &lt;b&gt;if&lt;/b&gt;;&lt;br /&gt;    &lt;b&gt;end&lt;/b&gt; &lt;b&gt;func&lt;/b&gt; Remove_Last;&lt;br /&gt;&lt;br /&gt;    &lt;b&gt;func&lt;/b&gt; Remove_Any(&lt;b&gt;var&lt;/b&gt; T : &lt;b&gt;optional&lt;/b&gt; AA_Tree) -&amp;gt; Result : &lt;b&gt;optional&lt;/b&gt; Element &lt;b&gt;is&lt;/b&gt;&lt;br /&gt;      &lt;i&gt;// Remove some element from tree&lt;/i&gt;&lt;br /&gt;        &lt;b&gt;if&lt;/b&gt; T &lt;b&gt;is&lt;/b&gt; &lt;b&gt;null&lt;/b&gt; &lt;b&gt;then&lt;/b&gt;&lt;br /&gt;            &lt;b&gt;return&lt;/b&gt; &lt;b&gt;null&lt;/b&gt;;&lt;br /&gt;        &lt;b&gt;end&lt;/b&gt; &lt;b&gt;if&lt;/b&gt;;&lt;br /&gt;        Result := T.Value;&lt;br /&gt;        &lt;b&gt;if&lt;/b&gt; Result &lt;b&gt;not&lt;/b&gt; &lt;b&gt;null&lt;/b&gt; &lt;b&gt;then&lt;/b&gt;&lt;br /&gt;            Delete(T, Result);&lt;br /&gt;        &lt;b&gt;end&lt;/b&gt; &lt;b&gt;if&lt;/b&gt;;&lt;br /&gt;    &lt;b&gt;end&lt;/b&gt; &lt;b&gt;func&lt;/b&gt; Remove_Any;&lt;br /&gt;&lt;br /&gt;    &lt;b&gt;func&lt;/b&gt; Count(T : &lt;b&gt;optional&lt;/b&gt; AA_Tree) -&amp;gt; Univ_Integer &lt;b&gt;is&lt;/b&gt;&lt;br /&gt;      &lt;i&gt;// Return a count of the nodes in the tree&lt;/i&gt;&lt;br /&gt;        &lt;b&gt;if&lt;/b&gt; T &lt;b&gt;is&lt;/b&gt; &lt;b&gt;null&lt;/b&gt; &lt;b&gt;then&lt;/b&gt;&lt;br /&gt;            &lt;b&gt;return&lt;/b&gt; 0;&lt;br /&gt;        &lt;b&gt;else&lt;/b&gt;&lt;br /&gt;            &lt;b&gt;return&lt;/b&gt; Count(T.Left) + Count(T.Right) + 1;&lt;br /&gt;        &lt;b&gt;end&lt;/b&gt; &lt;b&gt;if&lt;/b&gt;;&lt;br /&gt;    &lt;b&gt;end&lt;/b&gt; &lt;b&gt;func&lt;/b&gt; Count;&lt;br /&gt;&lt;br /&gt;    &lt;b&gt;op&lt;/b&gt; "|="(&lt;b&gt;var&lt;/b&gt; T : &lt;b&gt;optional&lt;/b&gt; AA_Tree; X : Element) &lt;b&gt;is&lt;/b&gt;&lt;br /&gt;        Insert(T, X);&lt;br /&gt;    &lt;b&gt;end&lt;/b&gt; &lt;b&gt;op&lt;/b&gt; "|=";&lt;br /&gt;&lt;br /&gt;    &lt;b&gt;func&lt;/b&gt; Overlapping(T : &lt;b&gt;optional&lt;/b&gt; AA_Tree; X : Element) -&amp;gt; &lt;b&gt;optional&lt;/b&gt; Element &lt;b&gt;is&lt;/b&gt;&lt;br /&gt;        &lt;i&gt;// input: X, the value to find, and T, &lt;/i&gt;&lt;br /&gt;        &lt;i&gt;// the root of the tree to be searched.&lt;/i&gt;&lt;br /&gt;        &lt;i&gt;// output: the element equal to or "unordered" relative to X.&lt;/i&gt;&lt;br /&gt;        &lt;b&gt;if&lt;/b&gt; T &lt;b&gt;is&lt;/b&gt; &lt;b&gt;null&lt;/b&gt; &lt;b&gt;or&lt;/b&gt; &lt;b&gt;else&lt;/b&gt; T.Value &lt;b&gt;is&lt;/b&gt; &lt;b&gt;null&lt;/b&gt; &lt;b&gt;then&lt;/b&gt;&lt;br /&gt;            &lt;b&gt;return&lt;/b&gt; &lt;b&gt;null&lt;/b&gt;;&lt;br /&gt;        &lt;b&gt;else&lt;/b&gt;&lt;br /&gt;            &lt;b&gt;case&lt;/b&gt; X =? T.Value &lt;b&gt;of&lt;/b&gt;&lt;br /&gt;              [#less] =&amp;gt;&lt;br /&gt;                &lt;b&gt;return&lt;/b&gt; Overlapping(T.Left, X);&lt;br /&gt;              [#greater] =&amp;gt;&lt;br /&gt;                &lt;b&gt;return&lt;/b&gt; Overlapping(T.Right, X);&lt;br /&gt;              [#equal | #unordered] =&amp;gt;&lt;br /&gt;                &lt;i&gt;// Close enough&lt;/i&gt;&lt;br /&gt;                &lt;b&gt;return&lt;/b&gt; T.Value;&lt;br /&gt;            &lt;b&gt;end&lt;/b&gt; &lt;b&gt;case&lt;/b&gt;;&lt;br /&gt;        &lt;b&gt;end&lt;/b&gt; &lt;b&gt;if&lt;/b&gt;;&lt;br /&gt;    &lt;b&gt;end&lt;/b&gt; &lt;b&gt;func&lt;/b&gt; Overlapping;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;end&lt;/b&gt; &lt;b&gt;class&lt;/b&gt; AA_Tree;&lt;/pre&gt;Here is a small test program for AA_Tree:&lt;pre&gt;&lt;b&gt;func&lt;/b&gt; Test_AA_Tree(A : Univ_Integer; B : Univ_Integer; C : Univ_Integer) &lt;b&gt;is&lt;/b&gt;&lt;br /&gt;    &lt;b&gt;type&lt;/b&gt; Univ_Tree &lt;b&gt;is&lt;/b&gt; AA_Tree&amp;lt;Univ_Integer&amp;gt;;&lt;br /&gt;    &lt;b&gt;var&lt;/b&gt; T : Univ_Tree := [];&lt;br /&gt;    &lt;b&gt;var&lt;/b&gt; X : Univ_Integer := A;&lt;br /&gt;&lt;br /&gt;    Insert(T, A);&lt;br /&gt;    Println("Count = " | Count(T) | " after insert of " | A);&lt;br /&gt;    Insert(T, B);&lt;br /&gt;    Println("Count = " | Count(T) | " after insert of " | B);&lt;br /&gt;    Insert(T, C);&lt;br /&gt;    Println("Count = " | Count(T) | " after insert of " | C);&lt;br /&gt;&lt;br /&gt;    Insert(T, A);&lt;br /&gt;    Println("Count = " | Count(T) | " after another insert of " | A);&lt;br /&gt;&lt;br /&gt;    Println(A | " in T = " | [[A &lt;b&gt;in&lt;/b&gt; T]]);&lt;br /&gt;    Println(B | " in T = " | [[B &lt;b&gt;in&lt;/b&gt; T]]);&lt;br /&gt;    Println(C | " in T = " | [[C &lt;b&gt;in&lt;/b&gt; T]]);&lt;br /&gt;    Println("7 in T = " | [[7 &lt;b&gt;in&lt;/b&gt; T]]);&lt;br /&gt;&lt;br /&gt;    &lt;b&gt;for&lt;/b&gt; E := Remove_First(T) &lt;b&gt;then&lt;/b&gt; Remove_First(T) &lt;b&gt;while&lt;/b&gt; E &lt;b&gt;not&lt;/b&gt; &lt;b&gt;null&lt;/b&gt; &lt;b&gt;loop&lt;/b&gt;&lt;br /&gt;        Println("Remove_First = " | E);&lt;br /&gt;    &lt;b&gt;end&lt;/b&gt; &lt;b&gt;loop&lt;/b&gt;;&lt;br /&gt;&lt;br /&gt;    Println("Count after loop : " | Count(T));&lt;br /&gt;&lt;br /&gt;    &lt;b&gt;for&lt;/b&gt; I &lt;b&gt;in&lt;/b&gt; 1..10 &lt;b&gt;forward&lt;/b&gt; &lt;b&gt;loop&lt;/b&gt;&lt;br /&gt;        Insert(T, I);&lt;br /&gt;        Println("Count = " | Count(T) | " after insert of " | I);&lt;br /&gt;    &lt;b&gt;end&lt;/b&gt; &lt;b&gt;loop&lt;/b&gt;;&lt;br /&gt;&lt;br /&gt;    &lt;b&gt;for&lt;/b&gt; L := Remove_Last(T) &lt;b&gt;then&lt;/b&gt; Remove_Last(T) &lt;b&gt;while&lt;/b&gt; L &lt;b&gt;not&lt;/b&gt; &lt;b&gt;null&lt;/b&gt; &lt;b&gt;loop&lt;/b&gt;&lt;br /&gt;        Println("Remove_Last = " | L);&lt;br /&gt;    &lt;b&gt;end&lt;/b&gt; &lt;b&gt;loop&lt;/b&gt;;&lt;br /&gt;&lt;br /&gt;    Println("Count after loop : " | Count(T));&lt;br /&gt;&lt;br /&gt;    &lt;b&gt;for&lt;/b&gt; J &lt;b&gt;in&lt;/b&gt; 1..10 &lt;b&gt;reverse&lt;/b&gt; &lt;b&gt;loop&lt;/b&gt;&lt;br /&gt;        Insert(T, J);&lt;br /&gt;        Println("Count = " | Count(T) | " after insert of " | J);&lt;br /&gt;    &lt;b&gt;end&lt;/b&gt; &lt;b&gt;loop&lt;/b&gt;;&lt;br /&gt;&lt;br /&gt;    Println("Count after loop : " | Count(T));&lt;br /&gt;&lt;br /&gt;    Println("Overlapping(T, 5) = " | Overlapping(T, 5));&lt;br /&gt;&lt;br /&gt;    &lt;b&gt;for&lt;/b&gt; Z := Remove_Any(T) &lt;b&gt;then&lt;/b&gt; Remove_Any(T) &lt;b&gt;while&lt;/b&gt; Z &lt;b&gt;not&lt;/b&gt; &lt;b&gt;null&lt;/b&gt; &lt;b&gt;loop&lt;/b&gt;&lt;br /&gt;        Println("Remove_Any = " | Z);&lt;br /&gt;    &lt;b&gt;end&lt;/b&gt; &lt;b&gt;loop&lt;/b&gt;;&lt;br /&gt;&lt;br /&gt;    Println("Count after loop : " | Count(T));&lt;br /&gt;&lt;br /&gt;    &lt;b&gt;for&lt;/b&gt; K &lt;b&gt;in&lt;/b&gt; 1..10 &lt;b&gt;loop&lt;/b&gt;&lt;br /&gt;        Insert(T, K);&lt;br /&gt;        Println("Count = " | Count(T) | " after insert of " | K);&lt;br /&gt;    &lt;b&gt;end&lt;/b&gt; &lt;b&gt;loop&lt;/b&gt;;&lt;br /&gt;&lt;br /&gt;    &lt;b&gt;for&lt;/b&gt; F := Remove_First(T) &lt;b&gt;then&lt;/b&gt; Remove_First(T) &lt;b&gt;while&lt;/b&gt; F &lt;b&gt;not&lt;/b&gt; &lt;b&gt;null&lt;/b&gt; &lt;b&gt;loop&lt;/b&gt;&lt;br /&gt;        Println("Remove_First = " | F);&lt;br /&gt;    &lt;b&gt;end&lt;/b&gt; &lt;b&gt;loop&lt;/b&gt;;&lt;br /&gt;&lt;br /&gt;    Println("Count after loop : " | Count(T));&lt;br /&gt;&lt;br /&gt;&lt;b&gt;end&lt;/b&gt; &lt;b&gt;func&lt;/b&gt; Test_AA_Tree;&lt;/pre&gt;Here is the ParaSail program that was used to "HTML"-ize the listings above (as well as the one below!).  Not terribly sophisticated, but illustrates some of the character handling:&lt;br /&gt;&lt;pre&gt;&lt;b&gt;func&lt;/b&gt; Html_Escape(C : Univ_Character) -&amp;gt; Univ_String &lt;b&gt;is&lt;/b&gt;&lt;br /&gt;    &lt;i&gt;// Do single-character escapes&lt;/i&gt;&lt;br /&gt;    &lt;b&gt;case&lt;/b&gt; C &lt;b&gt;of&lt;/b&gt;&lt;br /&gt;      ['&amp;lt;'] =&amp;gt;&lt;br /&gt;        &lt;b&gt;return&lt;/b&gt; "&amp;amp;lt;";&lt;br /&gt;      ['&amp;gt;'] =&amp;gt;&lt;br /&gt;        &lt;b&gt;return&lt;/b&gt; "&amp;amp;gt;";&lt;br /&gt;      ['&amp;amp;'] =&amp;gt;&lt;br /&gt;        &lt;b&gt;return&lt;/b&gt; "&amp;amp;amp;";&lt;br /&gt;      ['\\'] =&amp;gt;&lt;br /&gt;        &lt;b&gt;return&lt;/b&gt; "\\";    &lt;i&gt;// Prevent "Print" from expanding control chars&lt;/i&gt;&lt;br /&gt;      [..] =&amp;gt;&lt;br /&gt;        &lt;b&gt;return&lt;/b&gt; "" | C;  &lt;i&gt;// Convert character into a string&lt;/i&gt;&lt;br /&gt;    &lt;b&gt;end&lt;/b&gt; &lt;b&gt;case&lt;/b&gt;;&lt;br /&gt;&lt;b&gt;end&lt;/b&gt; &lt;b&gt;func&lt;/b&gt; Html_Escape;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;func&lt;/b&gt; Htmlize_Line(Orig : Univ_String) -&amp;gt; Result : Univ_String &lt;b&gt;is&lt;/b&gt;&lt;br /&gt;    &lt;i&gt;// bold lower case words that are not in comments or&lt;/i&gt;&lt;br /&gt;    &lt;i&gt;// character, string, or enum literals&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;    Result := "";&lt;br /&gt;    &lt;b&gt;var&lt;/b&gt; I := 1;&lt;br /&gt;    &lt;b&gt;const&lt;/b&gt; L := Length(Orig);&lt;br /&gt;    &lt;b&gt;var&lt;/b&gt; State : Univ_Enumeration := #other;&lt;br /&gt;    &lt;b&gt;while&lt;/b&gt; I &amp;lt;= L &lt;b&gt;loop&lt;/b&gt;&lt;br /&gt;        &lt;b&gt;var&lt;/b&gt; C := Orig[I];&lt;br /&gt;        &lt;b&gt;case&lt;/b&gt; C &lt;b&gt;of&lt;/b&gt;&lt;br /&gt;          ['\\'] =&amp;gt;&lt;br /&gt;            &lt;b&gt;if&lt;/b&gt; State == #string_literal &lt;b&gt;or&lt;/b&gt; &lt;b&gt;else&lt;/b&gt; State == #char_literal &lt;b&gt;then&lt;/b&gt;&lt;br /&gt;                &lt;i&gt;// skip next character no matter what it is&lt;/i&gt;&lt;br /&gt;                &lt;b&gt;if&lt;/b&gt; I &amp;lt; L &lt;b&gt;then&lt;/b&gt;&lt;br /&gt;                    Result |= Html_Escape(C);&lt;br /&gt;                    I += 1;&lt;br /&gt;                    C := Orig[I];&lt;br /&gt;                &lt;b&gt;end&lt;/b&gt; &lt;b&gt;if&lt;/b&gt;;&lt;br /&gt;            &lt;b&gt;end&lt;/b&gt; &lt;b&gt;if&lt;/b&gt;;&lt;br /&gt;          ['/'] =&amp;gt;&lt;br /&gt;            &lt;b&gt;if&lt;/b&gt; I &amp;lt; L &lt;b&gt;and&lt;/b&gt; &lt;b&gt;then&lt;/b&gt; Orig[I+1] == '/' &lt;b&gt;then&lt;/b&gt;&lt;br /&gt;                &lt;i&gt;// comment, italicize it&lt;/i&gt;&lt;br /&gt;                Result |= "&amp;lt;i&amp;gt;" | Html_Escape(C);&lt;br /&gt;                &lt;b&gt;while&lt;/b&gt; I &amp;lt; L &lt;b&gt;loop&lt;/b&gt;&lt;br /&gt;                    I += 1;&lt;br /&gt;                    Result |= Html_Escape(Orig[I]);&lt;br /&gt;                &lt;b&gt;end&lt;/b&gt; &lt;b&gt;loop&lt;/b&gt;;&lt;br /&gt;                Result |= "&amp;lt;/i&amp;gt;";&lt;br /&gt;                C := &lt;b&gt;null&lt;/b&gt;;&lt;br /&gt;            &lt;b&gt;end&lt;/b&gt; &lt;b&gt;if&lt;/b&gt;;&lt;br /&gt;          ['a' .. 'z'] =&amp;gt;&lt;br /&gt;            &lt;b&gt;if&lt;/b&gt; State == #other &lt;b&gt;then&lt;/b&gt;&lt;br /&gt;                &lt;i&gt;// Presume this is a reserved word, so bold it&lt;/i&gt;&lt;br /&gt;                Result |= "&amp;lt;b&amp;gt;" | C;&lt;br /&gt;                &lt;b&gt;while&lt;/b&gt; I &amp;lt; L &lt;b&gt;and&lt;/b&gt; &lt;b&gt;then&lt;/b&gt; Orig[I+1] &lt;b&gt;in&lt;/b&gt; 'a' .. 'z' &lt;b&gt;loop&lt;/b&gt;&lt;br /&gt;                    I += 1;&lt;br /&gt;                    Result |= Orig[I];&lt;br /&gt;                &lt;b&gt;end&lt;/b&gt; &lt;b&gt;loop&lt;/b&gt;;&lt;br /&gt;                Result |= "&amp;lt;/b&amp;gt;";&lt;br /&gt;                C := &lt;b&gt;null&lt;/b&gt;;&lt;br /&gt;            &lt;b&gt;end&lt;/b&gt; &lt;b&gt;if&lt;/b&gt;;&lt;br /&gt;            &lt;br /&gt;          ['#' | '0'..'9' | 'A' .. 'Z' | '_'] =&amp;gt;&lt;br /&gt;            &lt;i&gt;// Presume this is not a reserved word, pass through as is&lt;/i&gt;&lt;br /&gt;            &lt;b&gt;if&lt;/b&gt; State == #other &lt;b&gt;then&lt;/b&gt;&lt;br /&gt;                State := #unreserved;&lt;br /&gt;            &lt;b&gt;end&lt;/b&gt; &lt;b&gt;if&lt;/b&gt;;&lt;br /&gt;&lt;br /&gt;          ['"'] =&amp;gt;&lt;br /&gt;            &lt;b&gt;if&lt;/b&gt; State == #string_literal &lt;b&gt;then&lt;/b&gt;&lt;br /&gt;                &lt;i&gt;// End of string literal&lt;/i&gt;&lt;br /&gt;                State := #other;&lt;br /&gt;            &lt;b&gt;elsif&lt;/b&gt; State != #char_literal &lt;b&gt;then&lt;/b&gt;&lt;br /&gt;                State := #string_literal;&lt;br /&gt;            &lt;b&gt;end&lt;/b&gt; &lt;b&gt;if&lt;/b&gt;;&lt;br /&gt;&lt;br /&gt;          ['\''] =&amp;gt;&lt;br /&gt;            &lt;b&gt;if&lt;/b&gt; State == #char_literal &lt;b&gt;then&lt;/b&gt;&lt;br /&gt;                &lt;i&gt;// End of char literal&lt;/i&gt;&lt;br /&gt;                State := #other;&lt;br /&gt;            &lt;b&gt;elsif&lt;/b&gt; State != #string_literal &lt;b&gt;then&lt;/b&gt;&lt;br /&gt;                State := #char_literal;&lt;br /&gt;            &lt;b&gt;end&lt;/b&gt; &lt;b&gt;if&lt;/b&gt;;&lt;br /&gt;&lt;br /&gt;          [..] =&amp;gt;&lt;br /&gt;            &lt;b&gt;if&lt;/b&gt; State != #string_literal &lt;b&gt;and&lt;/b&gt; &lt;b&gt;then&lt;/b&gt; State != #char_literal &lt;b&gt;then&lt;/b&gt;&lt;br /&gt;                State := #other;&lt;br /&gt;            &lt;b&gt;end&lt;/b&gt; &lt;b&gt;if&lt;/b&gt;;&lt;br /&gt;        &lt;b&gt;end&lt;/b&gt; &lt;b&gt;case&lt;/b&gt;;&lt;br /&gt;&lt;br /&gt;        &lt;b&gt;if&lt;/b&gt; C &lt;b&gt;not&lt;/b&gt; &lt;b&gt;null&lt;/b&gt; &lt;b&gt;then&lt;/b&gt;&lt;br /&gt;            Result |= Html_Escape(C);&lt;br /&gt;        &lt;b&gt;end&lt;/b&gt; &lt;b&gt;if&lt;/b&gt;;&lt;br /&gt;        I += 1;&lt;br /&gt;    &lt;b&gt;end&lt;/b&gt; &lt;b&gt;loop&lt;/b&gt;;&lt;br /&gt;&lt;br /&gt;    Println(Result);&lt;br /&gt;&lt;b&gt;end&lt;/b&gt; &lt;b&gt;func&lt;/b&gt; Htmlize_Line;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;func&lt;/b&gt; Htmlize() &lt;b&gt;is&lt;/b&gt;&lt;br /&gt;    &lt;i&gt;// Htmlize the standard input, &lt;/i&gt;&lt;br /&gt;    &lt;i&gt;//  putting the result on the standard output&lt;/i&gt;&lt;br /&gt;    Println("&amp;lt;pre&amp;gt;");&lt;br /&gt;    &lt;b&gt;loop&lt;/b&gt;&lt;br /&gt;        &lt;b&gt;const&lt;/b&gt; Line : Univ_String := Readln();&lt;br /&gt;        &lt;b&gt;if&lt;/b&gt; Line &lt;b&gt;is&lt;/b&gt; &lt;b&gt;null&lt;/b&gt; &lt;b&gt;then&lt;/b&gt;&lt;br /&gt;            &lt;i&gt;// End of file indicated by "null"&lt;/i&gt;&lt;br /&gt;            &lt;b&gt;exit&lt;/b&gt; &lt;b&gt;loop&lt;/b&gt;;&lt;br /&gt;        &lt;b&gt;end&lt;/b&gt; &lt;b&gt;if&lt;/b&gt;;&lt;br /&gt;        Htmlize_Line(Line);&lt;br /&gt;    &lt;b&gt;end&lt;/b&gt; &lt;b&gt;loop&lt;/b&gt;;&lt;br /&gt;    Println("&amp;lt;/pre&amp;gt;");&lt;br /&gt;&lt;b&gt;end&lt;/b&gt; &lt;b&gt;func&lt;/b&gt; Htmlize;&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8383004232931899216-7106435721311334740?l=parasail-programming-language.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://parasail-programming-language.blogspot.com/feeds/7106435721311334740/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://parasail-programming-language.blogspot.com/2011/09/parasail-compiler-reaches-milestone.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8383004232931899216/posts/default/7106435721311334740'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8383004232931899216/posts/default/7106435721311334740'/><link rel='alternate' type='text/html' href='http://parasail-programming-language.blogspot.com/2011/09/parasail-compiler-reaches-milestone.html' title='ParaSail compiler reaches a milestone'/><author><name>Tuck</name><uri>http://www.blogger.com/profile/08866496974237052847</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8383004232931899216.post-3397890271581107606</id><published>2011-09-02T09:36:00.000-04:00</published><updated>2011-09-02T09:36:30.579-04:00</updated><title type='text'>ParaSail on Intel Parallel Programming Talk video</title><content type='html'>The talk about &lt;b&gt;ParaSail&lt;/b&gt; at OSCON 2011 generated a nice bit of media attention, and as a result we were invited to be on the Intel Software Network "Parallel Programming Talk" video show.&amp;nbsp; The show is now online at:&lt;br /&gt;&lt;br /&gt;&lt;a href="http://software.intel.com/en-us/blogs/2011/08/26/parasail-a-new-programming-language-parallel-programming-talk-120/" target="_blank"&gt;http://software.intel.com/en-u&lt;wbr&gt;&lt;/wbr&gt;s/blogs/2011/08/26/parasail-a-&lt;wbr&gt;&lt;/wbr&gt;new-programming-language-paral&lt;wbr&gt;&lt;/wbr&gt;lel-programming-talk-120/&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;There is a relatively long intro discussion of about 8 minutes, and then we get into the nitty gritty of ParaSail.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8383004232931899216-3397890271581107606?l=parasail-programming-language.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://parasail-programming-language.blogspot.com/feeds/3397890271581107606/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://parasail-programming-language.blogspot.com/2011/09/parasail-on-intel-parallel-programming.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8383004232931899216/posts/default/3397890271581107606'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8383004232931899216/posts/default/3397890271581107606'/><link rel='alternate' type='text/html' href='http://parasail-programming-language.blogspot.com/2011/09/parasail-on-intel-parallel-programming.html' title='ParaSail on Intel Parallel Programming Talk video'/><author><name>Tuck</name><uri>http://www.blogger.com/profile/08866496974237052847</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8383004232931899216.post-1836212039991082357</id><published>2011-07-30T17:50:00.000-04:00</published><updated>2011-07-30T17:50:24.348-04:00</updated><title type='text'>A load-and-null-out operation</title><content type='html'>As we have continued to write more programs in &lt;b&gt;ParaSail&lt;/b&gt;, we have found the pointer-free &lt;i&gt;expandable-object&lt;/i&gt; data structuring primitives very interesting to use.&amp;nbsp; A simple tree structure can be defined as:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;b&gt;interface&lt;/b&gt; Binary_Tree&amp;lt;Element_Type &lt;b&gt;is&lt;/b&gt; Assignable&amp;lt;&amp;gt;&amp;gt; &lt;b&gt;is&lt;/b&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;b&gt;var&lt;/b&gt; Left, Right : optional Binary_Tree;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;b&gt;var&lt;/b&gt; Contents : Element_Type;&lt;br /&gt;&lt;b&gt;end interface&lt;/b&gt; Binary_Tree;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;In most cases you would keep this structure private by declaring it inside the &lt;b&gt;class&lt;/b&gt; defining the Binary_Tree module rather than declaring it in the externally-visible &lt;b&gt;interface&lt;/b&gt;, but this illustrates the basic structuring technique, using &lt;b&gt;optional&lt;/b&gt; to allow recursive structures to be created.&amp;nbsp;&lt;br /&gt;&lt;br /&gt;Because there are no pointers, only sub-objects, essentially any arbitrarily complex data structure can be copied using a simple assignment:&lt;br /&gt;&lt;pre&gt;&amp;nbsp; &lt;b&gt;var&lt;/b&gt; Copy_Of_Tree : &lt;b&gt;optional&lt;/b&gt; Binary_Tree := Original_Tree;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;This will create a copy of Original_Tree, no matter how complex it is.&amp;nbsp; Similarly, we can expand a tree by assigning a new tree into its Left or Right subtree:&lt;br /&gt;&lt;pre&gt;&amp;nbsp; Original_Tree.Left := Copy_Of_Tree;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;So what did the above two assignments do?&amp;nbsp; Well they made a complete copy of the Original_Tree, and then assigned that copy into the left subtree of the Original_Tree, wiping out whatever was in the left subtree before.&amp;nbsp; But we now have a complete copy of what was in the Original_Tree.Left before in Original_Tree.Left.Left.&amp;nbsp; And Original_Tree.Left.Right is now identical in structure to Original_Tree.Right.&amp;nbsp; We could have done this without explicitly declaring the intermediate "Copy_Of_Tree" object, with the same effect:&lt;br /&gt;&lt;pre&gt;&amp;nbsp; Original_Tree.Left := Original_Tree; &lt;br /&gt;&lt;/pre&gt;I'm not sure whether what we just did was of any use, but it does give you a feel for the power of expandable objects.&amp;nbsp; The user doesn't have to write explicitly any &lt;i&gt;deep copy&lt;/i&gt; operation, since from ParaSail's point of view, these are just subobjects, and ":=" assigns the whole thing, including all of the subobjects.&amp;nbsp;&lt;br /&gt;&lt;br /&gt;The old contents of the left-hand side of an assignment are wiped out, and automatically reclaimed immediately -- no need for the user to write a &lt;i&gt;deep reclaim&lt;/i&gt; operation.&amp;nbsp; We don't need to wait for a garbage collector to decide whether it is safe to reclaim the storage associated with the old contents, since there is no sharing between objects in ParaSail.&amp;nbsp; If we overwrite the contents of an object or part of an object, whatever was there before can be reclaimed without danger of creating any dangling references.&lt;br /&gt;&lt;br /&gt;Here is another example:&lt;br /&gt;&lt;pre&gt;&amp;nbsp; Original_Tree := Original_Tree.Left;&lt;br /&gt;&lt;/pre&gt;This wipes out the old contents of Original _Tree and replaces it with a copy of its left subtree.&amp;nbsp; But there seems to be some unnecessary copying going on here.&amp;nbsp; The underlying sequence is:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Make a copy of Original_Tree.Left&lt;/li&gt;&lt;li&gt;Reclaim the old contents of Original_Tree&lt;/li&gt;&lt;li&gt;Overwrite it with the copy of Original_Tree.Left&lt;/li&gt;&lt;/ul&gt;This makes a complete copy of Original_Tree.Left, and then proceeds to reclaim all of Original_Tree (including the left subtree), and then stores the copy of the left subtree back into Original_Tree.&amp;nbsp; But wouldn't it make more sense to just &lt;i&gt;carve off&lt;/i&gt; the left subtree, leaving behind a stub (i.e. &lt;b&gt;null&lt;/b&gt;), then reclaim Original_Tree which now has a &lt;b&gt;null&lt;/b&gt; left subtree, and then set Original_Tree to be the carved-off left subtree?&amp;nbsp; In fact, if the compiler were somewhat smarter, that is exactly what it would do, and should be expected to do, since it &lt;i&gt;knows&lt;/i&gt; that Original_Tree.Left is about to be destroyed by the assignment to Original_Tree, so saving its content and replacing it with &lt;b&gt;null&lt;/b&gt; rather than making a complete copy of it would be equivalent and more efficient.&amp;nbsp; Be that as it may, it is conceivable that there are times when the compiler can't &lt;i&gt;see&lt;/i&gt; what is obvious to us, or perhaps the compiler is still just a prototype and isn't quite as smart as it will be eventually (;-).&amp;nbsp; In that case, we might want to be able to be explicit in cases where we want to fetch the value of an object or a part of an object, and after we fetch the value we want to set the object to &lt;b&gt;null&lt;/b&gt;, or perhaps to some other appropriate value. &lt;br /&gt;&lt;br /&gt;Given this situation, which seems like it might come up fairly frequently when making structural modifications to a data structure (such as rebalancing the tree), or destructively removing elements from a data structure (e.g. "Remove_First(Queue)"), we believe it might be useful to have a notion of &lt;i&gt;load-and-null-out.&lt;/i&gt;&amp;nbsp; That is, we want the value of Original.Left_Tree, but after fetching the value, we are "done" with it, so set it to &lt;b&gt;null&lt;/b&gt;.&amp;nbsp; This means we may not need to make a copy of the subobject, since it has been carved out of its old enclosing object, with a &lt;b&gt;null&lt;/b&gt; left behind.&lt;br /&gt;&lt;br /&gt;We considered various notations for representing &lt;i&gt;load-and-null-out&lt;/i&gt;, and came up with the notion of a &lt;i&gt;deferred&lt;/i&gt; assignment, that is an assignment where before we overwrite the left-hand-side, we fetch its old value and return it.&amp;nbsp; This is reminiscent of the compare-and-swap operation, or fetch-and-add, or the &lt;i&gt;post increment&lt;/i&gt; X++ of C (and PDP-11/Vax-11 fame, for those familiar with those older DEC machines).&amp;nbsp; Here is a tentative notation for a &lt;i&gt;deferred&lt;/i&gt; assignment:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&amp;nbsp;&amp;nbsp; Original_Tree := (Original_Tree.Left ::= &lt;b&gt;null&lt;/b&gt;); &lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;What the "::= &lt;b&gt;null&lt;/b&gt;" operation means is to fetch the value of Original_Tree.Left, and after doing so, assign it to &lt;b&gt;null&lt;/b&gt;.&amp;nbsp; One could imagine generalizing this &lt;i&gt;extra ':'&lt;/i&gt; notation to support &lt;i&gt;post-increment&lt;/i&gt;:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;X := A[(I :+= 1)]; &lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;This would mean fetch the value of I, and after doing so, apply the "+= 1" operation to it.&amp;nbsp; It is not obvious whether this generalization is a good idea, or just cute.&amp;nbsp; But the &lt;i&gt;deferred&lt;/i&gt; assignment of &lt;b&gt;null&lt;/b&gt; seems like an operation that will be quite useful in the pointer-free world of ParaSail, to provide more control when restructuring a complex object.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8383004232931899216-1836212039991082357?l=parasail-programming-language.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://parasail-programming-language.blogspot.com/feeds/1836212039991082357/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://parasail-programming-language.blogspot.com/2011/07/load-and-null-out-operation.html#comment-form' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8383004232931899216/posts/default/1836212039991082357'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8383004232931899216/posts/default/1836212039991082357'/><link rel='alternate' type='text/html' href='http://parasail-programming-language.blogspot.com/2011/07/load-and-null-out-operation.html' title='A load-and-null-out operation'/><author><name>Tuck</name><uri>http://www.blogger.com/profile/08866496974237052847</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8383004232931899216.post-5261489916752857492</id><published>2011-07-25T15:46:00.001-04:00</published><updated>2011-07-25T15:47:01.077-04:00</updated><title type='text'>Adapting one interface to implement another</title><content type='html'>We bumped into an interesting problem in &lt;b&gt;ParaSail&lt;/b&gt; recently.&amp;nbsp; We have an abstract module Countable which has the following interface:&lt;br /&gt;&lt;pre&gt;abstract interface Countable&amp;lt;&amp;gt; is&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; op "+"(Left : Countable; Right : Univ_Integer) -&amp;gt; Countable;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; op "+"(Left : Univ_Integer; Right : Countable) -&amp;gt; Countable;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; op "-"(Left : Countable; Right : Univ_Integer) -&amp;gt; Countable;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; op "-"(Left, Right : Countable) -&amp;gt; Univ_Integer;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; op "=?"(Left, Right : Countable) -&amp;gt; Ordering;&lt;br /&gt;end interface Countable;&lt;br /&gt;&lt;/pre&gt;This interface is used when defining a "countable interval" such as "X .. Y" where you want to be able to iterate from X up to Y, even though X and Y are not themselves of an integer type.  For example, if X and Y are characters, it makes sense to define an interval such as 'a' .. 'z' and there is a desire to be able to go from 'a' to the next character in the interval, so by using the "+" operator from Countable that is easy to do.  Just add 1.  Similarly, we can iterate through the interval in reverse by subtracting 1.  Or we can find out how big is the interval X..Y by computing (Y - X) + 1, where we are using the second "-" operator.&lt;br /&gt;&lt;br /&gt;Other examples of "countable" types are representations of time, where you can add and subtract some number of clock ticks, or compute the number of clock ticks between two times, even if the "time" type itself isn't necessarily represented as a single integer.  And in general any ordered enumeration type (such as Enum&amp;lt;[#monday,#tuesday,#wednesday, ...]&amp;gt;) might want to be considered Countable, so that intervals can be defined and manipulated.&lt;br /&gt;&lt;br /&gt;A Countable_Set abstraction would be useful as a way to represent sets of Countable elements, while still efficiently representing contiguous ranges of values such as "1..1000" as part of the set.  For example:&lt;pre&gt;interface Countable_Set&amp;lt;Element_Type is Countable&amp;lt;&amp;gt;&amp;gt; is&lt;br /&gt;    op ".."(Left, Right : Element_Type) -&gt; Countable_Set;&lt;br /&gt;    op "|"(Left, Right : Countable_Set) -&gt; Countable_Set;&lt;br /&gt;    op "in"(Left : Element_Type; Right : Countable_Set) -&amp;gt; Boolean;&lt;br /&gt;    func Count(CS : Countable_Set) -&gt; Univ_Integer;&lt;br /&gt;    ...&lt;br /&gt;end interface Countable_Set;&lt;br /&gt;&lt;/pre&gt;Implementing the Count function clearly will need to make use of the "+" or "-" Countable operations.  But this now brings us to the question, is Integer itself a Countable type?  Can we legally write Countable_Set&amp;lt;Integer&amp;gt;?  Well if we look at the binary "+" and "-" operators for Integer we see:&lt;br /&gt;&lt;pre&gt;interface Integer&amp;lt;...&amp;gt; is&lt;br /&gt;    op "+"(Left, Right : Integer) -&amp;gt; Integer;&lt;br /&gt;    op "-"(Left, Right : Integer) -&amp;gt; Integer;&lt;br /&gt;    ...&lt;br /&gt;end interface Integer;&lt;br /&gt;&lt;/pre&gt;These don't actually match the operators expected for a Countable type.  And if we were to simply add the missing operators, we would create significant ambiguity, since "X + 1" could either resolve to the existing Integer,Integer-&amp;gt;Integer "+" or to the added Countable one, Integer,Univ_Integer-&amp;gt;Integer "+".  Not ideal.  &lt;br /&gt;&lt;br /&gt;More generally, we can see a situation where a useful abstraction, such as a Countable_Set, expects a type parameter such as Countable&amp;lt;&amp;gt;, and the type we have is close but is missing some of the required operations, and we don't really want to add the missing operations for general use because of ambiguity, or they don't quite do the right thing, or whatever.  Ideally we would want to make them available for implementing a given interface or interfaces, but not for general use.&lt;br /&gt;&lt;br /&gt;Some languages provide mechanisms for addressing problems like these.  In Eiffel, as part of inheriting from another class the derived class can rename some of the operations.  With that approach, on inheriting these Countable operations we would rename them to something like "Countable_Plus" and "Countable_Minus" and then define them to do whatever we want.  In C++ it is possible to disambiguate particular operations by specifying from which base type they are inherited.&lt;br /&gt;&lt;br /&gt;In ParaSail we are pursuing somewhat of a different approach.  Essentially we are allowing a module to publicly declare that it is implementing various operations that might be needed to be considered "Countable" or "Hashable" or whatever, while not making them available for "general" use.  Here is how the ParaSail Integer module solves the Countable conundrum:&lt;pre&gt;interface Integer&amp;lt;...&amp;gt; is&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; op "+"(Left, Right : Integer) -&amp;gt; Integer;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; op "-"(Left, Right : Integer) -&amp;gt; Integer;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ...&lt;br /&gt;&amp;nbsp; implements&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; for Countable&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; op "+"(Left : Integer; Right : Univ_Integer) -&amp;gt; Integer;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; op "+"(Left : Univ_Integer; Right : Integer) -&amp;gt; Integer;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; op "-"(Left : Integer; Right : Univ_Integer) -&amp;gt; Integer;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; op "-"(Left, Right : Integer) -&amp;gt; Univ_Integer;&lt;br /&gt;end interface Integer;&lt;br /&gt;&lt;/pre&gt;You can also omit the "for Countable" part and then the operations are available to implement any other module's interface.&amp;nbsp; But the key thing is that you cannot call these operations directly on an Integer type.&amp;nbsp; You can only invoke them when "viewing" an Integer as a "Countable" object.&amp;nbsp; You can have multiple sections after "implements" each section starting with "for Interface1, Interface2, ..." if there are several different sets of operations that need to be implemented to satisfy the needs for different sets of interfaces.&amp;nbsp; In general situations like this are expected to be rare, but when you bump into one, it is useful to have a way to avoid the ambiguity and still satisfy the needs of the other interface.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8383004232931899216-5261489916752857492?l=parasail-programming-language.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://parasail-programming-language.blogspot.com/feeds/5261489916752857492/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://parasail-programming-language.blogspot.com/2011/07/adapting-one-interface-to-implement.html#comment-form' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8383004232931899216/posts/default/5261489916752857492'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8383004232931899216/posts/default/5261489916752857492'/><link rel='alternate' type='text/html' href='http://parasail-programming-language.blogspot.com/2011/07/adapting-one-interface-to-implement.html' title='Adapting one interface to implement another'/><author><name>Tuck</name><uri>http://www.blogger.com/profile/08866496974237052847</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8383004232931899216.post-453851919888325226</id><published>2011-07-23T16:43:00.000-04:00</published><updated>2011-07-23T16:43:08.855-04:00</updated><title type='text'>Another slight shift in syntax</title><content type='html'>As we use &lt;b&gt;ParaSail&lt;/b&gt; more, we are making some additional small changes in syntax.&amp;nbsp; The first one has to do with allowing a component to be declared as a reference to another object.&amp;nbsp; The ability to return a short-lived object reference is important for user-defined indexing.&amp;nbsp; We also imagine that certain data structures will want to incorporate references as components.&amp;nbsp; Such data structures will not allow assignment, but nevertheless they can be useful for iterating over some other data structure.&amp;nbsp;&amp;nbsp;&amp;nbsp; For example, one might have a complex tree structure, and then an iterator over the structure which contains a reference to the current item in the tree, and references to the enclosing nodes in the tree, so that given the iterator one can generate a reference to the next element of the tree (presuming some ordering such as depth-first left-to-right).&lt;br /&gt;&lt;br /&gt;Currently, object references are recognized by using "=&amp;gt;" rather than ":=" for defining their initial value.&amp;nbsp; However, that is somewhat subtle, and for a component, the initial value can't be specified when the component is declared.&amp;nbsp; Having already used the term "ref" for parameters that act as references, we have chosen to change the syntax for other objects that are references by explicitly using the term "ref" for them as well.&amp;nbsp; For example:&lt;br /&gt;&lt;pre&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;b&gt;ref&lt;/b&gt; X =&amp;gt; M[I];&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;b&gt;ref&lt;/b&gt; &lt;b&gt;const&lt;/b&gt; R =&amp;gt; T.Right;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &lt;b&gt;ref&lt;/b&gt; &lt;b&gt;var&lt;/b&gt; L =&amp;gt; T.Left; &lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;A "ref" by itself means that the reference is a read-write reference only if the object to which it refers is a variable.&amp;nbsp; Explicitly using "ref const" makes the reference read-only even if the object to which it refers is a variable.&amp;nbsp; Explicitly using "ref var" makes the reference read-write, and requires the object to which it refers to be a variable.&amp;nbsp; So the first example above creates a reference to the Ith element of M, providing read-write access only if M is a variable, the second creates a read-only reference to the Right component of T, and the third creates a read-write reference to the Left component of T, and requires that T itself is a variable.&lt;br /&gt;&lt;br /&gt;Having adopted the use of "ref", we can now leave off the "=&amp;gt; obj" part and simply specify a type, and in that way declare a component which will be a reference.  Here is an example of an iterator that walks over a tree structure.  It uses a "ref" component to point to a particular node in the tree:&lt;br /&gt;&lt;pre&gt;    &lt;b&gt;class&lt;/b&gt; Tree_Iterator &lt;b&gt;is&lt;/b&gt;&lt;br /&gt;        &lt;b&gt;ref&lt;/b&gt; Current_Node : Tree_Node;&lt;br /&gt;        &lt;b&gt;var&lt;/b&gt; Enclosing_Node : &lt;b&gt;optional&lt;/b&gt; Tree_Iterator;&lt;br /&gt;        &lt;b&gt;var&lt;/b&gt; Which_Child : Child_Index; &lt;br /&gt;      &lt;b&gt;exports&lt;/b&gt;&lt;br /&gt;        &lt;b&gt;func&lt;/b&gt; First_Item(&lt;b&gt;ref&lt;/b&gt; Root : Tree_Node) -&amp;gt; Tree_Iterator &lt;b&gt;is&lt;/b&gt;&lt;br /&gt;            &lt;i&gt;// Return leftmost child of Root to start the iteration&lt;/i&gt;&lt;br /&gt;            &lt;b&gt;return&lt;/b&gt; Leftmost_Child&lt;br /&gt;              ((Current_Node =&amp;gt; Root, Enclosing_Node =&amp;gt; null, Which_Child =&amp;gt; 0));&lt;br /&gt;        &lt;b&gt;end func&lt;/b&gt; First_Item;&lt;br /&gt;&lt;br /&gt;        &lt;b&gt;func&lt;/b&gt; Leftmost_Child(It : Tree_Iterator) -&amp;gt; Tree_Iterator is&lt;br /&gt;             &lt;i&gt;// Return iterator designating leftmost child&lt;/i&gt;&lt;br /&gt;             &lt;b&gt;if&lt;/b&gt; Num_Children(It.Current_Node) == 0 &lt;b&gt;then&lt;/b&gt;&lt;br /&gt;                 &lt;i&gt;// We are at the leftmost child already&lt;/i&gt;&lt;br /&gt;                 &lt;b&gt;return&lt;/b&gt; It;&lt;br /&gt;             &lt;b&gt;else&lt;/b&gt;&lt;br /&gt;                 &lt;i&gt;// Recurse down the left side&lt;/i&gt;&lt;br /&gt;                 &lt;b&gt;return&lt;/b&gt;&lt;br /&gt;                   (Current_Node =&amp;gt; It.Current_Node[1],&lt;br /&gt;                    Enclosing_Node =&amp;gt; It,&lt;br /&gt;                    Which_Child =&amp;gt; 1);&lt;br /&gt;             &lt;b&gt;end if&lt;/b&gt;;&lt;br /&gt;        &lt;b&gt;end func&lt;/b&gt; Leftmost_Child;&lt;br /&gt;&lt;br /&gt;        &lt;b&gt;func &lt;/b&gt;Next_Item(It : Tree_Iterator) -&amp;gt; &lt;b&gt;optional&lt;/b&gt; Tree_Iterator is&lt;br /&gt;            &lt;i&gt;// Advance iterator to next item in left-to-right depth-first walk&lt;/i&gt;&lt;br /&gt;            &lt;b&gt;if &lt;/b&gt;It.Enclosing_Node &lt;b&gt;is null then&amp;nbsp;&lt;/b&gt;&lt;br /&gt;                &lt;i&gt;// All done&lt;/i&gt;&lt;br /&gt;                &lt;b&gt;return null&lt;/b&gt;;&lt;br /&gt;            &lt;b&gt;elsif&lt;/b&gt; It.Which_Child &amp;lt; Num_Children(It.Enclosing_Node.Current_Node) &lt;b&gt;then&lt;/b&gt;&lt;br /&gt;                &lt;i&gt;// Return next child of same enclosing node&lt;/i&gt;&lt;br /&gt;                &lt;b&gt;return&lt;/b&gt; Leftmost_Child&lt;br /&gt;                  ((Current_Node =&amp;gt; It.Enclosing_Node[It.Which_Child + 1],&lt;br /&gt;                    Enclosing_Node =&amp;gt; It.Enclosing_Node,&lt;br /&gt;                    Which_Child =&amp;gt; It.Which_Child + 1));&lt;br /&gt;            &lt;b&gt;else&lt;/b&gt;&lt;br /&gt;                &lt;i&gt;// Recurse to go to next sibling of enclosing node&lt;/i&gt;&lt;br /&gt;                &lt;b&gt;return&lt;/b&gt; Next_Item(It.Enclosing_Node);&lt;br /&gt;            &lt;b&gt;end if;&lt;/b&gt;&lt;br /&gt;        &lt;b&gt;end func&lt;/b&gt; Next_Item;&lt;br /&gt;        ...&lt;br /&gt;    &lt;b&gt;end class&lt;/b&gt; Tree_Iterator; &lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;This Tree_Iterator has a component that is a reference to a node in a tree, an optional Tree_Iterator for the enclosing node in the tree, and an indication of which child the current node is of the enclosing node.&lt;br /&gt;&lt;br /&gt;By specifying simply "ref" rather than "ref var" or "ref const" for the Current_Node reference, we are saying that it is a reference to a variable when the enclosing Tree_Iterator object is a variable.&lt;br /&gt;&lt;br /&gt;Any type that has a (constructor) function in its interface that takes a "ref" input and produces a new object of the type as an output is presumed to be burying the "ref" somewhere in the object.  (Of course the compiler can just "look" in the class and see this, but a client of the module wants to know strictly from looking at the interface.)  If the objects of a type incorporate a reference within them, then objects of that type do not permit assignment, since references in ParaSail are always required to be short-lived.  The result of such a constructor function therefore can only be used to initialize a new object, be passed as a parameter, or be used to define the next value for a loop variable.  The result of such a function cannot be assigned as the new value for an existing object.&lt;br /&gt;&lt;br /&gt;Now that we are using "ref" explicitly for objects and components, it makes the syntax used for parameters, where "ref" comes after the parameter name and the ":", seem inconsistent.  Hence we are changing the syntax for parameters to more closely match that of objects and components:&lt;br /&gt;&lt;pre&gt;    operation_input ::= &lt;br /&gt;       id ':' type [ := default ]&lt;br /&gt;     | 'var' id ':' type&lt;br /&gt;     | 'ref' [ 'var' | 'const' ] id ':' type&lt;br /&gt;     | 'global' [ 'var' ] id ':' type&lt;br /&gt;     | [ 'locked' | 'queued' ] [ 'var' ] id ':' type &lt;br /&gt;&lt;br /&gt;   operation_output ::=&lt;br /&gt;       [ id ':' ] type&lt;br /&gt;     | 'ref' [ 'var' | 'const' ] [ id ':' ] type&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;For example:&lt;br /&gt;&lt;pre&gt;    &lt;b&gt;func&lt;/b&gt; Append(&lt;b&gt;var&lt;/b&gt; L : List; E : Element);&lt;br /&gt;    &lt;b&gt;op&lt;/b&gt; "indexing"(&lt;b&gt;ref&lt;/b&gt; V : Vector; I : Index) -&amp;gt; &lt;b&gt;ref&lt;/b&gt; Element;&lt;br /&gt;    &lt;b&gt;func&lt;/b&gt; Get_Next(&lt;b&gt;queued&lt;/b&gt; &lt;b&gt;var&lt;/b&gt; Q : Queue) -&amp;gt; Element;&lt;br /&gt;&lt;/pre&gt;We will be posting a new draft of the ParaSail reference manual reflecting these changes shortly to the ParaSail google group:&lt;br /&gt;&lt;a href="http://groups.google.com/group/parasail-programming-language"&gt;http://groups.google.com/group/parasail-programming-language&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8383004232931899216-453851919888325226?l=parasail-programming-language.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://parasail-programming-language.blogspot.com/feeds/453851919888325226/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://parasail-programming-language.blogspot.com/2011/07/another-slight-shift-in-syntax.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8383004232931899216/posts/default/453851919888325226'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8383004232931899216/posts/default/453851919888325226'/><link rel='alternate' type='text/html' href='http://parasail-programming-language.blogspot.com/2011/07/another-slight-shift-in-syntax.html' title='Another slight shift in syntax'/><author><name>Tuck</name><uri>http://www.blogger.com/profile/08866496974237052847</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8383004232931899216.post-1056921679004284462</id><published>2011-07-13T18:17:00.000-04:00</published><updated>2011-07-13T18:17:17.520-04:00</updated><title type='text'>Everything in a func?</title><content type='html'>Here is an issue which is trivial semantically, but potentially has a more substantial effect on the look and feel of the language.&amp;nbsp; Currently, reflecting to some extent the Pascal heritage, &lt;b&gt;ParaSail&lt;/b&gt; uses the terms "function," "procedure," and "operator" for the various kinds of operations.&amp;nbsp; Functions must have at least one output, procedures may not have any outputs, and operators may have zero or more outputs, but have a name given in quotes and are used for defining operations that connect into special syntax or semantics, such as unary or binary operators, implicit conversions from universal types, etc.&lt;br /&gt;&lt;br /&gt;As we go about creating more examples in ParaSail, and compare with various other recent languages, we find the use of these three distinct terms not particularly helpful, and certainly more verbose than most other languages.&amp;nbsp; On the other hand, the terms do communicate something about the appropriate use of the operations.&lt;br /&gt;&lt;br /&gt;We are now leaning toward replacing all three terms with the term "&lt;b&gt;func&lt;/b&gt;".&amp;nbsp; Our sense is this would give the syntax a somewhat less heavy, and perhaps more modern feel.&amp;nbsp; We would retain the requirement to echo the term at the end of the operation, hence:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;b&gt;func&lt;/b&gt; GCD(X, Y : Integer) -&amp;gt; Integer &lt;b&gt;is&lt;/b&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &lt;b&gt;case&lt;/b&gt; X =? Y &lt;b&gt;of&lt;/b&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; [#less] =&amp;gt; &lt;b&gt;return&lt;/b&gt; GCD(X, Y &lt;b&gt;mod&lt;/b&gt; X);&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; [#equal] =&amp;gt; &lt;b&gt;return&lt;/b&gt; X;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [#greater] =&amp;gt; &lt;b&gt;return&lt;/b&gt; GCD(X &lt;b&gt;mod&lt;/b&gt; Y, Y);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;b&gt;end case&lt;/b&gt;;&lt;br /&gt;&lt;b&gt;end func&lt;/b&gt; GCD;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;func&lt;/b&gt; Print(F : &lt;b&gt;ref var&lt;/b&gt; File; X : Integer) &lt;b&gt;is&lt;/b&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;b&gt;if&lt;/b&gt; &lt;b&gt;abs&lt;/b&gt; X &amp;gt;= 10 &lt;b&gt;then&lt;/b&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Print(F, X/10);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;b&gt;end if&lt;/b&gt;;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Print(F, '0' + (X &lt;b&gt;rem&lt;/b&gt; 10))&lt;br /&gt;&lt;b&gt;end func&lt;/b&gt; Print;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;func&lt;/b&gt; "|"(X : Set; E : Elem) -&amp;gt; Set &lt;b&gt;is&lt;/b&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &lt;b&gt;return&lt;/b&gt; Union(X, Make_Set(E)); &lt;br /&gt;&lt;b&gt;end func&lt;/b&gt; "|";&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;The above three "&lt;b&gt;func&lt;/b&gt;"s would be "&lt;b&gt;function&lt;/b&gt; GCD," "&lt;b&gt;procedure&lt;/b&gt; Print," and &lt;b&gt;operator&lt;/b&gt; "|" using the current ParaSail syntax.&amp;nbsp; Given that we are already abbreviating "constant" to &lt;b&gt;const&lt;/b&gt; and "variable" to &lt;b&gt;var&lt;/b&gt; in ParaSail, it doesn't seem inconsistent to adopt a standard abbreviation here for function/procedure/operator, and &lt;b&gt;func&lt;/b&gt; is one that appears in a number of languages.&lt;br /&gt;&lt;br /&gt;Now this is an issue about which anyone and everyone probably has an opinion...&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8383004232931899216-1056921679004284462?l=parasail-programming-language.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://parasail-programming-language.blogspot.com/feeds/1056921679004284462/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://parasail-programming-language.blogspot.com/2011/07/everything-in-func.html#comment-form' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8383004232931899216/posts/default/1056921679004284462'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8383004232931899216/posts/default/1056921679004284462'/><link rel='alternate' type='text/html' href='http://parasail-programming-language.blogspot.com/2011/07/everything-in-func.html' title='Everything in a func?'/><author><name>Tuck</name><uri>http://www.blogger.com/profile/08866496974237052847</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8383004232931899216.post-273360005208438194</id><published>2011-07-07T14:48:00.000-04:00</published><updated>2011-07-07T14:48:19.840-04:00</updated><title type='text'>Implementing concurrent loops in ParaSail</title><content type='html'>The implementation of the &lt;b&gt;ParaSail&lt;/b&gt; compiler and virtual machine (see &lt;a href="http://parasail-programming-language.blogspot.com/2010/11/virtual-machine-for-parasail-with.html"&gt;http://parasail-programming-language.blogspot.com/2010/11/virtual-machine-for-parasail-with.html&lt;/a&gt;) are proceeding apace.&amp;nbsp; Basic support is there for interfaces, classes, operators, functions, procedures, module instantiations, object and type declarations, if, case, while, and assignment statements, user-defined indexing, parallel evaluation of expressions, parallel execution of statements on either side of a "||", etc.&amp;nbsp; However, a big gap at the moment is &lt;b&gt;for&lt;/b&gt; loops, and in particular &lt;b&gt;concurrent&lt;/b&gt; for loops.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;For&lt;/b&gt; loops are a bit unusual in ParaSail, as they support both a &lt;b&gt;continue loop&lt;/b&gt; and an &lt;b&gt;exit&amp;nbsp; loop&lt;/b&gt; (i.e. "break") capability in the presence of parallelism.&amp;nbsp; Here is an example using &lt;b&gt;continue loop&lt;/b&gt;:&lt;br /&gt;&lt;pre&gt;&lt;b&gt;for&lt;/b&gt; X =&amp;gt; Root &lt;b&gt;while&lt;/b&gt; X &lt;b&gt;not null loop&lt;/b&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;b&gt;case&lt;/b&gt; X.Kind &lt;b&gt;of&lt;/b&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [#leaf] =&amp;gt; Process(X.Data);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [#unary] =&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Process(X.Data);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;  ||&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;b&gt;continue loop with&lt;/b&gt; X =&amp;gt; X.Operand;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [#binary] =&amp;gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Process(X.Data);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ||&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;b&gt;continue loop with&lt;/b&gt; X =&amp;gt; X.Left;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ||&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;b&gt;continue loop with&lt;/b&gt; X =&amp;gt; X.Right;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;b&gt;end case&lt;/b&gt;;&lt;br /&gt;&lt;b&gt;end loop&lt;/b&gt;;&lt;br /&gt;&lt;/pre&gt;Here is an example using &lt;b&gt;exit loop&lt;/b&gt;:&lt;br /&gt;&lt;pre&gt;&lt;b&gt;const&lt;/b&gt; Result : Id_Type; &lt;br /&gt;&lt;b&gt;for&lt;/b&gt; X =&amp;gt; Root &lt;b&gt;then&lt;/b&gt; X.Left || X.Right &lt;b&gt;while&lt;/b&gt; X &lt;b&gt;not null&amp;nbsp;&lt;/b&gt;&lt;br /&gt;&lt;b&gt;  concurrent loop&lt;/b&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;b&gt;if&lt;/b&gt; X.Value == Desired_Value &lt;b&gt;then&lt;/b&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;b&gt;exit loop with&lt;/b&gt; Result =&amp;gt; X.Id;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;b&gt;end if&lt;/b&gt;;&lt;br /&gt;&lt;b&gt;end loop with&lt;/b&gt; Result =&amp;gt; &lt;b&gt;null&lt;/b&gt;;&lt;br /&gt;&lt;/pre&gt;This first example processes an expression tree, and creates parallelism by using an explicit &lt;b&gt;continue loop&lt;/b&gt; statement in concert with a concurrent sequence ("||") construct.  The second example searches a binary tree and creates parallelism by both the use of &lt;b&gt;concurrent loop&lt;/b&gt; and by having two values in the &lt;b&gt;then&lt;/b&gt; part of the &lt;b&gt;for&lt;/b&gt; loop header, which will result in the execution of the loop splitting into two separate threads at each binary node.&lt;br /&gt;&lt;br /&gt;The semantics of saying &lt;b&gt;concurrent loop&lt;/b&gt; rather than simply &lt;b&gt;loop&lt;/b&gt; is that the next iteration starts before even starting the current iteration.&amp;nbsp; If we had said simply &lt;b&gt;loop&lt;/b&gt; in the second example, then it would first check the Root node to see if it has the Desired_Value, and only if it did not would we proceed on to the next iteration(s), at which point we would check both the Left and Right subtrees (presuming both were non-&lt;b&gt;null&lt;/b&gt;).&amp;nbsp; Since we said &lt;b&gt;concurrent loop&lt;/b&gt;, the iteration on the Left and Right subtrees begins in parallel with executing the loop body on the Root.&lt;br /&gt;&lt;br /&gt;The semantics of the &lt;b&gt;exit loop&lt;/b&gt; statement are that all other threads within the loop being exited are stopped, and when the thread first reaching the &lt;b&gt;exit loop&lt;/b&gt; is the only thread remaining, the assignments specified by the &lt;b&gt;with&lt;/b&gt;-values clause are performed.&amp;nbsp; If the loop ends normally without an &lt;b&gt;exit loop&lt;/b&gt;, then the assignments specified by the &lt;b&gt;end with&lt;/b&gt;-values clause are performed.&amp;nbsp; The net effect is that if the Desired_Value is in the tree, Result ends up with the Id of that node.&amp;nbsp; If it is not found, Result ends up &lt;b&gt;null&lt;/b&gt;.&lt;br /&gt;&lt;br /&gt;See &lt;a href="http://parasail-programming-language.blogspot.com/2010/06/generalized-for-loops-in-parasail.html"&gt;http://parasail-programming-language.blogspot.com/2010/06/generalized-for-loops-in-parasail.html&lt;/a&gt; and &lt;a href="http://parasail-programming-language.blogspot.com/2010/06/intentional-race-condition-in-parasail.html"&gt;http://parasail-programming-language.blogspot.com/2010/06/intentional-race-condition-in-parasail.html&lt;/a&gt; for more details about the generalized &lt;b&gt;for loop&lt;/b&gt; capabilities. &lt;br /&gt;&lt;br /&gt;So given all of the above, what should be the implementation model for a &lt;b&gt;for loop&lt;/b&gt; in ParaSail?&amp;nbsp; As mentioned in the blog entry on the ParaSail virtual machine (PSVM -- see link in first paragraph above), the implementation uses &lt;i&gt;pico-threads&lt;/i&gt; to represent the potential parallelism in the code.&amp;nbsp; There are PSVM instructions for invoking a separate operation, or a local block, as a separate parallel pico-thread.&amp;nbsp; Currently this is used to support parallel evaluation of expressions or concurrent sequences ("||"), where each operand of a call on an operation, or each side of "||",&amp;nbsp; can be evaluated in its own pico-thread.&amp;nbsp; In fact, the compiler is a bit smarter than that, and it doesn't bother to create a pico-thread if the computation of the operand involves only simple built-in operations (such as basic arithmetic, numeric comparisons, etc.).&amp;nbsp; If it involves an out-of-line call then it becomes a candidate for being turned into a pico-thread (this is clearly an area for tuning of the compiler as more experience is gained).&lt;br /&gt;&lt;br /&gt;So it makes sense for the body of a &lt;b&gt;concurrent loop&lt;/b&gt;, or a loop that gains parallelism through multiple parallel "next" values or explicit uses of &lt;b&gt;continue loop&lt;/b&gt; inside a concurrent sequence, to be executed as a separate pico-thread.&amp;nbsp; The compiler can turn the loop body into a local operation, with the parameter(s) being the loop index (or indices).&amp;nbsp; A &lt;b&gt;continue loop&lt;/b&gt; is essentially a (tail) recursive call on this local loop-body operation, with the parameter being the next value specified in the &lt;b&gt;with&lt;/b&gt;-values clause.&amp;nbsp; Similarly, if there are explicit "next" values given after &lt;b&gt;then&lt;/b&gt; in the loop header, these can be handled using (parallel) calls on the loop-body operation, with the "next" value as the parameter.&lt;br /&gt;&lt;br /&gt;Rather than using tail recursion, an alternative is to use a parallel call followed by a return, with the pico-thread for the parallel call being associated with a pico-thread &lt;i&gt;master&lt;/i&gt; that controls the entire loop.&amp;nbsp; At the outer level, the whole loop can then be executed by creating the pico-thread master, and then starting the loop off with a parallel call on the loop-body operation, followed by waiting for the pico-thread master to be complete.&amp;nbsp;&lt;br /&gt;&lt;br /&gt;The overall flow would be:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Create pico-thread master.&lt;/li&gt;&lt;li&gt;Initiate parallel-call on loop-body operation with parameter referring to initial value of loop index, presuming initial value satisfies the &lt;b&gt;while&lt;/b&gt; condition (if any).&lt;/li&gt;&lt;li&gt;Wait for pico-thread master to be complete.&lt;/li&gt;&lt;/ul&gt;At the end of an iteration of a &lt;b&gt;loop&lt;/b&gt;, or at a &lt;b&gt;continue loop&lt;/b&gt; statement, the flow would be:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Determine next value(s) for loop index.&amp;nbsp;&amp;nbsp;&lt;/li&gt;&lt;li&gt;Initiate parallel call(s) on loop-body operation with parameter referring to next value, presuming value satisfies the &lt;b&gt;while&lt;/b&gt; condition (if any).&lt;/li&gt;&lt;li&gt;Return from the loop-body operation (don't wait for the call(s) to complete).&lt;/li&gt;&lt;/ul&gt;At the &lt;i&gt;beginning&lt;/i&gt; of an iteration of a &lt;i&gt;&lt;b&gt;concurrent&lt;/b&gt;&lt;/i&gt; &lt;b&gt;loop&lt;/b&gt;, the flow would be:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Determine next value(s) for loop index.&amp;nbsp;&amp;nbsp;&lt;/li&gt;&lt;li&gt;Initiate parallel call(s) on loop-body operation with parameter referring to next value, presuming value satisfies the &lt;b&gt;while&lt;/b&gt; condition (if any).&lt;/li&gt;&lt;li&gt;Perform the loop body for the current value.&lt;/li&gt;&lt;li&gt;Return from the loop-body operation (don't wait for the call(s) to complete). &lt;/li&gt;&lt;/ul&gt;When reaching an &lt;b&gt;exit loop&lt;/b&gt; statement, the flow would be:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Tell pico-thread master of loop to terminate all but the current thread.&lt;/li&gt;&lt;li&gt;Wait for other threads to terminate.&lt;/li&gt;&lt;li&gt;Perform &lt;b&gt;with&lt;/b&gt;-values assignment(s).&lt;/li&gt;&lt;li&gt;Return from the loop-body operation.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;When the master is complete:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;If there is a&lt;b&gt; with&lt;/b&gt;-values clause on the &lt;b&gt;end loop&lt;/b&gt; and the master completed normally, as opposed to being terminated early by an &lt;b&gt;exit loop&lt;/b&gt; statement:&lt;/li&gt;&lt;/ul&gt;&lt;ol&gt;&lt;ul&gt;&lt;li&gt;Perform the assignment(s) specified by the &lt;b&gt;end loop&lt;/b&gt; &lt;b&gt;with&lt;/b&gt;-values clause.&lt;/li&gt;&lt;/ul&gt;&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8383004232931899216-273360005208438194?l=parasail-programming-language.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://parasail-programming-language.blogspot.com/feeds/273360005208438194/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://parasail-programming-language.blogspot.com/2011/07/implementing-concurrent-loops-in.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8383004232931899216/posts/default/273360005208438194'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8383004232931899216/posts/default/273360005208438194'/><link rel='alternate' type='text/html' href='http://parasail-programming-language.blogspot.com/2011/07/implementing-concurrent-loops-in.html' title='Implementing concurrent loops in ParaSail'/><author><name>Tuck</name><uri>http://www.blogger.com/profile/08866496974237052847</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8383004232931899216.post-4390500168156958741</id><published>2011-06-03T08:52:00.001-04:00</published><updated>2011-07-07T13:55:04.143-04:00</updated><title type='text'>Upcoming presentations on ParaSail -- Edinburgh and Portland</title><content type='html'>This summer we will be presenting on ParaSail at:&lt;br /&gt;&lt;ul&gt;&lt;li&gt; AdaEurope 2011 in Edinburgh, Scotland, Tutorial/Workshop on Experimenting with ParaSail (Monday 20-June-2011, 9:00am - 1:00pm GMT) &lt;a href="http://conferences.ncl.ac.uk/adaconnection2011/tutorials/T1.html"&gt;http://conferences.ncl.ac.uk/adaconnection2011/tutorials/T1.html&lt;/a&gt;&lt;/li&gt;&lt;li&gt; OSCON 2011 in Portland, Introduction to ParaSail (Weds. 27-July-2011&amp;nbsp; 10:40am -&amp;nbsp; 11:20am PDT Room: E144 --NOTE the time change) &lt;a href="http://www.oscon.com/oscon2011/public/schedule/detail/18557"&gt;http://www.oscon.com/oscon2011/public/schedule/detail/18557&lt;/a&gt; &lt;/li&gt;&lt;/ul&gt;You can still register for both of these conferences.  For OSCON, there is a 20% registration discount if you use the code "os11fos".&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8383004232931899216-4390500168156958741?l=parasail-programming-language.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://parasail-programming-language.blogspot.com/feeds/4390500168156958741/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://parasail-programming-language.blogspot.com/2011/06/upcoming-presentations-on-parasail.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8383004232931899216/posts/default/4390500168156958741'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8383004232931899216/posts/default/4390500168156958741'/><link rel='alternate' type='text/html' href='http://parasail-programming-language.blogspot.com/2011/06/upcoming-presentations-on-parasail.html' title='Upcoming presentations on ParaSail -- Edinburgh and Portland'/><author><name>Tuck</name><uri>http://www.blogger.com/profile/08866496974237052847</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8383004232931899216.post-1741326844278907047</id><published>2011-05-25T14:06:00.000-04:00</published><updated>2011-05-25T14:06:39.766-04:00</updated><title type='text'>When null isn't just null -- value representation in ParaSail</title><content type='html'>The qualifier &lt;b&gt;optional&lt;/b&gt; may be applied to any type in &lt;b&gt;ParaSail&lt;/b&gt;, effectively producing a type with one additional value, namely the &lt;b&gt;null&lt;/b&gt; value.&amp;nbsp; In many languages, &lt;b&gt;null&lt;/b&gt; is only used for pointer types, and is often represented as a zero address.&amp;nbsp; In ParaSail, we want to be able to add the &lt;b&gt;null&lt;/b&gt; value to any type without presuming that the zero value is available for that purpose, so this means that the representation for &lt;b&gt;null&lt;/b&gt; will vary depending on the particular type.&lt;br /&gt;&lt;br /&gt;For simple types, coming up with a &lt;b&gt;null&lt;/b&gt; value is pretty straightforward.&amp;nbsp; For unsigned integer types, a value one greater than the maximum value could be used for &lt;b&gt;null&lt;/b&gt;.&amp;nbsp;&amp;nbsp; For example, given an unsigned type going from 0 to 100, the value 101 could be used to represent &lt;b&gt;null&lt;/b&gt;.&amp;nbsp; Similarly, for enumeration types that use an internal unsigned integer representation, such as 0 for #false and 1 for #true, the null value could be represented by one more than the maximum internal unsigned integer code, for example 2 for the &lt;b&gt;null&lt;/b&gt; value of an &lt;b&gt;optional&lt;/b&gt; Boolean type.&amp;nbsp; For a signed integer type, one less than the minimum value might make sense, particularly on a 2's complement machine where there is one "extra" negative value anyway.&amp;nbsp; So for a 64-bit signed integer, one might use -2**63+1 .. 2**63-1 for "normal" values of the type, and reserve -2**63 for the &lt;b&gt;null&lt;/b&gt; value.&amp;nbsp; Most floating point representations include the notion of "Not a Number" (NaN), and some NaN value would make sense for &lt;b&gt;null&lt;/b&gt;.&amp;nbsp; Since there are no run-time checks in ParaSail (checking all being done at compile-time), it would be fine to use a "non-signaling" NaN for &lt;b&gt;null&lt;/b&gt;.&lt;br /&gt;&lt;br /&gt;For more complex types, the representation for &lt;b&gt;null&lt;/b&gt; is a bit more interesting.&amp;nbsp; One common kind of type would be a simple "wrapper," that is, a type defined by a class that has exactly one &lt;b&gt;var&lt;/b&gt; component.&amp;nbsp; For example:&lt;br /&gt;&lt;pre&gt;&lt;b&gt;class&lt;/b&gt; Box&amp;lt;Contents_Type &lt;b&gt;is&lt;/b&gt; Assignable&amp;lt;&amp;gt;&amp;gt; &lt;b&gt;is&lt;/b&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;b&gt;var&lt;/b&gt; Contents : Contents_Type;&lt;br /&gt;&amp;nbsp; &lt;b&gt;exports&lt;/b&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;b&gt;function&lt;/b&gt; Create(Value : Contents_Type) -&amp;gt; Box &lt;b&gt;is&lt;/b&gt;&lt;br /&gt;      &lt;b&gt;return&lt;/b&gt; (Contents =&amp;gt; Value);&lt;br /&gt;    &lt;b&gt;end function&lt;/b&gt; Create;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;...&lt;br /&gt;&lt;b&gt;end class &lt;/b&gt;Box; &lt;br /&gt;&lt;/pre&gt;In this case, it would be nice to have the wrapper type use exactly the same representation as that of the underlying component type (e.g. Contents_Type).&amp;nbsp; This would mean that the &lt;b&gt;null&lt;/b&gt; value for the wrapper would be the same as the &lt;b&gt;null&lt;/b&gt; value for the component type.&amp;nbsp; This does mean that the component type must not itself be marked as &lt;b&gt;optional&lt;/b&gt;, as then there would be no way to distinguish the wrapper being non-&lt;b&gt;null&lt;/b&gt; but containing a single &lt;b&gt;null&lt;/b&gt; component, from the case where the wrapper itself is &lt;b&gt;null&lt;/b&gt;.&lt;br /&gt;&lt;br /&gt;So our conclusion is that a wrapper type can use the same representation as its component type so long as the component type is not itself marked &lt;b&gt;optional&lt;/b&gt;.&amp;nbsp; If the component type is itself marked &lt;b&gt;optional&lt;/b&gt;, then the wrapper needs to allow for its "own" representation for &lt;b&gt;null&lt;/b&gt;, which might in some cases be accommodated by simply allowing for yet one more value if the component type is "simple," or a level of indirection for a more complex component type.&lt;br /&gt;&lt;br /&gt;Now what about more complex types?&amp;nbsp; For example, a type defined by a class with multiple &lt;b&gt;var&lt;/b&gt; components:&lt;br /&gt;&lt;pre&gt;&lt;b&gt;class&lt;/b&gt; Pair&amp;lt;Element_Type &lt;b&gt;is&lt;/b&gt; Assignable&amp;lt;&amp;gt;&amp;gt; &lt;b&gt;is&lt;/b&gt;&lt;br /&gt;&lt;b&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; var&lt;/b&gt; Left : Element_Type;&lt;br /&gt;&lt;b&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; var&lt;/b&gt; Right : Element_Type;&lt;br /&gt;&amp;nbsp; &lt;b&gt;exports&lt;/b&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;b&gt;function&lt;/b&gt; Cons(Left, Right : Element_Type) -&amp;gt; Pair &lt;b&gt;is&lt;/b&gt;&lt;br /&gt;      &lt;b&gt;return&lt;/b&gt; (Left =&amp;gt; Left, Right =&amp;gt; Right);&lt;br /&gt;    &lt;b&gt;end function&lt;/b&gt; Cons;&lt;br /&gt;&amp;nbsp; &amp;nbsp; ...&lt;br /&gt;&lt;b&gt;end&lt;/b&gt; &lt;b&gt;class&lt;/b&gt; Pair;&amp;nbsp; &lt;br /&gt;&lt;/pre&gt;One obvious representation for a type with multiple components is as a sequence of memory cells long enough to accommodate the representation of each of the components, and then some provision for representing&lt;b&gt; null&lt;/b&gt;, which could be by piggy-backing on one of the components if it is not itself allowed to be &lt;b&gt;null&lt;/b&gt;, or by adding an additional bit to indicate &lt;b&gt;null&lt;/b&gt;-ness.&amp;nbsp; However, in our initial (prototype, ParaSail-Virtual-Machine-based) implementation, we have chosen to represent every object using a single 64-bit memory cell.&amp;nbsp; This basically means that if the value cannot fit in a single 64-bit cell, it will need to use a level of indirection.&amp;nbsp; To simplify further, we won't be doing any "packing" initially, so even if the components are each quite short (such as booleans), we will nevertheless go to an indirect representation.&amp;nbsp; We do anticipate supporting packed arrays, but that would initially be handled by doing explicit shifting and masking, rather than by building in the notion of packing into the ParaSail Virtual Machine instruction set.&amp;nbsp; In the ParaSail Virtual Machine, pretty much everything occupies a single 64-bit word.&lt;br /&gt;&lt;br /&gt;So back to the initial question -- how will we represent objects with multiple components (or with a single component whose type is marked &lt;b&gt;optional&lt;/b&gt;)?&amp;nbsp; And how will we represent &lt;b&gt;null&lt;/b&gt; for such objects?&amp;nbsp; One important thing to remember is that (large) ParaSail objects live in regions, and the regions are associated with stack frames.&amp;nbsp; Whenever assigning a value to an object, if the new value can't "fit" in the same space as its current value, then the space for the old value needs to be released and the space for the new value needs to be allocated, in the appropriate region.&amp;nbsp; Since a "&lt;b&gt;ref var&lt;/b&gt;" parameter (or subcomponent thereof) might be assigned a new value, it won't necessarily be known at compile-time what region the object being assigned "lives" in.&amp;nbsp; This suggests that every value for a large object must identify its region, so that its space can be released back to that region when it is freed, and so that the new value can be allocated in that region.&amp;nbsp; This same requirement applies even if the object has a &lt;b&gt;null&lt;/b&gt; value to begin with.&amp;nbsp; Hence, we are left with the conclusion that a &lt;b&gt;null&lt;/b&gt; value for a "large" type needs to identify its region.&lt;br /&gt;&lt;br /&gt;Another issue for "large" objects is that we need to know how to reclaim the entire "subtree" of subcomponents when we release the enclosing object.&amp;nbsp; In some cases we will know the type at compile-time, but in the case of polymorphic objects, or in cases where the type of the object is a formal type parameter of the enclosing module, we won't necessarily know.&amp;nbsp; This implies that we may want to have some kind of "type-id" associated with large objects.&amp;nbsp; This then results in the following representation for large objects:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; A 64-bit pointer to:&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [Region, Type-Id, component1, component2, component3, ...]&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;where the Type-Id provides enough information to know which of the components are themselves "large" and hence need to be recursively released.&amp;nbsp; In addition, there would probably be a special &lt;b&gt;null&lt;/b&gt; Type-Id, which would allow the "&lt;b&gt;is null&lt;/b&gt;" operation to be implemented relatively efficiently by comparing the Type-Id against some kind of standard "Null-Type-Id" value.&amp;nbsp; Each region would only need a single &lt;b&gt;null&lt;/b&gt; value, which pointed back to the region, and had the Null-Type-Id.&amp;nbsp; Such &lt;b&gt;null&lt;/b&gt; objects would &lt;i&gt;not&lt;/i&gt; be reclaimed if they were the "old" value of the left-hand side of an assignment, since there is only one such value per region, and it is shared among all objects in that region currently having a &lt;b&gt;null&lt;/b&gt; value.&lt;br /&gt;&lt;br /&gt;So to summarize, we now see that &lt;b&gt;null&lt;/b&gt; is not a single value, but rather each simple type potentially has its own representation for &lt;b&gt;null&lt;/b&gt;, and for "large" types that use a level of indirection, there is a separate &lt;b&gt;null&lt;/b&gt; value for each region.&amp;nbsp; So the "&lt;b&gt;is null&lt;/b&gt;" operation is not necessarily a simple check for equality with the global &lt;b&gt;null&lt;/b&gt; value, but instead would depend on the type, and in particular for "large" objects, would be a check of the Type-Id field of the object to see if it has the Null-Type-Id.&lt;br /&gt;&lt;br /&gt;On a final note, when a function returns "large" values, it needs to be "told" in which region to allocate the value(s) being returned.&amp;nbsp; One simple way to do this is for the "large" output parameter(s) to be initialized with a (large) &lt;b&gt;null&lt;/b&gt; value by the caller.&amp;nbsp; Since such a &lt;b&gt;null&lt;/b&gt; value identifies the region, the function can use that information when allocating the space for the returned value.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8383004232931899216-1741326844278907047?l=parasail-programming-language.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://parasail-programming-language.blogspot.com/feeds/1741326844278907047/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://parasail-programming-language.blogspot.com/2011/05/when-null-isnt-just-null-value.html#comment-form' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8383004232931899216/posts/default/1741326844278907047'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8383004232931899216/posts/default/1741326844278907047'/><link rel='alternate' type='text/html' href='http://parasail-programming-language.blogspot.com/2011/05/when-null-isnt-just-null-value.html' title='When null isn&apos;t just null -- value representation in ParaSail'/><author><name>Tuck</name><uri>http://www.blogger.com/profile/08866496974237052847</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8383004232931899216.post-6415993910551906600</id><published>2011-05-09T10:53:00.000-04:00</published><updated>2011-05-09T10:53:43.087-04:00</updated><title type='text'>Updated YACC grammar for ParaSail</title><content type='html'>Here is a more up-to-date YACC grammar from &lt;b&gt;ParaSail&lt;/b&gt;.&amp;nbsp; It uses "--" for comments, but otherwise is pretty vanilla "yacc" syntax.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;--------------------------------------&lt;br /&gt;-- YACC Grammar for ParaSail&lt;br /&gt;--------------------------------------&lt;br /&gt;&lt;br /&gt;-- Single-character delimiters --&lt;br /&gt;%token ',' ';' ':' '.'&lt;br /&gt;%token '+' '-' '*' '/' &lt;br /&gt;%token '?'&lt;br /&gt;%token '(' ')' '[' ']' '&amp;lt;' '&amp;gt;' ''&lt;br /&gt;%token '|' &lt;br /&gt;%token '='&amp;nbsp;&amp;nbsp;&amp;nbsp; -- for error recovery only&lt;br /&gt;%token PRIME -- '''&lt;br /&gt;&lt;br /&gt;-- Compound delimiters --&lt;br /&gt;%token COMPARE -- "=?"&lt;br /&gt;%token EQ&amp;nbsp;&amp;nbsp; -- "=="&lt;br /&gt;%token NEQ&amp;nbsp; -- "!="&lt;br /&gt;%token GEQ&amp;nbsp; -- "&amp;gt;="&lt;br /&gt;%token LEQ&amp;nbsp; -- "&amp;lt;="&lt;br /&gt;%token POWER&amp;nbsp; -- "**"&lt;br /&gt;%token ASSIGN -- ":="&lt;br /&gt;%token SWAP&amp;nbsp;&amp;nbsp; -- ":=:"&lt;br /&gt;%token DOT_DOT -- ".."&lt;br /&gt;%token OPEN_CLOSED_INTERVAL -- "&amp;lt;.."&lt;br /&gt;%token OPEN_INTERVAL -- "&amp;lt;..&amp;lt;"&lt;br /&gt;%token CLOSED_OPEN_INTERVAL -- "..&amp;lt;"&lt;br /&gt;%token DOUBLE_COLON&amp;nbsp; -- "::"&lt;br /&gt;%token REFERS_TO&amp;nbsp; -- "=&amp;gt;"&lt;br /&gt;%token GIVES&amp;nbsp;&amp;nbsp;&amp;nbsp; -- "-&amp;gt;"&lt;br /&gt;%token IMPLIES&amp;nbsp;&amp;nbsp;&amp;nbsp; -- "==&amp;gt;"&lt;br /&gt;%token SEQUENCE&amp;nbsp;&amp;nbsp; -- ";;"&lt;br /&gt;%token PARALLEL&amp;nbsp;&amp;nbsp; -- "||"&lt;br /&gt;%token PLUS_ASSIGN -- "+="&lt;br /&gt;%token MINUS_ASSIGN -- "-="&lt;br /&gt;%token TIMES_ASSIGN -- "*="&lt;br /&gt;%token DIVIDE_ASSIGN -- "/="&lt;br /&gt;%token POWER_ASSIGN -- "**="&lt;br /&gt;%token CONCAT_ASSIGN -- "|="&lt;br /&gt;%token AND_ASSIGN -- "and="&lt;br /&gt;%token OR_ASSIGN -- "or="&lt;br /&gt;%token XOR_ASSIGN -- "xor="&lt;br /&gt;&lt;br /&gt;-- Literals --&lt;br /&gt;%token Char_Literal&lt;br /&gt;%token Enum_Literal&lt;br /&gt;%token Integer_Literal &lt;br /&gt;%token Real_Literal&lt;br /&gt;%token String_Literal&lt;br /&gt;&lt;br /&gt;-- Identifier --&lt;br /&gt;%token Identifier &lt;br /&gt;&lt;br /&gt;-- Reserved words --&lt;br /&gt;%token ABS_kw&lt;br /&gt;%token ABSTRACT_kw&lt;br /&gt;%token ALL_kw&lt;br /&gt;%token AND_kw&lt;br /&gt;%token BEGIN_kw&amp;nbsp;&amp;nbsp; -- used for error recovery only&lt;br /&gt;%token BLOCK_kw&lt;br /&gt;%token CASE_kw&lt;br /&gt;%token CLASS_kw&lt;br /&gt;%token CONCURRENT_kw&lt;br /&gt;%token CONST_kw&lt;br /&gt;%token CONTINUE_kw&lt;br /&gt;%token EACH_kw&lt;br /&gt;%token ELSE_kw&lt;br /&gt;%token ELSIF_kw&lt;br /&gt;%token END_kw&lt;br /&gt;%token EXIT_kw&lt;br /&gt;%token EXPORTS_kw&lt;br /&gt;%token EXTENDS_kw&lt;br /&gt;%token FOR_kw&lt;br /&gt;%token FORWARD_kw&lt;br /&gt;%token FUNCTION_kw&lt;br /&gt;%token GLOBAL_kw&lt;br /&gt;%token IF_kw&lt;br /&gt;%token IMPLEMENTS_kw&lt;br /&gt;%token IMPORT_kw&lt;br /&gt;%token IN_kw&lt;br /&gt;%token INTERFACE_kw&lt;br /&gt;%token IS_kw&lt;br /&gt;%token LAMBDA_kw&lt;br /&gt;%token LOCKED_kw&lt;br /&gt;%token LOOP_kw&lt;br /&gt;%token MOD_kw&lt;br /&gt;%token MUTABLE_kw&lt;br /&gt;%token NEW_kw&lt;br /&gt;%token NOT_kw&lt;br /&gt;%token NULL_kw&lt;br /&gt;%token OF_kw&lt;br /&gt;%token OPERATOR_kw&lt;br /&gt;%token OPTIONAL_kw&lt;br /&gt;%token OR_kw&lt;br /&gt;%token PRIVATE_kw&lt;br /&gt;%token PROCEDURE_kw&lt;br /&gt;%token QUEUED_kw&lt;br /&gt;%token REF_kw&lt;br /&gt;%token REM_kw&lt;br /&gt;%token RETURN_kw&lt;br /&gt;%token REVERSE_kw&lt;br /&gt;%token SELECT_kw&lt;br /&gt;%token SOME_kw&lt;br /&gt;%token THEN_kw&lt;br /&gt;%token TYPE_kw&lt;br /&gt;%token UNTIL_kw&lt;br /&gt;%token VAR_kw&lt;br /&gt;%token WHILE_kw&lt;br /&gt;%token WITH_kw&lt;br /&gt;%token XOR_kw&lt;br /&gt;&lt;br /&gt;%start module_list&lt;br /&gt;&lt;br /&gt;%%&lt;br /&gt;&lt;br /&gt;module_list : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; module&lt;br /&gt;&amp;nbsp; | module_list module&lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;module : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; import_clauses interface_declaration ';' &lt;br /&gt;&amp;nbsp; | import_clauses class_definition ';' &lt;br /&gt;&amp;nbsp; | import_clauses standalone_operation_definition ';'&lt;br /&gt;&amp;nbsp; | import_clauses error ';'&lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;import_clauses : &lt;br /&gt;&amp;nbsp; | import_clauses IMPORT_kw qualified_name_list ';' &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;qualified_name_list : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; qualified_name &lt;br /&gt;&amp;nbsp; | qualified_name_list ',' qualified_name &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;interface_declaration : &lt;br /&gt;&amp;nbsp;&amp;nbsp; opt_interface_qualifier INTERFACE_kw module_defining_name &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; formals_and_implemented_interfaces&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; IS_kw&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; interface_element_list&lt;br /&gt;&amp;nbsp;&amp;nbsp; END_kw opt_INTERFACE_kw module_defining_name &lt;br /&gt;&amp;nbsp;&amp;nbsp; ; &lt;br /&gt;&lt;br /&gt;opt_INTERFACE_kw : INTERFACE_kw&lt;br /&gt;&amp;nbsp; | &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &lt;br /&gt;opt_interface_qualifier : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; interface_qualifier &lt;br /&gt;&amp;nbsp; | &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;interface_qualifier : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; class_qualifier &lt;br /&gt;&amp;nbsp; | ABSTRACT_kw opt_class_qualifier &lt;br /&gt;&amp;nbsp; | PRIVATE_kw opt_class_qualifier &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;opt_class_qualifier : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; class_qualifier &lt;br /&gt;&amp;nbsp; | &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;class_qualifier : CONCURRENT_kw ;&lt;br /&gt;&lt;br /&gt;standalone_operation_definition : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; function_definition &lt;br /&gt;&amp;nbsp; | procedure_definition &lt;br /&gt;&amp;nbsp; | operator_definition &lt;br /&gt;&amp;nbsp; | operation_import &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;formals : '&amp;lt;' opt_module_formal_list '&amp;gt;' ;&lt;br /&gt;&lt;br /&gt;formals_and_implemented_interfaces :&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; opt_formals opt_implements_list &lt;br /&gt;&amp;nbsp; | opt_formals EXTENDS_kw interface_name opt_implements_list &lt;br /&gt;&amp;nbsp; ; &lt;br /&gt;&lt;br /&gt;opt_formals : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; formals&amp;nbsp; &lt;br /&gt;&amp;nbsp; | &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;opt_implements_list : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; implements_list &lt;br /&gt;&amp;nbsp; | &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;implements_list : IMPLEMENTS_kw interface_name_list&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;interface_name_list :&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; interface_name &lt;br /&gt;&amp;nbsp; | interface_name_list ',' interface_name &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;interface_name : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; module_name &lt;br /&gt;&amp;nbsp; | module_instantiation &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &lt;br /&gt;module_name : qualified_name ;&lt;br /&gt;&lt;br /&gt;module_defining_name : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; qualified_name &lt;br /&gt;&amp;nbsp; | qualified_name add_on_label &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;add_on_label : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; '[' operation_actual_list ']' ;&lt;br /&gt;&lt;br /&gt;opt_module_formal_list : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; module_formal_list &lt;br /&gt;&amp;nbsp; | ;&lt;br /&gt;&lt;br /&gt;module_formal_list : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; annotated_module_formal &lt;br /&gt;&amp;nbsp; | module_formal_list ';' annotated_module_formal &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;annotated_module_formal : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; opt_annotation type_formal opt_annotation &lt;br /&gt;&amp;nbsp; | opt_annotation operation_formal &lt;br /&gt;&amp;nbsp; | opt_annotation value_formal opt_annotation &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;opt_annotation : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; annotation &lt;br /&gt;&amp;nbsp; | &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;type_formal : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; id IS_kw module_instantiation &lt;br /&gt;&amp;nbsp; | module_instantiation &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;operation_formal : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; operation_declaration opt_operation_default&amp;nbsp; &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;opt_operation_default : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; IS_kw simple_expression &lt;br /&gt;&amp;nbsp; | &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;value_formal : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; id_list ':' opt_output_modifier operand_type_specifier &lt;br /&gt;&amp;nbsp; | id_list ':' opt_output_modifier operand_type_specifier &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ASSIGN_or_equal simple_expression&amp;nbsp; &lt;br /&gt;&amp;nbsp; | ref_or_global_modifier operand_type_specifier &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;id : Identifier &lt;br /&gt;&amp;nbsp;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;id_list : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; id &lt;br /&gt;&amp;nbsp; | id_list ',' id &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;type_name : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; qualified_name &lt;br /&gt;&amp;nbsp; | polymorphic_type_name &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;polymorphic_type_name : qualified_name '+' ;&lt;br /&gt;&lt;br /&gt;qualified_name : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; id_or_string_literal &lt;br /&gt;&amp;nbsp; | qualified_name DOUBLE_COLON id_or_string_literal ;&lt;br /&gt;&lt;br /&gt;id_or_string_literal :&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; id &lt;br /&gt;&amp;nbsp; | String_Literal &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&amp;nbsp; &lt;br /&gt;module_instantiation : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; module_name '&amp;lt;' opt_module_actual_list '&amp;gt;' &lt;br /&gt;&amp;nbsp; | name '[' opt_operation_actual_list ']' '&amp;lt;' opt_module_actual_list '&amp;gt;' &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;opt_add_on_label :&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; add_on_label &lt;br /&gt;&amp;nbsp; | &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;opt_module_actual_list : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; module_actual_list &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; | &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;module_actual_list :&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; module_actual &lt;br /&gt;&amp;nbsp; | module_actual_list ',' module_actual &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;module_actual : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; simple_type_specifier_or_expression &lt;br /&gt;&amp;nbsp; | id REFERS_TO simple_type_specifier_or_expression &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;-- simple_expression subsumes simple type_name in this rule&lt;br /&gt;simple_type_specifier_or_expression : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; qualified_name annotation &lt;br /&gt;&amp;nbsp; | qualified_type_specifier opt_annotation &lt;br /&gt;&amp;nbsp; | simple_expression&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; -- simple_expr to avoid problems with '&amp;gt;'&lt;br /&gt;&amp;nbsp; | lambda_expression &lt;br /&gt;&amp;nbsp; | module_instantiation &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&amp;nbsp; &lt;br /&gt;annotated_type_specifier : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; type_specifier &lt;br /&gt;&amp;nbsp; | type_specifier annotation &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;type_specifier :&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; basic_type_specifier &lt;br /&gt;&amp;nbsp; | qualified_type_specifier &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;basic_type_specifier : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; type_name &lt;br /&gt;&amp;nbsp; | module_instantiation &lt;br /&gt;&amp;nbsp; | module_instantiation EXTENDS_kw type_specifier &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;qualified_type_specifier : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; type_qualifier type_name &lt;br /&gt;&amp;nbsp; | type_qualifier module_instantiation &lt;br /&gt;&amp;nbsp; | type_qualifier module_instantiation &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; EXTENDS_kw type_specifier &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;type_qualifier :&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; OPTIONAL_kw opt_MUTABLE_kw opt_CONCURRENT_kw &lt;br /&gt;&amp;nbsp; | MUTABLE_kw opt_CONCURRENT_kw &lt;br /&gt;&amp;nbsp; | CONCURRENT_kw &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;opt_CONCURRENT_kw : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; CONCURRENT_kw &lt;br /&gt;&amp;nbsp; | &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;interface_element_list : &lt;br /&gt;&amp;nbsp; | interface_element_list interface_element ';' &lt;br /&gt;&amp;nbsp; | interface_element_list operation_import ';' &lt;br /&gt;&amp;nbsp; | interface_element_list error ';' &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;interface_element : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; operation_declaration &lt;br /&gt;&amp;nbsp; | object_declaration &lt;br /&gt;&amp;nbsp; | interface_declaration &lt;br /&gt;&amp;nbsp; | type_declaration &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;operation_import :&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; function_declaration IS_kw import_operation &lt;br /&gt;&amp;nbsp; | procedure_declaration IS_kw import_operation &lt;br /&gt;&amp;nbsp; | operator_declaration IS_kw import_operation &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;class_definition :&lt;br /&gt;&amp;nbsp;&amp;nbsp; opt_class_qualifier CLASS_kw module_defining_name &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; class_formals_and_implemented_interfaces&lt;br /&gt;&amp;nbsp;&amp;nbsp; IS_kw&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; class_element_list&lt;br /&gt;&amp;nbsp;&amp;nbsp; END_kw opt_CLASS_kw module_defining_name ; &lt;br /&gt;&lt;br /&gt;opt_CLASS_kw : CLASS_kw&lt;br /&gt;&amp;nbsp; | &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &lt;br /&gt;class_formals_and_implemented_interfaces :&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; formals_and_implemented_interfaces &lt;br /&gt;&amp;nbsp; | opt_formals EXTENDS_kw id ':' interface_name opt_implements_list &lt;br /&gt;&amp;nbsp; ; &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;class_element_list : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; local_class_element_list&lt;br /&gt;&amp;nbsp; EXPORTS_kw &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; exported_class_element_list &lt;br /&gt;&amp;nbsp; | local_class_element_list&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; annotation&lt;br /&gt;&amp;nbsp; EXPORTS_kw &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; exported_class_element_list &lt;br /&gt;&amp;nbsp; | local_class_element_list &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;local_class_element_list : &lt;br /&gt;&amp;nbsp; | local_class_element_list local_class_element ';' &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;local_class_element : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; interface_element&amp;nbsp; &lt;br /&gt;&amp;nbsp; | operation_import &lt;br /&gt;&amp;nbsp; | annotated_exported_class_element &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&amp;nbsp; &lt;br /&gt;exported_class_element_list : &lt;br /&gt;&amp;nbsp; | exported_class_element_list annotated_exported_class_element ';' &lt;br /&gt;&amp;nbsp; | exported_class_element_list operation_import ';' &lt;br /&gt;&amp;nbsp; | exported_class_element_list interface_element ';' &lt;br /&gt;&amp;nbsp; | exported_class_element_list error ';' &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;annotated_exported_class_element : &lt;br /&gt;&amp;nbsp; | exported_class_element &lt;br /&gt;&amp;nbsp; | annotation &lt;br /&gt;&amp;nbsp; | annotation exported_class_element &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;exported_class_element : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; operation_definition&amp;nbsp; &lt;br /&gt;&amp;nbsp; | object_definition&amp;nbsp; &lt;br /&gt;&amp;nbsp; | class_definition&amp;nbsp; &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp; &lt;br /&gt;annotation : '' &lt;br /&gt;&amp;nbsp; | annotation '' &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;annotation_element_list : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; annotation_element &lt;br /&gt;&amp;nbsp; | annotation_element_list ';' annotation_element &lt;br /&gt;&amp;nbsp; | annotation_element_list ';' error &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;annotation_element : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; interface_element &lt;br /&gt;&amp;nbsp; | operation_import &lt;br /&gt;&amp;nbsp; | condition &lt;br /&gt;&amp;nbsp; | quantified_expression &lt;br /&gt;&amp;nbsp; | annotation &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;condition : expression&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;operation_declaration : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; function_declaration &lt;br /&gt;&amp;nbsp; | procedure_declaration &lt;br /&gt;&amp;nbsp; | operator_declaration &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;function_declaration :&lt;br /&gt;&amp;nbsp; opt_ABSTRACT_or_OPTIONAL_kw FUNCTION_kw id_or_string_literal&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; operation_inputs opt_annotation &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; GIVES_or_RETURN_kw operation_outputs opt_annotation ;&lt;br /&gt;&lt;br /&gt;GIVES_or_RETURN_kw : GIVES&lt;br /&gt;&amp;nbsp; | RETURN_kw &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;procedure_declaration :&lt;br /&gt;&amp;nbsp; opt_ABSTRACT_or_OPTIONAL_kw PROCEDURE_kw id &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; operation_inputs opt_annotation ;&lt;br /&gt;&lt;br /&gt;operator_declaration :&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; opt_ABSTRACT_or_OPTIONAL_kw OPERATOR_kw operator_designator &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; operation_inputs opt_annotation &lt;br /&gt;&amp;nbsp; | opt_ABSTRACT_or_OPTIONAL_kw OPERATOR_kw operator_designator &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; operation_inputs opt_annotation &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; GIVES_or_RETURN_kw operation_outputs opt_annotation &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;opt_ABSTRACT_or_OPTIONAL_kw :&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ABSTRACT_kw &lt;br /&gt;&amp;nbsp; | OPTIONAL_kw &lt;br /&gt;&amp;nbsp; | &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;operator_designator : String_Literal ;&lt;br /&gt;&amp;nbsp; &lt;br /&gt;operation_inputs :&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; simple_operation_input &lt;br /&gt;&amp;nbsp; | '(' opt_annotated_operation_input_list ')' &lt;br /&gt;&amp;nbsp; | '(' id_list ',' id ')' &lt;br /&gt;&amp;nbsp; | &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;simple_operation_input :&amp;nbsp;&amp;nbsp; -- avoids trailing use of "IS"&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; id ':' opt_input_modifier simple_operand_type_specifier &lt;br /&gt;&amp;nbsp; | input_modifier simple_operand_type_specifier &lt;br /&gt;&amp;nbsp; | simple_operand_type_specifier &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;opt_annotated_operation_input_list : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; annotated_operation_input_list &lt;br /&gt;&amp;nbsp; | &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;annotated_operation_input_list : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; annotated_operation_input &lt;br /&gt;&amp;nbsp; | annotated_operation_input_list ';' annotated_operation_input &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;annotated_operation_input : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; operation_input opt_annotation &lt;br /&gt;&amp;nbsp; | annotation operation_input opt_annotation &lt;br /&gt;&amp;nbsp; | function_declaration opt_operation_default &lt;br /&gt;&amp;nbsp; | annotation function_declaration opt_operation_default &lt;br /&gt;&amp;nbsp; | procedure_declaration opt_operation_default &lt;br /&gt;&amp;nbsp; | annotation procedure_declaration opt_operation_default &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;operation_input : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; id_list ':' opt_input_modifier operand_type_specifier opt_ASSIGN_expression&lt;br /&gt;&amp;nbsp; | input_modifier operand_type_specifier opt_ASSIGN_expression &lt;br /&gt;&amp;nbsp; | operand_type_specifier opt_ASSIGN_expression &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;opt_input_modifier : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; input_modifier &lt;br /&gt;&amp;nbsp; | &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&amp;nbsp; &lt;br /&gt;simple_operand_type_specifier :&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; type_name &lt;br /&gt;&amp;nbsp; | module_instantiation &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;operand_type_specifier : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; simple_operand_type_specifier &lt;br /&gt;&amp;nbsp; | id IS_kw module_instantiation &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;input_modifier : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; output_modifier &lt;br /&gt;&amp;nbsp; | QUEUED_kw mutable_or_var_or_const &lt;br /&gt;&amp;nbsp; | LOCKED_kw mutable_or_var_or_const &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;mutable_or_var_or_const :&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; MUTABLE_kw opt_VAR_kw &lt;br /&gt;&amp;nbsp; | VAR_kw &lt;br /&gt;&amp;nbsp; | CONST_kw &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;opt_VAR_kw : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; VAR_kw &lt;br /&gt;&amp;nbsp; | &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;operation_outputs : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; simple_operation_output &lt;br /&gt;&amp;nbsp; | annotation simple_operation_output &lt;br /&gt;&amp;nbsp; | '(' annotated_operation_output_list ')' &lt;br /&gt;&amp;nbsp; | '(' id_list ',' id ')' &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;simple_operation_output :&amp;nbsp;&amp;nbsp; -- avoids trailing use of "IS"&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; id ':' opt_output_modifier simple_operand_type_specifier &lt;br /&gt;&amp;nbsp; | output_modifier simple_operand_type_specifier &lt;br /&gt;&amp;nbsp; | simple_operand_type_specifier &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;annotated_operation_output_list :&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; annotated_operation_output &lt;br /&gt;&amp;nbsp; | annotated_operation_output_list ';' annotated_operation_output &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;annotated_operation_output : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; operation_output opt_annotation &lt;br /&gt;&amp;nbsp; | annotation operation_output opt_annotation&amp;nbsp; &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;operation_output : &lt;br /&gt;&amp;nbsp; id_list ':' opt_output_modifier operand_type_specifier &lt;br /&gt;&amp;nbsp; | output_modifier operand_type_specifier&amp;nbsp; &lt;br /&gt;&amp;nbsp; | operand_type_specifier&amp;nbsp; &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;opt_output_modifier :&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; output_modifier &lt;br /&gt;&amp;nbsp; | &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;output_modifier :&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; OPTIONAL_kw &lt;br /&gt;&amp;nbsp; | ref_or_global_modifier &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;ref_or_global_modifier :&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; REF_or_GLOBAL_opt_optional_mutable &lt;br /&gt;&amp;nbsp; | REF_or_GLOBAL_opt_optional_mutable VAR_kw &lt;br /&gt;&amp;nbsp; | REF_or_GLOBAL_opt_optional_mutable CONST_kw &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;REF_or_GLOBAL_opt_optional_mutable :&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; REF_or_GLOBAL_kw &lt;br /&gt;&amp;nbsp; | REF_or_GLOBAL_kw OPTIONAL_kw &lt;br /&gt;&amp;nbsp; | REF_or_GLOBAL_kw MUTABLE_kw &lt;br /&gt;&amp;nbsp; | REF_or_GLOBAL_kw OPTIONAL_kw MUTABLE_kw &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;REF_or_GLOBAL_kw : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; REF_kw &lt;br /&gt;&amp;nbsp; | GLOBAL_kw &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;object_declaration : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; VAR_kw id ':' &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; annotated_type_specifier &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; opt_ASSIGN_expression &lt;br /&gt;&amp;nbsp; | CONST_kw id ':' annotated_type_specifier &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; opt_ASSIGN_expression &lt;br /&gt;&amp;nbsp; | id ':' annotated_type_specifier &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; opt_ASSIGN_expression &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;opt_ASSIGN_expression : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ASSIGN_or_equal expression &lt;br /&gt;&amp;nbsp; | &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &lt;br /&gt;object_definition :&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; CONST_kw id ASSIGN_or_equal expression &lt;br /&gt;&amp;nbsp; | VAR_kw id ASSIGN_or_equal expression &lt;br /&gt;&amp;nbsp; | CONST_kw id REFERS_TO name &lt;br /&gt;&amp;nbsp; | VAR_kw id REFERS_TO name &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;opt_OPTIONAL_kw : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; OPTIONAL_kw &lt;br /&gt;&amp;nbsp; | &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;opt_MUTABLE_kw : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; MUTABLE_kw &lt;br /&gt;&amp;nbsp; | &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;type_declaration : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; TYPE_kw id IS_kw opt_NEW_kw annotated_type_specifier ;&lt;br /&gt;&lt;br /&gt;opt_NEW_kw : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; NEW_kw &lt;br /&gt;&amp;nbsp; | &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;operation_definition : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; function_definition &lt;br /&gt;&amp;nbsp; | procedure_definition &lt;br /&gt;&amp;nbsp; | operator_definition &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;function_definition : &lt;br /&gt;&amp;nbsp; function_declaration IS_kw opt_queued_clause &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; statement_list_with_semi &lt;br /&gt;&amp;nbsp; END_kw opt_FUNCTION_kw id &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;opt_FUNCTION_kw : FUNCTION_kw&lt;br /&gt;&amp;nbsp; | &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;procedure_definition : &lt;br /&gt;&amp;nbsp; procedure_declaration IS_kw opt_queued_clause &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; statement_list_with_semi &lt;br /&gt;&amp;nbsp; END_kw opt_PROCEDURE_kw id &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;opt_PROCEDURE_kw : PROCEDURE_kw&lt;br /&gt;&amp;nbsp; | &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;operator_definition : &lt;br /&gt;&amp;nbsp; operator_declaration IS_kw &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; statement_list_with_semi &lt;br /&gt;&amp;nbsp; END_kw opt_OPERATOR_kw operator_designator&amp;nbsp; &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;opt_OPERATOR_kw : OPERATOR_kw&lt;br /&gt;&amp;nbsp; | &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;opt_queued_clause : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; queued_clause &lt;br /&gt;&amp;nbsp; | &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;queued_clause :&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; QUEUED_kw WHILE_or_UNTIL_kw condition THEN_kw ;&lt;br /&gt;&lt;br /&gt;import_operation :&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; IMPORT_kw '(' opt_operation_actual_list ')' ;&lt;br /&gt;&lt;br /&gt;statement_list_with_semi : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; parallel_sequence_with_semi &lt;br /&gt;&amp;nbsp; | statement_list_no_semi THEN_kw parallel_sequence_with_semi &lt;br /&gt;&amp;nbsp; | statement_list_with_semi THEN_kw parallel_sequence_with_semi &lt;br /&gt;&amp;nbsp; | statement_list_with_semi use_BEGIN_kw parallel_sequence_with_semi &lt;br /&gt;&amp;nbsp; | use_BEGIN_kw parallel_sequence_with_semi &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;use_BEGIN_kw : BEGIN_kw ;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;statement_list_no_semi : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; parallel_sequence_no_semi &lt;br /&gt;&amp;nbsp; | statement_list_no_semi THEN_kw parallel_sequence_no_semi &lt;br /&gt;&amp;nbsp; | statement_list_with_semi THEN_kw parallel_sequence_no_semi &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;parallel_sequence_with_semi : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; statement_sequence_with_semi &lt;br /&gt;&amp;nbsp; | parallel_sequence_no_semi PARALLEL statement_sequence_with_semi &lt;br /&gt;&amp;nbsp; | parallel_sequence_with_semi PARALLEL statement_sequence_with_semi &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;parallel_sequence_no_semi :&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; statement_sequence &lt;br /&gt;&amp;nbsp; | parallel_sequence_no_semi PARALLEL statement_sequence &lt;br /&gt;&amp;nbsp; | parallel_sequence_with_semi PARALLEL statement_sequence &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;statement_sequence_opt_semi :&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; statement_sequence_with_semi &lt;br /&gt;&amp;nbsp; | statement_sequence &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;statement_sequence_with_semi : statement_sequence ';' ;&lt;br /&gt;&lt;br /&gt;statement_sequence :&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; annotated_statement &lt;br /&gt;&amp;nbsp; | statement_sequence SEQUENCE annotated_statement &lt;br /&gt;&amp;nbsp; | statement_sequence ';' SEQUENCE annotated_statement &lt;br /&gt;&amp;nbsp; | statement_sequence ';' annotated_statement &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&amp;nbsp; &lt;br /&gt;annotated_statement : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; opt_annotation local_declaration &lt;br /&gt;&amp;nbsp; | opt_annotation statement opt_annotation &lt;br /&gt;&amp;nbsp; | annotation &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;statement : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; local_definition &lt;br /&gt;&amp;nbsp; | simple_statement &lt;br /&gt;&amp;nbsp; | label compound_statement &lt;br /&gt;&amp;nbsp; | compound_statement &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;simple_statement :&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; primitive_statement &lt;br /&gt;&amp;nbsp; | name equal_as_assign expression &lt;br /&gt;&amp;nbsp; | NULL_kw &lt;br /&gt;&amp;nbsp; | name '(' opt_operation_actual_list ')' &lt;br /&gt;&amp;nbsp; | RETURN_kw expression &lt;br /&gt;&amp;nbsp; | RETURN_kw opt_WITH_values&amp;nbsp; &lt;br /&gt;&amp;nbsp; | CONTINUE_kw LOOP_kw opt_id opt_WITH_values&amp;nbsp; &lt;br /&gt;&amp;nbsp; | EXIT_kw compound_statement_kind opt_id opt_WITH_values &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;primitive_statement :&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; name assign_operator_not_divide expression &lt;br /&gt;&amp;nbsp; | name DIVIDE_ASSIGN expression &lt;br /&gt;&amp;nbsp; | name SWAP name &lt;br /&gt;&amp;nbsp; | '(' opt_operation_actual_list ')' ASSIGN expression &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;opt_operation_actual_list : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; operation_actual_list &lt;br /&gt;&amp;nbsp; | &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;opt_WITH_values : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; WITH_values &lt;br /&gt;&amp;nbsp; | &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;WITH_values : WITH_kw operation_actual ;&lt;br /&gt;&lt;br /&gt;opt_id : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; id &lt;br /&gt;&amp;nbsp; | &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;compound_statement_kind : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; LOOP_kw &lt;br /&gt;&amp;nbsp; | IF_kw &lt;br /&gt;&amp;nbsp; | CASE_kw &lt;br /&gt;&amp;nbsp; | SELECT_kw &lt;br /&gt;&amp;nbsp; | BLOCK_kw &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;local_declaration : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; operation_declaration &lt;br /&gt;&amp;nbsp; | type_declaration &lt;br /&gt;&amp;nbsp; | object_declaration&lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;local_definition :&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; object_definition &lt;br /&gt;&amp;nbsp; | operation_definition &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;label : '*' id '*' ;&lt;br /&gt;&lt;br /&gt;compound_statement :&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if_statement &lt;br /&gt;&amp;nbsp; | case_statement &lt;br /&gt;&amp;nbsp; | indefinite_loop_statement &lt;br /&gt;&amp;nbsp; | while_until_loop_statement &lt;br /&gt;&amp;nbsp; | for_loop_statement &lt;br /&gt;&amp;nbsp; | block_statement&amp;nbsp; &lt;br /&gt;&amp;nbsp; | select_statement &lt;br /&gt;&amp;nbsp; | error ';' &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;if_statement : &lt;br /&gt;&amp;nbsp; IF_kw condition THEN_kw &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; statement_list_with_semi&lt;br /&gt;&amp;nbsp; opt_else_part&lt;br /&gt;&amp;nbsp; END_kw IF_kw opt_id opt_WITH_values ;&lt;br /&gt;&lt;br /&gt;opt_else_part : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ELSIF_kw condition THEN_kw&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; statement_list_with_semi &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; opt_else_part &lt;br /&gt;&amp;nbsp; | ELSE_kw statement_list_with_semi &lt;br /&gt;&amp;nbsp; | &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;case_statement : &lt;br /&gt;&amp;nbsp; CASE_kw expression OF_kw&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; case_alt_list&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; opt_default_alt&lt;br /&gt;&amp;nbsp; END_kw CASE_kw opt_id opt_WITH_values ;&lt;br /&gt;&lt;br /&gt;case_alt_list : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; case_alt &lt;br /&gt;&amp;nbsp; | case_alt_list case_alt &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;case_alt :&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; '[' simple_expression_opt_named ']' REFERS_TO statement_list_with_semi &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;simple_expression_opt_named :&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; simple_expression &lt;br /&gt;&amp;nbsp; | id ':' simple_expression &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&amp;nbsp; &lt;br /&gt;opt_default_alt : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; '[' dot_dot_opt_named ']' REFERS_TO statement_list_with_semi &lt;br /&gt;&amp;nbsp; | &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;dot_dot_opt_named :&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; dot_dot_as_interval &lt;br /&gt;&amp;nbsp; | id ':' dot_dot_as_interval &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br /&gt;dot_dot_as_interval : DOT_DOT ;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;indefinite_loop_statement :&lt;br /&gt;&amp;nbsp; LOOP_kw &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; statement_list_with_semi&lt;br /&gt;&amp;nbsp; END_kw LOOP_kw opt_id opt_WITH_values ;&lt;br /&gt;&lt;br /&gt;while_until_loop_statement :&lt;br /&gt;&amp;nbsp; WHILE_or_UNTIL_kw condition LOOP_kw&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; statement_list_with_semi&lt;br /&gt;&amp;nbsp; END_kw LOOP_kw opt_id opt_WITH_values ;&lt;br /&gt;&lt;br /&gt;WHILE_or_UNTIL_kw :&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; WHILE_kw &lt;br /&gt;&amp;nbsp; | UNTIL_kw &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;for_loop_statement :&lt;br /&gt;&amp;nbsp; FOR_kw iterator_spec opt_direction LOOP_kw&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; statement_list_with_semi&lt;br /&gt;&amp;nbsp; END_kw LOOP_kw opt_id opt_WITH_values ;&lt;br /&gt;&lt;br /&gt;iterator_spec : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; iterator &lt;br /&gt;&amp;nbsp; | '(' iterator_list ')' &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;iterator_list :&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; iterator &lt;br /&gt;&amp;nbsp; | iterator_list ';' iterator &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;iterator :&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; index_set_iterator &lt;br /&gt;&amp;nbsp; | EACH_kw element_iterator &lt;br /&gt;&amp;nbsp; | initial_next_while_iterator &lt;br /&gt;&amp;nbsp; | initial_value_iterator &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;index_set_iterator :&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; id opt_COLON_type_specifier IN_kw opt_REVERSE_kw expression ;&lt;br /&gt;&lt;br /&gt;opt_REVERSE_kw : &lt;br /&gt;&amp;nbsp; | REVERSE_kw ;&lt;br /&gt;&lt;br /&gt;element_iterator :&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; id opt_COLON_type_specifier OF_kw expression &lt;br /&gt;&amp;nbsp; | '[' id REFERS_TO id ']' OF_kw expression &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;initial_next_while_iterator :&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; id opt_COLON_type_specifier ASSIGN_or_equal expression &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; opt_THEN_next_value_list &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; WHILE_or_UNTIL_kw condition &lt;br /&gt;&amp;nbsp; | id opt_COLON_type_specifier REFERS_TO name &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; opt_THEN_next_name_list&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; WHILE_or_UNTIL_kw condition &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;opt_THEN_next_value_list :&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; THEN_kw next_value_list &lt;br /&gt;&amp;nbsp; | &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;opt_THEN_next_name_list :&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; THEN_kw next_name_list &lt;br /&gt;&amp;nbsp; | &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;initial_value_iterator :&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; id opt_COLON_type_specifier ASSIGN_or_equal expression &lt;br /&gt;&amp;nbsp; | id opt_COLON_type_specifier REFERS_TO name &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;opt_COLON_type_specifier : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ':' type_specifier &lt;br /&gt;&amp;nbsp; | &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;next_value_list : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; expression&amp;nbsp; &lt;br /&gt;&amp;nbsp; | next_value_list PARALLEL expression &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;next_name_list : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; name&amp;nbsp; &lt;br /&gt;&amp;nbsp; | next_name_list PARALLEL name &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;opt_direction : direction&amp;nbsp; &lt;br /&gt;&amp;nbsp; | &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;direction : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; CONCURRENT_kw &lt;br /&gt;&amp;nbsp; | FORWARD_kw &lt;br /&gt;&amp;nbsp; | REVERSE_kw &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;select_statement :&lt;br /&gt;&amp;nbsp; SELECT_kw &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; select_alt_list&lt;br /&gt;&amp;nbsp; END_kw SELECT_kw opt_id opt_WITH_values ;&lt;br /&gt;&lt;br /&gt;select_alt_list : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; select_alt&lt;br /&gt;&amp;nbsp; | select_alt_list PARALLEL select_alt&lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;select_alt : &lt;br /&gt;&amp;nbsp; '[' statement_sequence_opt_semi ']' REFERS_TO statement_sequence_with_semi ;&lt;br /&gt;&lt;br /&gt;block_statement :&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; BLOCK_kw&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; statement_list_with_semi&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; END_kw opt_BLOCK_kw opt_id opt_WITH_values &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;opt_BLOCK_kw : BLOCK_kw&lt;br /&gt;&amp;nbsp; | &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &lt;br /&gt;expression :&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; expression_no_err &lt;br /&gt;&amp;nbsp; | expression_no_err divide_assign_as_not_equal expression_no_err &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;divide_assign_as_not_equal :&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; DIVIDE_ASSIGN &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;expression_no_err :&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; logical_expression &lt;br /&gt;&amp;nbsp; | logical_expression '?' expression ':' expression_no_err &lt;br /&gt;&amp;nbsp; | lambda_expression &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;lambda_expression :&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; LAMBDA_kw operation_inputs opt_annotation IS_kw &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; simple_expression_or_expr_stmt_seq &lt;br /&gt;&amp;nbsp; | LAMBDA_kw operation_inputs opt_annotation&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; GIVES operation_outputs opt_annotation IS_kw &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; simple_expression_or_expr_stmt_seq &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;simple_expression_or_expr_stmt_seq :&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; simple_expression &lt;br /&gt;&amp;nbsp; | '(' expr_statement_seq ')' &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;expr_statement_seq : expr_statement ';' expr_statement &lt;br /&gt;&amp;nbsp; | expr_statement_seq ';' expr_statement &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;expr_statement : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; primitive_statement &lt;br /&gt;&amp;nbsp; | expression_no_err &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;logical_expression :&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; comparison_expression &lt;br /&gt;&amp;nbsp; | logical_expression logical_operator comparison_expression &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;comparison_expression :&amp;nbsp; -- comparisons are non associative&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; simple_expression &lt;br /&gt;&amp;nbsp; | simple_expression comparison_operator simple_expression &lt;br /&gt;&amp;nbsp; | adding_expression IN_kw simple_expression &lt;br /&gt;&amp;nbsp; | adding_expression NOT_kw IN_kw simple_expression &lt;br /&gt;&amp;nbsp; | adding_expression IS_kw NULL_kw &lt;br /&gt;&amp;nbsp; | adding_expression NOT_kw NULL_kw &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;simple_expression : -- used to avoid use of '&amp;gt;' in module instantiation&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; simple_expression_component &lt;br /&gt;&amp;nbsp; | simple_expression '|' simple_expression_component &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;simple_expression_component :&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; adding_expression &lt;br /&gt;&amp;nbsp; | adding_expression interval_operator adding_expression &lt;br /&gt;&amp;nbsp; | adding_expression interval_operator &lt;br /&gt;&amp;nbsp; | interval_operator adding_expression &lt;br /&gt;&amp;nbsp; | adding_expression '+' &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;adding_expression :&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; term &lt;br /&gt;&amp;nbsp; | adding_expression adding_operator term &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;term : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; factor &lt;br /&gt;&amp;nbsp; | term multiplying_operator factor &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;factor : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; primary &lt;br /&gt;&amp;nbsp; | primary power_operator factor &lt;br /&gt;&amp;nbsp; | unary_operator factor&amp;nbsp; &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;primary :&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; name &lt;br /&gt;&amp;nbsp; | literal &lt;br /&gt;&amp;nbsp; | '(' conditional_expression ')' &lt;br /&gt;&amp;nbsp; | '(' quantified_expression ')' &lt;br /&gt;&amp;nbsp; | aggregate &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&amp;nbsp; &lt;br /&gt;literal:&amp;nbsp; -- NOTE: See "name" for String_Literal&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Integer_Literal &lt;br /&gt;&amp;nbsp; | Real_Literal &lt;br /&gt;&amp;nbsp; | Char_Literal &lt;br /&gt;&amp;nbsp; | Enum_Literal &lt;br /&gt;&amp;nbsp; | NULL_kw &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;name :&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; qualified_name_and_property opt_PRIME &lt;br /&gt;&amp;nbsp; | qualified_name DOUBLE_COLON literal &lt;br /&gt;&amp;nbsp; | name '(' opt_operation_actual_list ')' &lt;br /&gt;&amp;nbsp; | name '[' opt_operation_actual_list ']' &lt;br /&gt;&amp;nbsp; | name '.' selector &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;qualified_name_and_property :&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; qualified_name &lt;br /&gt;&amp;nbsp; | qualified_name_and_property Enum_Literal &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;opt_PRIME : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; PRIME &lt;br /&gt;&amp;nbsp; | PRIME Identifier &lt;br /&gt;&amp;nbsp; | &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;operation_actual_list : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; operation_actual &lt;br /&gt;&amp;nbsp; | operation_actual_list ',' operation_actual &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;operation_actual : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; expression_no_err &lt;br /&gt;&amp;nbsp; | id REFERS_TO expression &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;selector : id ;&lt;br /&gt;&lt;br /&gt;unary_operator : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; '+' &lt;br /&gt;&amp;nbsp; | '-' &lt;br /&gt;&amp;nbsp; | ABS_kw &lt;br /&gt;&amp;nbsp; | NOT_kw &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;adding_operator : &lt;br /&gt;&amp;nbsp; '+' &lt;br /&gt;&amp;nbsp; | '-' &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;multiplying_operator : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; '*' &lt;br /&gt;&amp;nbsp; | '/' &lt;br /&gt;&amp;nbsp; | MOD_kw &lt;br /&gt;&amp;nbsp; | REM_kw &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;power_operator : POWER ;&lt;br /&gt;&lt;br /&gt;assign_operator : assign_operator_not_divide &lt;br /&gt;&amp;nbsp; | DIVIDE_ASSIGN &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;assign_operator_not_divide :&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ASSIGN &lt;br /&gt;&amp;nbsp; | PLUS_ASSIGN &lt;br /&gt;&amp;nbsp; | MINUS_ASSIGN &lt;br /&gt;&amp;nbsp; | TIMES_ASSIGN &lt;br /&gt;&amp;nbsp; | CONCAT_ASSIGN &lt;br /&gt;&amp;nbsp; | AND_ASSIGN &lt;br /&gt;&amp;nbsp; | OR_ASSIGN &lt;br /&gt;&amp;nbsp; | XOR_ASSIGN &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;ASSIGN_or_equal : ASSIGN &lt;br /&gt;&amp;nbsp; | equal_as_assign &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;equal_as_assign : '=' &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;comparison_operator : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; COMPARE &lt;br /&gt;&amp;nbsp; | EQ &lt;br /&gt;&amp;nbsp; | NEQ &lt;br /&gt;&amp;nbsp; | '&amp;lt;' &lt;br /&gt;&amp;nbsp; | LEQ &lt;br /&gt;&amp;nbsp; | '&amp;gt;' &lt;br /&gt;&amp;nbsp; | GEQ &lt;br /&gt;&amp;nbsp; | '&amp;lt;' '&amp;lt;' &lt;br /&gt;&amp;nbsp; | '&amp;gt;' '&amp;gt;' &lt;br /&gt;&amp;nbsp; | '=' &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;logical_operator :&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; AND_kw &lt;br /&gt;&amp;nbsp; | OR_kw &lt;br /&gt;&amp;nbsp; | XOR_kw&amp;nbsp; &lt;br /&gt;&amp;nbsp; | AND_kw THEN_kw &lt;br /&gt;&amp;nbsp; | OR_kw ELSE_kw &lt;br /&gt;&amp;nbsp; | IMPLIES &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;interval_operator :&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; DOT_DOT &lt;br /&gt;&amp;nbsp; | OPEN_INTERVAL &lt;br /&gt;&amp;nbsp; | CLOSED_OPEN_INTERVAL &lt;br /&gt;&amp;nbsp; | OPEN_CLOSED_INTERVAL &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;aggregate : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; class_aggregate&amp;nbsp; &lt;br /&gt;&amp;nbsp; | container_aggregate&amp;nbsp; &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;class_aggregate : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; '(' opt_operation_actual_list ')' &lt;br /&gt;&amp;nbsp; | '(' name DIVIDE_ASSIGN expression ')' &lt;br /&gt;&amp;nbsp; | qualified_name DOUBLE_COLON '(' opt_operation_actual_list ')' &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;container_aggregate : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; '[' opt_container_element_list ']' &lt;br /&gt;&amp;nbsp; | qualified_name DOUBLE_COLON '[' opt_container_element_list ']' &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&amp;nbsp; &lt;br /&gt;opt_container_element_list : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; container_element_list &lt;br /&gt;&amp;nbsp; | DOT_DOT &lt;br /&gt;&amp;nbsp; | &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;container_element_list : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; container_element &lt;br /&gt;&amp;nbsp; | container_element_list ',' container_element &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;container_element : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; expression &lt;br /&gt;&amp;nbsp; | simple_expression REFERS_TO filtered_expression_stream &lt;br /&gt;&amp;nbsp; | DOT_DOT REFERS_TO filtered_expression_stream &lt;br /&gt;&amp;nbsp; | FOR_kw iterator REFERS_TO filtered_expression_stream &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;filtered_expression_stream : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; expression &lt;br /&gt;&amp;nbsp; | expression ':' condition &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;conditional_expression :&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if_expression &lt;br /&gt;&amp;nbsp; | case_expression &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;if_expression : &lt;br /&gt;&amp;nbsp; IF_kw condition THEN_kw &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; expression&lt;br /&gt;&amp;nbsp; opt_else_expr ;&lt;br /&gt;&lt;br /&gt;opt_else_expr : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ELSIF_kw condition THEN_kw &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; expression &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; opt_else_expr &lt;br /&gt;&amp;nbsp; | ELSE_kw expression &lt;br /&gt;&amp;nbsp; | &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;case_expression : &lt;br /&gt;&amp;nbsp; CASE_kw expression OF_kw&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; case_expr_alt_list ;&lt;br /&gt;&lt;br /&gt;case_expr_alt_list : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; case_expr_alt &lt;br /&gt;&amp;nbsp; | case_expr_alt_list ';' case_expr_alt &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;case_expr_alt : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; '[' simple_expression_opt_named ']' REFERS_TO expression &lt;br /&gt;&amp;nbsp; | '[' dot_dot_opt_named ']' REFERS_TO expression &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;quantified_expression :&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; FOR_kw ALL_or_SOME_kw quantified_iterator REFERS_TO&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; condition_or_quantified_expression ;&lt;br /&gt;&lt;br /&gt;condition_or_quantified_expression :&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; condition &lt;br /&gt;&amp;nbsp; | if_expression &lt;br /&gt;&amp;nbsp; | quantified_expression &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;ALL_or_SOME_kw : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ALL_kw &lt;br /&gt;&amp;nbsp; | SOME_kw &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;quantified_iterator :&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; index_set_iterator &lt;br /&gt;&amp;nbsp; | element_iterator &lt;br /&gt;&amp;nbsp; | initial_next_while_iterator &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;%%&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8383004232931899216-6415993910551906600?l=parasail-programming-language.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://parasail-programming-language.blogspot.com/feeds/6415993910551906600/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://parasail-programming-language.blogspot.com/2011/05/updated-yacc-grammar-for-parasail.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8383004232931899216/posts/default/6415993910551906600'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8383004232931899216/posts/default/6415993910551906600'/><link rel='alternate' type='text/html' href='http://parasail-programming-language.blogspot.com/2011/05/updated-yacc-grammar-for-parasail.html' title='Updated YACC grammar for ParaSail'/><author><name>Tuck</name><uri>http://www.blogger.com/profile/08866496974237052847</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8383004232931899216.post-5074600431615585147</id><published>2011-05-08T23:46:00.000-04:00</published><updated>2011-05-08T23:46:54.115-04:00</updated><title type='text'>ParaSail Reference Manual -- first complete draft posted</title><content type='html'>We have posted the first complete draft of the reference manual for the &lt;b&gt;ParaSail&lt;/b&gt; programming language to the ParaSail google group:&lt;br /&gt;&lt;br /&gt;&amp;nbsp; &lt;a href="http://groups.google.com/group/parasail-programming-language"&gt;http://groups.google.com/group/parasail-programming-language&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Comments welcomed!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8383004232931899216-5074600431615585147?l=parasail-programming-language.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://parasail-programming-language.blogspot.com/feeds/5074600431615585147/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://parasail-programming-language.blogspot.com/2011/05/parasail-reference-manual-first.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8383004232931899216/posts/default/5074600431615585147'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8383004232931899216/posts/default/5074600431615585147'/><link rel='alternate' type='text/html' href='http://parasail-programming-language.blogspot.com/2011/05/parasail-reference-manual-first.html' title='ParaSail Reference Manual -- first complete draft posted'/><author><name>Tuck</name><uri>http://www.blogger.com/profile/08866496974237052847</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8383004232931899216.post-5373133023193822374</id><published>2011-04-10T16:48:00.000-04:00</published><updated>2011-04-10T16:48:51.780-04:00</updated><title type='text'>Writing preconditions and postconditions incrementally</title><content type='html'>Once you start enforcing pre- and postconditions at compile time, as in &lt;b&gt;ParaSail&lt;/b&gt;, some interesting things start to happen.&amp;nbsp; Unless programmers are very familiar with writing pre- and postconditions as a matter of course, chances are that the code will be written initially with few if any pre/postconditions.&amp;nbsp; However, presuming that the language-provided abstractions, such as Arrays, already have some preconditions (such as you cannot index into an array with an index that is out of the array bounds), the compiler pretty quickly identifies places where the programmer will &lt;i&gt;have&lt;/i&gt; to write some of their own preconditions, constraints, invariants, etc.&amp;nbsp; For example, consider the classic Stack abstraction.&amp;nbsp; This might be written in ParaSail as follows, initially without any pre/postconditions:&lt;br /&gt;&lt;pre&gt;&lt;b&gt;interface&lt;/b&gt; Stack&lt;br /&gt;  &amp;lt;Component &lt;b&gt;is&lt;/b&gt; Assignable&amp;lt;&amp;gt;; &lt;br /&gt;   Size_Type &lt;b&gt;is&lt;/b&gt; Integer&amp;lt;&amp;gt;&amp;gt; &lt;b&gt;is&lt;/b&gt;&lt;br /&gt;    &lt;b&gt;function&lt;/b&gt; Create(Max : Size_Type) -&amp;gt; Stack;&lt;br /&gt;    &lt;b&gt;function&lt;/b&gt; Top(S : &lt;b&gt;ref&lt;/b&gt; Stack) -&amp;gt; &lt;b&gt;ref&lt;/b&gt; Component;&lt;br /&gt;    &lt;b&gt;procedure&lt;/b&gt; Pop(S : &lt;b&gt;ref&lt;/b&gt; &lt;b&gt;var&lt;/b&gt; Stack);&lt;br /&gt;    &lt;b&gt;procedure&lt;/b&gt; Push&lt;br /&gt;      (S : &lt;b&gt;ref&lt;/b&gt; &lt;b&gt;var&lt;/b&gt; Stack; &lt;br /&gt;       X : Component);     &lt;br /&gt;&lt;b&gt;end&lt;/b&gt; &lt;b&gt;interface&lt;/b&gt; Stack;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;class&lt;/b&gt; Stack &lt;b&gt;is&lt;/b&gt;&lt;br /&gt;    &lt;b&gt;const&lt;/b&gt; Max_Len : Size_Type;&lt;br /&gt;    &lt;b&gt;var&lt;/b&gt; Cur_Len : Size_Type;&lt;br /&gt;    &lt;b&gt;type&lt;/b&gt; Index_Type &lt;b&gt;is&lt;/b&gt; Size_Type &lt;i&gt;{Index_Type in 1..Max_Len}&lt;/i&gt;;&lt;br /&gt;    &lt;b&gt;var&lt;/b&gt; Data : Array&amp;lt;&lt;b&gt;optional&lt;/b&gt; Component, Indexed_By =&amp;gt; Index_Type&amp;gt;;    &lt;br /&gt;  &lt;b&gt;exports&lt;/b&gt;&lt;br /&gt;    &lt;b&gt;function&lt;/b&gt; Create(Max : Size_Type) -&amp;gt; Stack &lt;b&gt;is&lt;/b&gt;&lt;br /&gt;      &lt;b&gt;return&lt;/b&gt; (Max_Len =&amp;gt; Max, Cur_Len =&amp;gt; 0, Data =&amp;gt; [.. =&amp;gt; &lt;b&gt;null&lt;/b&gt;]);&lt;br /&gt;    &lt;b&gt;end&lt;/b&gt; &lt;b&gt;function&lt;/b&gt; Create;&lt;br /&gt;&lt;br /&gt;    &lt;b&gt;procedure&lt;/b&gt; Push(S : &lt;b&gt;ref&lt;/b&gt; &lt;b&gt;var&lt;/b&gt; Stack; X : Component) &lt;b&gt;is&lt;/b&gt;&lt;br /&gt;      S.Cur_Len += 1;&lt;br /&gt;      S.Data[S.Cur_Len] := X;&lt;br /&gt;    &lt;b&gt;end&lt;/b&gt; &lt;b&gt;procedure&lt;/b&gt; Push;&lt;br /&gt;      &lt;br /&gt;    &lt;b&gt;function&lt;/b&gt; Top(S : &lt;b&gt;ref&lt;/b&gt; Stack) -&amp;gt; &lt;b&gt;ref&lt;/b&gt; Component &lt;b&gt;is&lt;/b&gt;&lt;br /&gt;      &lt;b&gt;return&lt;/b&gt; S.Data[S.Cur_Len];&lt;br /&gt;    &lt;b&gt;end&lt;/b&gt; &lt;b&gt;function&lt;/b&gt; Top;                &lt;br /&gt;&lt;br /&gt;    &lt;b&gt;procedure&lt;/b&gt; Pop(S : &lt;b&gt;ref&lt;/b&gt; &lt;b&gt;var&lt;/b&gt; Stack) &lt;b&gt;is&lt;/b&gt;&lt;br /&gt;      S.Cur_Len -= 1;&lt;br /&gt;    &lt;b&gt;end&lt;/b&gt; &lt;b&gt;procedure&lt;/b&gt; Pop;     &lt;br /&gt;&lt;b&gt;end&lt;/b&gt; &lt;b&gt;class&lt;/b&gt; Stack;&lt;br /&gt;&lt;/pre&gt;This all looks pretty straightforward until we try to compile it, and the compiler begins to complain at various places.  For example, we blithely add one to S.Cur_Len in Push without any apparent concern about overflow.  Then we blithely use the incremented S.Cur_Len as an index into S.Data, again with no apparent concern for the index being out of bounds.  &lt;br /&gt;&lt;br /&gt;The ParaSail compiler is never &lt;i&gt;blithe&lt;/i&gt;, and will complain because the Array abstraction imposes a precondition on the indexing into S.Data, requiring that the index be in the range of Index_Type (1..Max_Len).  It will also complain because the increment of S.Cur_Len might cause it to exceed the maximum Size_Type value (this precondition is from the "+=" operation of the Integer abstraction).&lt;br /&gt;&lt;br /&gt;We could resolve these problems by adding a meaningful constraint on the range of values of Cur_Len (namely &lt;i&gt;{Cur_Len in 0 .. Max_Len}&lt;/i&gt;) and adding a precondition on the Push operation ensuring that Cur_Len &amp;lt; Max_Len before any call on Push.&amp;nbsp; However, Cur_Len and Max_Len are not exported in the Stack interface, so we need to provide functions that reveal their value, say "Count" and "Max_Stack_Size."&amp;nbsp; So our new Stack abstraction would look like this:&lt;br /&gt;&lt;pre&gt;&lt;b&gt;interface&lt;/b&gt; Stack&lt;br /&gt;  &amp;lt;Component &lt;b&gt;is&lt;/b&gt; Assignable&amp;lt;&amp;gt;; &lt;br /&gt;   Size_Type &lt;b&gt;is&lt;/b&gt; Integer&amp;lt;&amp;gt;&amp;gt; &lt;b&gt;is&lt;/b&gt;&lt;br /&gt;    &lt;b&gt;function&lt;/b&gt; Max_Stack_Size(S : Stack) -&amp;gt; Size_Type;&lt;br /&gt;    &lt;b&gt;function&lt;/b&gt; Count(S : Stack) -&amp;gt; Size_Type;&lt;br /&gt;    &lt;b&gt;function&lt;/b&gt; Create(Max : Size_Type) -&amp;gt; Stack;&lt;br /&gt;    &lt;b&gt;function&lt;/b&gt; Top(S : &lt;b&gt;ref&lt;/b&gt; Stack) -&amp;gt; &lt;b&gt;ref&lt;/b&gt; Component;&lt;br /&gt;    &lt;b&gt;procedure&lt;/b&gt; Pop(S : &lt;b&gt;ref&lt;/b&gt; &lt;b&gt;var&lt;/b&gt; Stack);&lt;br /&gt;    &lt;b&gt;procedure&lt;/b&gt; Push&lt;br /&gt;      (S : &lt;b&gt;ref&lt;/b&gt; &lt;b&gt;var&lt;/b&gt; Stack &lt;i&gt;{Count(S) &amp;lt; Max_Stack_Size(S)}&lt;/i&gt;; &lt;br /&gt;       X : Component);&lt;br /&gt;&lt;b&gt;end&lt;/b&gt; &lt;b&gt;interface&lt;/b&gt; Stack;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;class&lt;/b&gt; Stack &lt;b&gt;is&lt;/b&gt;&lt;br /&gt;    &lt;b&gt;const&lt;/b&gt; Max_Len : Size_Type;&lt;br /&gt;    &lt;b&gt;var&lt;/b&gt; Cur_Len : Size_Type &lt;i&gt;{Cur_Len in 0..Max_Len}&lt;/i&gt;;&lt;br /&gt;    &lt;b&gt;type&lt;/b&gt; Index_Type &lt;b&gt;is&lt;/b&gt; Size_Type &lt;i&gt;{Index_Type in 1..Max_Len}&lt;/i&gt;;&lt;br /&gt;    &lt;b&gt;var&lt;/b&gt; Data : Array&amp;lt;&lt;b&gt;optional&lt;/b&gt; Component, Indexed_By =&amp;gt; Index_Type&amp;gt;;    &lt;br /&gt;  &lt;b&gt;exports&lt;/b&gt;&lt;br /&gt;    &lt;b&gt;function&lt;/b&gt; Max_Stack_Size(S : Stack) -&amp;gt; Size_Type &lt;b&gt;is&lt;/b&gt;&lt;br /&gt;      &lt;b&gt;return&lt;/b&gt; S.Max_Len;&lt;br /&gt;    &lt;b&gt;end&lt;/b&gt; &lt;b&gt;function&lt;/b&gt; Max_Stack_Size;&lt;br /&gt;    &lt;br /&gt;    &lt;b&gt;function&lt;/b&gt; Count(S : Stack) -&amp;gt; Size_Type &lt;b&gt;is&lt;/b&gt;&lt;br /&gt;      &lt;b&gt;return&lt;/b&gt; S.Cur_Len;&lt;br /&gt;    &lt;b&gt;end&lt;/b&gt; &lt;b&gt;function&lt;/b&gt; Count; &lt;br /&gt;&lt;br /&gt;    &lt;b&gt;function&lt;/b&gt; Create(Max : Size_Type &lt;i&gt;{Max &amp;gt; 0}&lt;/i&gt;) -&amp;gt; Stack &lt;b&gt;is&lt;/b&gt;&lt;br /&gt;      &lt;b&gt;return&lt;/b&gt; (Max_Len =&amp;gt; Max, Cur_Len =&amp;gt; 0, Data =&amp;gt; [.. =&amp;gt; &lt;b&gt;null&lt;/b&gt;]);&lt;br /&gt;    &lt;b&gt;end&lt;/b&gt; &lt;b&gt;function&lt;/b&gt; Create;&lt;br /&gt;&lt;br /&gt;    &lt;b&gt;procedure&lt;/b&gt; Push&lt;br /&gt;      (S : &lt;b&gt;ref&lt;/b&gt; &lt;b&gt;var&lt;/b&gt; Stack &lt;i&gt;{Count(S) &amp;lt; Max_Stack_Size(S)}&lt;/i&gt;; &lt;br /&gt;       X : Component) &lt;b&gt;is&lt;/b&gt;&lt;br /&gt;      S.Cur_Len += 1;&lt;br /&gt;      S.Data[S.Cur_Len] := X;&lt;br /&gt;    &lt;b&gt;end&lt;/b&gt; &lt;b&gt;procedure&lt;/b&gt; Push;&lt;br /&gt;      &lt;br /&gt;    &lt;b&gt;function&lt;/b&gt; Top(S : &lt;b&gt;ref&lt;/b&gt; Stack) -&amp;gt; &lt;b&gt;ref&lt;/b&gt; Component &lt;b&gt;is&lt;/b&gt;&lt;br /&gt;      &lt;b&gt;return&lt;/b&gt; S.Data[S.Cur_Len];&lt;br /&gt;    &lt;b&gt;end&lt;/b&gt; &lt;b&gt;function&lt;/b&gt; Top;                &lt;br /&gt;&lt;br /&gt;    &lt;b&gt;procedure&lt;/b&gt; Pop(S : &lt;b&gt;ref&lt;/b&gt; &lt;b&gt;var&lt;/b&gt; Stack) &lt;b&gt;is&lt;/b&gt;&lt;br /&gt;      S.Cur_Len -= 1;&lt;br /&gt;    &lt;b&gt;end&lt;/b&gt; &lt;b&gt;procedure&lt;/b&gt; Pop;&lt;br /&gt;&lt;b&gt;end&lt;/b&gt; &lt;b&gt;class&lt;/b&gt; Stack;&lt;br /&gt;&lt;/pre&gt;So with these changes, Push should now compile.  However, we are going to run into similar problems in Top and Pop, and we will need a precondition on both of those of &lt;i&gt;{Count(S) &amp;gt; 0}&lt;/i&gt;.&amp;nbsp; Top also presents a more subtle problem.&amp;nbsp; The Data array is defined as being an array of &lt;b&gt;optional&lt;/b&gt; Element_Type, but we are returning S.Data[S.Cur_Len] with a return type of simply Element_Type, implying that we somehow know that S.Data[S.Cur_Len] is not &lt;b&gt;null&lt;/b&gt;.&amp;nbsp; So how do we know that?&amp;nbsp; Well, we know that Push only pushes non-null elements onto the stack (because the parameter type for X is a non-&lt;b&gt;optional&lt;/b&gt; Element_Type.&amp;nbsp; But Data starts out all null, and when looking only at Top we have no way of knowing that S.Data[S.Cur_Len] is not null.&lt;br /&gt;&lt;br /&gt;What we need is some kind of class &lt;i&gt;invariant&lt;/i&gt; which ensures that when we get into Top, S.Data[S.Cur_Len] is not null.&amp;nbsp; What might that invariant look like?&amp;nbsp; What we know about a stack is that all of the elements that have been pushed onto the stack are non-null, but the slots in the stack past Cur_Len might be null if they have never been used.&amp;nbsp; So our invariant would seem to be:&lt;br /&gt;&lt;pre&gt;&lt;i&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;{for all I in 1..Cur_Len =&amp;gt; Data[I] not null}&lt;/i&gt;&lt;br /&gt;&lt;/pre&gt;The basic requirement for a class invariant is that, presuming it is true on entering any externally visible operation, it is true again on exiting that operation.&amp;nbsp; It might be false in the middle of some operation, but it is &lt;i&gt;preserved&lt;/i&gt; overall by all visible operations.&amp;nbsp; Furthermore, for any operation that creates an object of type Stack, the returned object must satisfy the invariant.&lt;br /&gt;&lt;br /&gt;So let us check whether the above proposed invariant is true upon creation of a Stack object, and is preserved by operations that modify a Stack.&amp;nbsp; Create produces a new value with Cur_Len == 0, so the invariant is trivially true, since there are no values in the interval 1..Cur_Len.&amp;nbsp; Push and Pop modify a Stack object.&amp;nbsp; Pop is trivial since it is decrementing Cur_Len, so the interval 1..Cur_Len is shrinking.&amp;nbsp; Push is not trivial, because it is adding one to Cur_Len.&amp;nbsp; But if we presume the invariant holds on entry to Push, then the only new value to worry about is S'.Data[S'.Cur_Len], where S' represents the value of S after the Push operation is complete.&amp;nbsp; Since S'.Data[S'.Cur_Len] is set to X, and X is not null, our invariant is preserved.&lt;br /&gt;&lt;br /&gt;Note that we might have tried an invariant of simply &lt;i&gt;{Data[Cur_Len] not null}&lt;/i&gt;, which would have satisfied Top, and would be preserved by Push, but it would not be preserved by Pop, since without the more sophisticated invariant, Pop would know nothing about S'.Data[S'.Cur_Len].&amp;nbsp; It might be null if the invariant only claims that the very top element is non-null.&lt;br /&gt;&lt;br /&gt;So after adding the class invariant, and the various preconditions, we can now get the Stack abstraction to compile.&amp;nbsp; However, it now becomes time to write some code that tests the Stack abstraction.&amp;nbsp; What we quickly discover is that the compiler rejects any call on any Stack operation with a precondition, since there are no postconditions that would allow it to know whether Count(S) &amp;gt; 0 or Count(S) &amp;lt; Max_Stack_Size(S).&amp;nbsp; At the call site there is no &lt;i&gt;peeking&lt;/i&gt; into the &lt;b&gt;class&lt;/b&gt; that defines the &lt;b&gt;interface&lt;/b&gt;.&amp;nbsp; The compiler must prove the preconditions of the call looking only at information in the &lt;b&gt;interface&lt;/b&gt;.&amp;nbsp; And without any postconditions, the compiler is stuck.&lt;br /&gt;&lt;br /&gt;So now we have to start adding postconditions to the operations.&amp;nbsp; If we do a Create and then immediately try to do a Push onto the created stack object, our first job is to prove that Count(S) &amp;lt; Max_Stack_Size(S).&amp;nbsp; This implies we need a postcondition on Create that indicates the values of Count() and Max_Stack_Size() for the result of Create.&amp;nbsp; We could write this as follows:&lt;br /&gt;&lt;pre&gt;&amp;nbsp;&amp;nbsp; &lt;i&gt;{Max_Stack_Size(Create) == Max; Count(Create) == 0}&lt;/i&gt; &lt;br /&gt;&lt;/pre&gt;What this says is that the result of Create (within a postcondition, we can use the name of the creating function to represent the result) has a Max_Stack_Size that corresponds to the passed in parameter Max, and starts out with a Count of zero.&amp;nbsp; No big surprise here, but without such a postcondition the compiler would be pretty much at a loss.&amp;nbsp; We also might want to impose a precondition on Max of &lt;i&gt;{Max &amp;gt; 0}&lt;/i&gt; just so the stack is at least of some use.&lt;br /&gt;&lt;br /&gt;Next question we might have is what happens to Count as a result of Push.&amp;nbsp; This brings up an interesting question that is sometimes called the &lt;i&gt;frame&lt;/i&gt; problem.&amp;nbsp; How do we know what might be written by an operation -- what is the &lt;i&gt;write frame&lt;/i&gt;?&amp;nbsp; (We might also be interested in exactly what might be read by an operation -- what is the &lt;i&gt;read frame&lt;/i&gt; -- but that is less relevant as far as checking preconditions.)&amp;nbsp; Since the Push operation has S as a &lt;b&gt;ref var&lt;/b&gt; parameter, we could assume the worst and assume any function of S' (the value of S after Push) might return a different value, so after Push we know pretty much nothing about Count(S') and Max_Stack_Size(S').&amp;nbsp; Alternatively, we could take the view that if there is no postcondition, then nothing is changed.&amp;nbsp; &lt;br /&gt;&lt;br /&gt;For ParaSail we are (tentatively) adopting a model that for any function of S mentioned in any precondition of an operation on a Stack object S, if such a function is not mentioned in a postcondition then it is presumed unchanged.&amp;nbsp; Now that we have mentioned Count() and Max_Stack_Size() in the preconditions of Push, we are duty bound to write postconditions any time the value of Count() or Max_Stack_Size() is changed.&amp;nbsp; This obligation will be checked when we compile the Stack class, so having written some preconditions, the compiler is going to start complaining because Count(S') is clearly going to be different from Count(S) after the call on Push.&amp;nbsp; Similar obligations will apply to Pop.&amp;nbsp; So now we will need to add a postcondition to Push of &lt;i&gt;{Count(S') == Count(S) + 1}&lt;/i&gt; and a postcondition to Pop of &lt;i&gt;{Count(S') == Count(S) - 1}&lt;/i&gt;.&amp;nbsp; We don't need to say that &lt;i&gt;{Max_Stack_Size(S') == Max_Stack_Size(S)}&lt;/i&gt; because as indicated, our default assumption is that anything used in any precondition, but not mentioned in a postcondition, is presumed to be unchanged by the operation.&amp;nbsp; Again, the compiler will check that when it compiles the code for the operation.&amp;nbsp; If we don't want to say anything about the new value other than it is not the same as the old value, we could say {Some_Property(S') != Some_Property(S)}.&amp;nbsp; That won't help the compiler with proving later preconditions, but it will at least satisfy the obligation to mention the changed property in a postcondition.&lt;br /&gt;&lt;br /&gt;So if we continue this process until we make the compiler happy, both with the Stack module itself, and with our various test programs, we will probably end up with a relatively fully annotated Stack like the following:&lt;br /&gt;&lt;pre&gt;&lt;b&gt;interface&lt;/b&gt; Stack&lt;br /&gt;  &amp;lt;Component &lt;b&gt;is&lt;/b&gt; Assignable&amp;lt;&amp;gt;; &lt;br /&gt;   Size_Type &lt;b&gt;is&lt;/b&gt; Integer&amp;lt;&amp;gt;&amp;gt; &lt;b&gt;is&lt;/b&gt;&lt;br /&gt;    &lt;b&gt;function&lt;/b&gt; Max_Stack_Size(S : Stack) -&amp;gt; Size_Type;&lt;br /&gt;    &lt;b&gt;function&lt;/b&gt; Count(S : Stack) -&amp;gt; Size_Type;&lt;br /&gt;&lt;br /&gt;    &lt;b&gt;function&lt;/b&gt; Create(Max : Size_Type &lt;i&gt;{Max &amp;gt; 0}&lt;/i&gt;) -&amp;gt; Stack &lt;br /&gt;      &lt;i&gt;{Max_Stack_Size(Create) == Max; Count(Create) == 0}&lt;/i&gt;;&lt;br /&gt;    &lt;br /&gt;    &lt;b&gt;procedure&lt;/b&gt; Push&lt;br /&gt;      (S : &lt;b&gt;ref&lt;/b&gt; &lt;b&gt;var&lt;/b&gt; Stack &lt;i&gt;{Count(S) &amp;lt; Max_Stack_Size(S)}&lt;/i&gt;; &lt;br /&gt;       X : Component) &lt;i&gt;{Count(S') == Count(S) + 1}&lt;/i&gt;;&lt;br /&gt;&lt;br /&gt;    &lt;b&gt;function&lt;/b&gt; Top(S : &lt;b&gt;ref&lt;/b&gt; Stack &lt;i&gt;{Count(S) &amp;gt; 0}&lt;/i&gt;) -&amp;gt; &lt;b&gt;ref&lt;/b&gt; Component;&lt;br /&gt;    &lt;br /&gt;    &lt;b&gt;procedure&lt;/b&gt; Pop(S : &lt;b&gt;ref&lt;/b&gt; &lt;b&gt;var&lt;/b&gt; Stack &lt;i&gt;{Count(S) &amp;gt; 0}&lt;/i&gt;) &lt;br /&gt;      &lt;i&gt;{Count(S') == Count(S) - 1}&lt;/i&gt;;&lt;br /&gt;&lt;b&gt;end&lt;/b&gt; &lt;b&gt;interface&lt;/b&gt; Stack;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;class&lt;/b&gt; Stack &lt;b&gt;is&lt;/b&gt;&lt;br /&gt;    &lt;b&gt;const&lt;/b&gt; Max_Len : Size_Type;&lt;br /&gt;    &lt;b&gt;var&lt;/b&gt; Cur_Len : Size_Type &lt;i&gt;{Cur_Len in 0..Max_Len}&lt;/i&gt;;&lt;br /&gt;    &lt;b&gt;type&lt;/b&gt; Index_Type &lt;b&gt;is&lt;/b&gt; Size_Type &lt;i&gt;{Index_Type in 1..Max_Len}&lt;/i&gt;;&lt;br /&gt;    &lt;b&gt;var&lt;/b&gt; Data : Array&amp;lt;&lt;b&gt;optional&lt;/b&gt; Component, Indexed_By =&amp;gt; Index_Type&amp;gt;;    &lt;br /&gt;  &lt;b&gt;exports&lt;/b&gt;&lt;br /&gt;    &lt;i&gt;{&lt;b&gt;for&lt;/b&gt; &lt;b&gt;all&lt;/b&gt; I &lt;b&gt;in&lt;/b&gt; 1..Cur_Len =&amp;gt; Data[I] &lt;b&gt;not&lt;/b&gt; &lt;b&gt;null&lt;/b&gt;}&lt;/i&gt;   &lt;i&gt;// invariant for Top()&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;    &lt;b&gt;function&lt;/b&gt; Max_Stack_Size(S : Stack) -&amp;gt; Size_Type &lt;b&gt;is&lt;/b&gt;&lt;br /&gt;        &lt;b&gt;return&lt;/b&gt; S.Max_Len;&lt;br /&gt;    &lt;b&gt;end&lt;/b&gt; &lt;b&gt;function&lt;/b&gt; Max_Stack_Size;&lt;br /&gt;    &lt;br /&gt;    &lt;b&gt;function&lt;/b&gt; Count(S : Stack) -&amp;gt; Size_Type &lt;b&gt;is&lt;/b&gt;&lt;br /&gt;      &lt;b&gt;return&lt;/b&gt; S.Cur_Len;&lt;br /&gt;    &lt;b&gt;end&lt;/b&gt; &lt;b&gt;function&lt;/b&gt; Count; &lt;br /&gt;&lt;br /&gt;    &lt;b&gt;function&lt;/b&gt; Create(Max : Size_Type &lt;i&gt;{Max &amp;gt; 0}&lt;/i&gt;) -&amp;gt; Stack&lt;br /&gt;      &lt;i&gt;{Max_Stack_Size(Create) == Max; Count(Create) == 0}&lt;/i&gt; &lt;b&gt;is&lt;/b&gt;&lt;br /&gt;      &lt;b&gt;return&lt;/b&gt; (Max_Len =&amp;gt; Max, Cur_Len =&amp;gt; 0, Data =&amp;gt; [.. =&amp;gt; &lt;b&gt;null&lt;/b&gt;]);&lt;br /&gt;    &lt;b&gt;end&lt;/b&gt; &lt;b&gt;function&lt;/b&gt; Create;&lt;br /&gt;&lt;br /&gt;    &lt;b&gt;procedure&lt;/b&gt; Push&lt;br /&gt;      (S : &lt;b&gt;ref&lt;/b&gt; &lt;b&gt;var&lt;/b&gt; Stack &lt;i&gt;{Count(S) &amp;lt; Max_Stack_Size(S)}&lt;/i&gt;; &lt;br /&gt;       X : Component) &lt;i&gt;{Count(S') == Count(S) + 1}&lt;/i&gt; &lt;b&gt;is&lt;/b&gt;&lt;br /&gt;      S.Cur_Len += 1;&lt;br /&gt;      S.Data[S.Cur_Len] := X;&lt;br /&gt;    &lt;b&gt;end&lt;/b&gt; &lt;b&gt;procedure&lt;/b&gt; Push;&lt;br /&gt;      &lt;br /&gt;    &lt;b&gt;function&lt;/b&gt; Top(S : &lt;b&gt;ref&lt;/b&gt; Stack &lt;i&gt;{Count(S) &amp;gt; 0}&lt;/i&gt;) -&amp;gt; &lt;b&gt;ref&lt;/b&gt; Component &lt;b&gt;is&lt;/b&gt;&lt;br /&gt;      &lt;b&gt;return&lt;/b&gt; S.Data[S.Cur_Len];&lt;br /&gt;    &lt;b&gt;end&lt;/b&gt; &lt;b&gt;function&lt;/b&gt; Top;                &lt;br /&gt;&lt;br /&gt;    &lt;b&gt;procedure&lt;/b&gt; Pop(S : &lt;b&gt;ref&lt;/b&gt; &lt;b&gt;var&lt;/b&gt; Stack &lt;i&gt;{Count(S) &amp;gt; 0}&lt;/i&gt;) &lt;br /&gt;      &lt;i&gt;{Count(S') == Count(S) - 1}&lt;/i&gt; &lt;b&gt;is&lt;/b&gt;&lt;br /&gt;        S.Cur_Len -= 1;&lt;br /&gt;    &lt;b&gt;end&lt;/b&gt; &lt;b&gt;procedure&lt;/b&gt; Pop;&lt;br /&gt;&lt;b&gt;end&lt;/b&gt; &lt;b&gt;class&lt;/b&gt; Stack;&lt;br /&gt;&lt;/pre&gt;One thing to note is that the compiler has not forced us to create postconditions that ensure all the nice properties of Stacks, such as after Push(S,X), then Top(S') == X, or if Top(S) == A, then after Push(S, X) and Pop(S'), Top(S'') == A.&amp;nbsp; These might be called &lt;i&gt;correctness&lt;/i&gt; preconditions as opposed to merely &lt;i&gt;safety&lt;/i&gt; preconditions, and they are up to the programmer to add if they see fit.&amp;nbsp; We have considered having a &lt;i&gt;second class&lt;/i&gt; annotation in ParaSail which is &lt;i&gt;not&lt;/i&gt; required to be provable at compile-time, but is designed to aid in correctness proofs, and provide additional debugging support.&amp;nbsp; We have set aside a syntax of doubly nested &lt;i&gt;{{...}}&lt;/i&gt; for such correctness preconditions, but we aren't worrying about them more than that at this point.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8383004232931899216-5373133023193822374?l=parasail-programming-language.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://parasail-programming-language.blogspot.com/feeds/5373133023193822374/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://parasail-programming-language.blogspot.com/2011/04/writing-preconditions-and.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8383004232931899216/posts/default/5373133023193822374'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8383004232931899216/posts/default/5373133023193822374'/><link rel='alternate' type='text/html' href='http://parasail-programming-language.blogspot.com/2011/04/writing-preconditions-and.html' title='Writing preconditions and postconditions incrementally'/><author><name>Tuck</name><uri>http://www.blogger.com/profile/08866496974237052847</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8383004232931899216.post-9181125702096436341</id><published>2011-03-09T00:14:00.000-05:00</published><updated>2011-03-09T00:14:10.978-05:00</updated><title type='text'>WoDet 2011, ParaSail, and back to the future with Value Semantics</title><content type='html'>This past Sunday &lt;i&gt;WoDet 2011&lt;/i&gt;, the &lt;i&gt;2nd Workshop on Determinism and Correctness in Parallel Programming&lt;/i&gt; was held in Newport Beach, CA.&amp;nbsp; It was a very interesting event, with a number of excellent talks and a lively debate at the end on the topic of whether current programming models are sufficient given the right tools, etc., or whether we need fundamentally new models to support programming going forward in a multi-core world.&amp;nbsp;&lt;br /&gt;&lt;br /&gt;After listening to the various talks at the workshop, and while thinking about the debate topic, it seemed that &lt;b&gt;ParaSail&lt;/b&gt; aligned nicely with an underlying thread in the research community moving toward, or perhaps returning to, what might best be called &lt;i&gt;value semantics&lt;/i&gt;.&amp;nbsp; A number of the talks described one variant or another of multi-version concurrency control, which at its heart involves giving different threads their own private copy/version/snapshot of an object, and then dealing with merging any updates at specific later points, possibly rolling back one of the threads if no meaningful merge is possible.&amp;nbsp; This is in contrast to an approach where multiple threads share access to a single object, and use some kind of locking or "careful" lock-free operations to make direct updates to the shared object.&amp;nbsp; The multi-version approach results in fewer interactions between the threads, fewer synchronization points, and hence generally higher throughput in a highly parallel world.&amp;nbsp;&lt;br /&gt;&lt;br /&gt;Looked at another way, the multi-version approach means that objects are being passed around by &lt;i&gt;value&lt;/i&gt; rather than by &lt;i&gt;reference&lt;/i&gt;, and updating the original object is done after all the new "values" have been generated independently and then appropriately merged (perhaps using some kind of parallel merging process).&amp;nbsp; This isn't going all the way to pure functional programming, because updates can eventually happen, but the bulk of the processing is performed on object &lt;i&gt;values&lt;/i&gt;, with no underlying sharing.&lt;br /&gt;&lt;br /&gt;If we go all the way back to the original versions of BASIC, a la Kemeny and Kurtz or Microsoft CP/M BASIC, pointers didn't exist, but there were &lt;i&gt;strings&lt;/i&gt;, and you could create them and concatenate them and assign them, and you never by mistake overwrote memory because you concatenated into a too-short buffer, nor did you ever have two variables unintentionally referring to the "same" string in memory, such that changing one would unintentionally alter what you had in the other (even though the implementation might choose to share the space until one of them was altered).&amp;nbsp;&lt;br /&gt;&lt;br /&gt;These kinds of &lt;i&gt;value-semantics&lt;/i&gt; strings still exist in many scripting languages, but they have essentially disappeared from compiled languages in the years since BASIC was widely used (and compiled, in some cases).&amp;nbsp; In almost all modern compiled languages, strings are manipulated by &lt;i&gt;reference&lt;/i&gt;, though in some languages they are immutable which to some extent skirts the issue of by-value vs. by-reference semantics.&amp;nbsp; And certainly when you get to larger, more abstract objects, by-reference semantics rules, with only the simplest of "struct" objects being manipulated by value.&amp;nbsp; And even when declared objects have value semantics, parameters generally revert to by-reference semantics, again introducing the possibility of unintended aliasing between two distinctly named objects.&amp;nbsp; (Or if by-value semantics are available for parameter passing (as in C++), it can result in "slicing" of the object, so that it is truncated from its original run-time type to the compile-time type of the formal parameter.)&lt;br /&gt;&lt;br /&gt;Unintended aliasing due to by-reference semantics can cause nasty (but still reproducible) bugs in any sequential language that uses by-reference semantics, but in a parallel language, such bugs can become race conditions, which can result in hard-to-reproduce, timing-dependent bugs.&lt;br /&gt;&lt;br /&gt;In any case, the net effect of the various ParaSail rules that restrict aliasing, eliminate reassignable pointers, disallow global variables, etc. is that ParaSail provides &lt;i&gt;value&lt;/i&gt; &lt;i&gt;semantics&lt;/i&gt; for all non-concurrent objects, of arbitrarily complex types.&amp;nbsp; Note that this does &lt;i&gt;not&lt;/i&gt; imply that objects need to be copied when passed as a parameter.&amp;nbsp; Rather the ParaSail rules allow non-concurrent objects to be passed by reference &lt;i&gt;or&lt;/i&gt; by copy, with the same results. This allows efficient by-reference parameter passing when the call stays within the same address space, but allows transferring the object between address spaces, such as might be needed by a call between a CPU and a GPU.&amp;nbsp; This essentially value semantics eliminates a large class of common bugs, and makes it straightforward for the compiler to detect and disallow at compile-time any possible race conditions.&lt;br /&gt;&lt;br /&gt;As implied by the growing interest in multi-version concurrency control in the research community, a return to the world of &lt;i&gt;value semantics&lt;/i&gt; might be a good answer for the multi-core challenges.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8383004232931899216-9181125702096436341?l=parasail-programming-language.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://parasail-programming-language.blogspot.com/feeds/9181125702096436341/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://parasail-programming-language.blogspot.com/2011/03/wodet-2011-parasail-and-back-to-future.html#comment-form' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8383004232931899216/posts/default/9181125702096436341'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8383004232931899216/posts/default/9181125702096436341'/><link rel='alternate' type='text/html' href='http://parasail-programming-language.blogspot.com/2011/03/wodet-2011-parasail-and-back-to-future.html' title='WoDet 2011, ParaSail, and back to the future with Value Semantics'/><author><name>Tuck</name><uri>http://www.blogger.com/profile/08866496974237052847</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8383004232931899216.post-5331847847850843915</id><published>2011-03-01T10:38:00.000-05:00</published><updated>2011-03-01T10:38:12.289-05:00</updated><title type='text'>Streaming in Parasail -- A Unix-like pipeline</title><content type='html'>We have been considering how &lt;i&gt;streaming&lt;/i&gt; can best be supported in &lt;b&gt;ParaSail&lt;/b&gt;.&amp;nbsp; By streaming we mean having a series of components each of which reads inputs from a stream and writes outputs to a stream, with each component running in parallel with the others.&amp;nbsp; The most natural seems to be to define an abstract Stream_Component interface which takes an Input_Stream and Output_Stream type and declares an operation Transform which reads one or more input elements from the Input_Stream, transforms the input(s) in some way, and then writes one or more output elements to the Output_Stream.&amp;nbsp;&amp;nbsp; An actual component would be defined by some concrete module that implements this abstract interface, with an appropriate constructor function that provides whatever arguments are needed to specify or control the transformation.&lt;br /&gt;&lt;br /&gt;This might be the abstract Stream_Component interface:&lt;br /&gt;&lt;pre&gt;&lt;b&gt;abstract interface&lt;/b&gt; Stream_Component&lt;br /&gt;  &amp;lt;Input_Stream&amp;lt;&amp;gt;; Output_Stream&amp;lt;&amp;gt;&amp;gt; &lt;b&gt;is&lt;/b&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;b&gt;procedure&lt;/b&gt; Transform&lt;br /&gt;      (Args : Stream_Component;&lt;br /&gt;       Inp : &lt;b&gt;ref var&lt;/b&gt; Input_Stream; &lt;br /&gt;       Outp : &lt;b&gt;ref var&lt;/b&gt; Output_Stream);&lt;br /&gt;&lt;b&gt;end interface&lt;/b&gt; Stream_Component;&lt;br /&gt;&lt;/pre&gt;The Input_Stream and Output_Stream interfaces might look like this:&lt;br /&gt;&lt;pre&gt;&lt;b&gt;abstract concurrent&lt;/b&gt; &lt;b&gt;interface&lt;/b&gt; Input_Stream&lt;br /&gt;  &amp;lt;Element_Type is Assignable&amp;lt;&amp;gt;&amp;gt; &lt;b&gt;is&lt;/b&gt;&lt;br /&gt;    &lt;b&gt;function&lt;/b&gt; Get(Stream : &lt;b&gt;queued var&lt;/b&gt; Input_Stream) -&amp;gt; &lt;b&gt;optional&lt;/b&gt; Element_Type;&lt;br /&gt;&lt;b&gt;end interface&lt;/b&gt; Input_Stream;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;abstract concurrent&lt;/b&gt; &lt;b&gt;interface&lt;/b&gt; Output_Stream&lt;br /&gt;  &amp;lt;Element_Type is Assignable&amp;lt;&amp;gt;&amp;gt; &lt;b&gt;is&lt;/b&gt;&lt;br /&gt;    &lt;b&gt;procedure&lt;/b&gt; Put&lt;br /&gt;      (Stream : &lt;b&gt;queued var&lt;/b&gt; Output_Stream; Element : Element_Type);&lt;br /&gt;    &lt;b&gt;procedure&lt;/b&gt; Close(Stream : &lt;b&gt;queued&lt;/b&gt; &lt;b&gt;var&lt;/b&gt; Output_Stream);&lt;br /&gt;&lt;b&gt;end interface&lt;/b&gt; Output_Stream;&lt;/pre&gt;We now want to put together two or more stream components into a pipeline.  Let us presume we define a Pipeline interface:&lt;br /&gt;&lt;pre&gt;&lt;b&gt;interface&lt;/b&gt; Pipeline&lt;br /&gt;  &amp;lt;Pipe_Input is Input_Stream&amp;lt;&amp;gt;;&lt;br /&gt;   Pipe_Output is Output_Stream&amp;lt;&amp;gt;&amp;gt; &lt;br /&gt;  &lt;b&gt;implements&lt;/b&gt; Stream_Component&amp;lt;Pipe_Input, Pipe_Output&amp;gt; is&lt;br /&gt;    &lt;b&gt;operator&lt;/b&gt; "|"&lt;br /&gt;     (Left &lt;b&gt;is&lt;/b&gt; Stream_Component&lt;br /&gt;        &amp;lt;Pipe_Input,&lt;br /&gt;         Output_Stream&amp;lt;Internal_Type &lt;b&gt;is&lt;/b&gt; Assignable&amp;lt;&amp;gt;&amp;gt;;&lt;br /&gt;      Right &lt;b&gt;is &lt;/b&gt;Stream_Component&lt;br /&gt;        &amp;lt;Input_Stream&amp;lt;Internal_Type&amp;gt;,&lt;br /&gt;         Pipe_Output&amp;gt;)&lt;br /&gt;     -&amp;gt; Pipeline;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;b&gt;procedure&lt;/b&gt; Transform&lt;br /&gt;      (Args : Pipeline;&lt;br /&gt;       Inp : &lt;b&gt;ref var&lt;/b&gt; Pipe_Input; &lt;br /&gt;       Outp : &lt;b&gt;ref var&lt;/b&gt; Pipe_Output);&lt;br /&gt;&lt;b&gt;end interface&lt;/b&gt; Pipeline;&lt;/pre&gt;The pipeline "|" operator takes two stream components and produces a Pipeline stream component, feeding the output of the first stream component into the input for the second stream component, by using an IO_Queue:&lt;br /&gt;&lt;pre&gt;&lt;b&gt;concurrent interface&lt;/b&gt; IO_Queue&amp;lt;Element_Type &lt;b&gt;is&lt;/b&gt; Assignable&amp;lt;&amp;gt;&amp;gt; &lt;br /&gt;  &lt;b&gt;implements&lt;/b&gt; Input_Stream&amp;lt;Element_Type&amp;gt;, Output_Stream&amp;lt;Element_Type&amp;gt; &lt;b&gt;is&lt;/b&gt;&lt;br /&gt;    &lt;b&gt;function&lt;/b&gt; Create(Buffer_Size : Univ_Integer := 100) -&amp;gt; IO_Queue;&lt;br /&gt;    &lt;b&gt;function&lt;/b&gt; Get(Queue : &lt;b&gt;queued var&lt;/b&gt; IO_Queue) -&amp;gt; &lt;b&gt;optional&lt;/b&gt; Element_Type;&lt;br /&gt;    &lt;b&gt;procedure&lt;/b&gt; Put&lt;br /&gt;      (Queue : &lt;b&gt;queued var&lt;/b&gt; IO_Queue; Element : Element_Type);&lt;br /&gt;    &lt;b&gt;procedure&lt;/b&gt; Close(Queue : &lt;b&gt;queued&lt;/b&gt; &lt;b&gt;var&lt;/b&gt; IO_Queue);&lt;br /&gt;&lt;b&gt;end interface&lt;/b&gt; IO_Queue;&lt;br /&gt;&lt;/pre&gt;When constructing a pipeline from two stream components, the output stream of the first must have the same Element_Type as the input stream for the second, so that they can be opposite ends of the IO_Queue.  The result pipeline has the same input stream as the first, and the same output stream as the second.  The implementation of the pipeline Transform procedure would construct an IO_Queue object and then pass it to parallel invocations of the Transform procedures of the two stream components:&lt;br /&gt;&lt;pre&gt;&lt;b&gt;class&lt;/b&gt; Pipeline &lt;b&gt;is&lt;/b&gt;&lt;br /&gt;    &lt;b&gt;const&lt;/b&gt; Left : Stream_Component+;&lt;br /&gt;    &lt;b&gt;const&lt;/b&gt; Right : Stream_Component+;&lt;br /&gt;  &lt;b&gt;exports&lt;/b&gt;&lt;br /&gt;    &lt;b&gt;operator&lt;/b&gt; "|"&lt;br /&gt;     (Left &lt;b&gt;is&lt;/b&gt; Stream_Component&lt;br /&gt;        &amp;lt;Pipe_Input,&lt;br /&gt;         Output_Stream&amp;lt;Internal_Type &lt;b&gt;is&lt;/b&gt; Assignable&amp;lt;&amp;gt;&amp;gt;;&lt;br /&gt;      Right &lt;b&gt;is&lt;/b&gt; Stream_Component&lt;br /&gt;        &amp;lt;Input_Stream&amp;lt;Internal_Type&amp;gt;,&lt;br /&gt;         Pipe_Output&amp;gt;)&lt;br /&gt;     -&amp;gt; Pipeline &lt;b&gt;is&lt;/b&gt;&lt;br /&gt;      &lt;b&gt;return&lt;/b&gt; (Left =&amp;gt; Left; Right =&amp;gt; Right);&lt;br /&gt;    &lt;b&gt;end operator&lt;/b&gt; "|"; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;b&gt;procedure&lt;/b&gt; Transform&lt;br /&gt;      (Args : Pipeline;&lt;br /&gt;       Inp : &lt;b&gt;ref var&lt;/b&gt; Pipe_Input; &lt;br /&gt;       Outp : &lt;b&gt;ref var&lt;/b&gt; Pipe_Output) &lt;b&gt;is&lt;/b&gt;&lt;br /&gt;        &lt;b&gt;var&lt;/b&gt; Queue : IO_Queue := Create();&lt;br /&gt;      &lt;b&gt;then&lt;/b&gt;&lt;br /&gt;        Transform(Left, Inp, Queue);&lt;br /&gt;      || &lt;br /&gt;        Transform(Right, Queue, Outp);&lt;br /&gt;    &lt;b&gt;end procedure&lt;/b&gt; Transform;&lt;br /&gt;&lt;b&gt;end class&lt;/b&gt; Pipeline;&lt;br /&gt;&lt;/pre&gt;If we have a set of components with both input and output streams being streams of characters, then the "|" operator is essentially equivalent to the Unix shell's "|" pipe command.  To write a "program" that is compatible with such a pipeline, we define a module that implements Stream_Component, with Input_Stream and Output_Stream both having Element_Type of Character&amp;lt;&amp;gt;.  Any constructor function within such a module may be used to provide the parameters to the program.  The Transform procedure of the module is the one that actually performs the action of the program.  Alternatively, we can be somewhat more flexible, and allow the streams to have higher level element types, such as words or lines.&lt;br /&gt;&lt;br /&gt;For example, here is a trivial "element count" program, which allows the input element type to be any sort of thing.  The output element type is presumed to be some Character type:&lt;br /&gt;&lt;pre&gt;&lt;b&gt;interface&lt;/b&gt; Elem_Count&lt;br /&gt;  &amp;lt;Input_Stream&amp;lt;&amp;gt;, Output_Stream&amp;lt;Character&amp;lt;&amp;gt;&amp;gt;&amp;gt;&lt;br /&gt;&lt;b&gt;&amp;nbsp; implements&lt;/b&gt; Stream_Component&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;lt;Input_Stream, Output_Stream&amp;gt; &lt;b&gt;is&lt;/b&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;b&gt;function&lt;/b&gt; Args()-&amp;gt;Elem_Count;&amp;nbsp;&lt;i&gt; // takes no parameters&lt;/i&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;b&gt;procedure&lt;/b&gt; Transform&lt;br /&gt;      (Args : Elem_Count;&lt;br /&gt;       Inp : &lt;b&gt;ref var&lt;/b&gt; Input_Stream; Outp : &lt;b&gt;ref var&lt;/b&gt; Output_Stream);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;i&gt;// Prints a count of the elements in Inp on the Outp stream&lt;/i&gt;&lt;br /&gt;&lt;b&gt;end interface&lt;/b&gt; Elem_Count;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;class&lt;/b&gt; Elem_Count &lt;b&gt;is&lt;/b&gt;&lt;br /&gt;&amp;nbsp; &lt;b&gt;exports&lt;/b&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;b&gt;function&lt;/b&gt; Args() -&amp;gt; Result : Elem_Count &lt;b&gt;is&lt;/b&gt;&lt;br /&gt;&lt;b&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return&lt;/b&gt;;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;b&gt;end function&lt;/b&gt; Args;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;b&gt;procedure&lt;/b&gt; Transform&lt;br /&gt;      (Args : Character_Count;&lt;br /&gt;       Inp : &lt;b&gt;ref var&lt;/b&gt; Input_Stream; Outp : &lt;b&gt;ref var&lt;/b&gt; Output_Stream) &lt;b&gt;is&lt;/b&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;i&gt;// Prints a count of the elements in Inp on the Outp stream&lt;/i&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp; &lt;b&gt;var&lt;/b&gt; Count : Univ_Integer := 0;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;b&gt;while&lt;/b&gt; Get(Inp) &lt;b&gt;not&lt;/b&gt; &lt;b&gt;null loop&lt;/b&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Count += 1;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp; &lt;b&gt;end loop&lt;/b&gt;;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;b&gt;const&lt;/b&gt; Answer : String&amp;lt;Output_Stream::Element_Type&amp;gt; := To_String(Count);&lt;br /&gt;       &lt;i&gt;// Copy the answer to the output stream one character at a time&lt;br /&gt;       // (in all probability, we would actually use an output stream&lt;br /&gt;       //  with an operation that takes a string of characters directly).&lt;/i&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;b&gt;for&lt;/b&gt; &lt;b&gt;each&lt;/b&gt; C &lt;b&gt;of&lt;/b&gt; Answer &lt;b&gt;forward loop&lt;/b&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Put(Outp, C);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;b&gt;end loop&lt;/b&gt;;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Close(Outp);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;b&gt;end procedure&lt;/b&gt; Transform;&lt;br /&gt;&lt;b&gt;end class&lt;/b&gt; Elem_Count; &lt;br /&gt;&lt;/pre&gt;In a more realistic example, the Args constructor function would take one or more arguments, which it would store as fields of the stream component object.  The Transform procedure would refer to the arguments using the Args parameter, which is an instance of the stream component object.&lt;br /&gt;&lt;br /&gt;Presuming we create a number of stream components like Elem_Count, we could construct a pipeline like the following:&lt;br /&gt;&lt;pre&gt;Read::Args("my_file.txt") | Break_Into_Words::Args() | Elem_Count::Args()&lt;br /&gt;&lt;/pre&gt;This would presumably read my_file.txt producing a stream of characters, break it into a stream of words, and then count the words and produce the count as a string on the output stream of characters.  With a little syntactic sugar by some kind of ParaSail "shell" this could become:&lt;br /&gt;&lt;pre&gt;Read my_file.txt | Break_Into_Words | Elem_Count&lt;br /&gt;&lt;/pre&gt;This is a little bit of a "cheat" as we would have to pass in the "Context" or equivalent to "Read" to provide it access to the underlying file system.  The Context argument could presumably be supplied automatically as part of the syntactic sugar provided by the "shell" if desired.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8383004232931899216-5331847847850843915?l=parasail-programming-language.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://parasail-programming-language.blogspot.com/feeds/5331847847850843915/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://parasail-programming-language.blogspot.com/2011/03/streaming-in-parasail-unix-like.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8383004232931899216/posts/default/5331847847850843915'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8383004232931899216/posts/default/5331847847850843915'/><link rel='alternate' type='text/html' href='http://parasail-programming-language.blogspot.com/2011/03/streaming-in-parasail-unix-like.html' title='Streaming in Parasail -- A Unix-like pipeline'/><author><name>Tuck</name><uri>http://www.blogger.com/profile/08866496974237052847</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8383004232931899216.post-3207168560731000502</id><published>2011-02-08T17:29:00.000-05:00</published><updated>2011-02-08T17:29:37.580-05:00</updated><title type='text'>Map/Reduce in ParaSail; Parameterized operations</title><content type='html'>The &lt;i&gt;Map/Reduce&lt;/i&gt; paradigm popularized by Google has a long history.  In APL, there is a &lt;i&gt;reduction&lt;/i&gt; operator "/", which can be combined with an operator like "+" to &lt;i&gt;reduce&lt;/i&gt; a vector to a scalar, by summing its individual members.  That is "+/ V" adds up the elements of V producing a scalar sum.  To include a &lt;i&gt;map&lt;/i&gt; operation, you could simply insert the name of the scalar-&amp;gt;scalar function of interest in the middle, and you get the map-reduce functionality.  For example, "+/ V*2" would produce the sum of squares of the vector V ("*" is exponentiation in APL, "x" is used for multiplication).&lt;br /&gt;&lt;br /&gt;In Google's variant of Map/Reduce, the input is a vector of key/value pairs, and the &lt;i&gt;map&lt;/i&gt; operation takes one key/value pair and produces as output a list of key/value pairs.  The &lt;i&gt;reduce&lt;/i&gt; operation takes all values produced by any &lt;i&gt;map&lt;/i&gt; invocation with the same key and combines them to produce a single value, or optionally a list of values, to be associated with this (output) key.&lt;br /&gt;&lt;br /&gt;A simple, parallel version of Map/Reduce can be implemented relatively straightforwardly in &lt;b&gt;ParaSail&lt;/b&gt;, as a single function, parameterized by the input and output types of the "Map" function:&lt;br /&gt;&lt;pre&gt;&lt;i&gt;// ParaSail Function to perform Map-Reduce operation.&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;function&lt;/b&gt; Map_Reduce&lt;br /&gt;  (&lt;b&gt;function&lt;/b&gt; Map(Input &lt;b&gt;is&lt;/b&gt; Any&amp;lt;&amp;gt;) -&amp;gt; (Output &lt;b&gt;is&lt;/b&gt; Any&amp;lt;&amp;gt;);&lt;br /&gt;   &lt;b&gt;function&lt;/b&gt; Reduce(Left, Right : Output) -&amp;gt; Output;&lt;br /&gt;   Inputs : Vector&amp;lt;Input&amp;gt;)  &lt;i&gt;{Length(Inputs) &amp;gt; 0}&lt;/i&gt; -&amp;gt; Output &lt;b&gt;is&lt;/b&gt;&lt;br /&gt;       &lt;i&gt;// Handle singleton directly, recurse for longer inputs&lt;/i&gt;&lt;br /&gt;       &lt;b&gt;if&lt;/b&gt; Length(Inputs) == 1 &lt;b&gt;then&lt;/b&gt;&lt;br /&gt;         &lt;b&gt;return&lt;/b&gt; Map(Inputs[1]);&lt;br /&gt;       &lt;b&gt;else&lt;/b&gt;&lt;br /&gt;         &lt;i&gt;// Split and recurse&lt;/i&gt;&lt;br /&gt;         &lt;b&gt;const&lt;/b&gt; Half_Length := Length(Inputs)/2;&lt;br /&gt;         &lt;b&gt;return&lt;/b&gt; Reduce&lt;br /&gt;           (Map_Reduce(Map, Reduce, Inputs[1..Half_Length]),&lt;br /&gt;             Map_Reduce(Map, Reduce, &lt;br /&gt;        Inputs[Half_Length &amp;lt;.. Length(Inputs)]));&lt;br /&gt;       &lt;b&gt;end&lt;/b&gt; &lt;b&gt;if&lt;/b&gt;;&lt;br /&gt;&lt;b&gt;end&lt;/b&gt; &lt;b&gt;function&lt;/b&gt; Map_Reduce;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;procedure&lt;/b&gt; Test() &lt;b&gt;is&lt;/b&gt;  &lt;i&gt;// Test Map_Reduce function -- compute sum of squares&lt;/i&gt;&lt;br /&gt;    Print_Int(Map_Reduce&lt;br /&gt;      (Map =&amp;gt; &lt;b&gt;lambda&lt;/b&gt;(X : Integer) -&amp;gt; Integer &lt;b&gt;is&lt;/b&gt; (X**2),&lt;br /&gt;       Reduce =&amp;gt; "+",&lt;br /&gt;       Inputs =&amp;gt; [1, 2, 3, 4, 5, 6]));&lt;br /&gt;&lt;b&gt;end&lt;/b&gt; &lt;b&gt;procedure&lt;/b&gt; Test;&lt;/pre&gt;&lt;br /&gt;In ParaSail, the parameters in any call can be evaluated concurrently, so the two operands in the call on &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;Reduce&lt;/span&gt;, which are recursive calls on &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;Map_Reduce&lt;/span&gt;, will become separate &lt;i&gt;pico-threads&lt;/i&gt;, allowing the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;Map_Reduce&lt;/span&gt; to be executed using a binary tree of pico-threads, providing significant potential for parallelism.&lt;br /&gt;&lt;br /&gt;A couple of things to notice about the ParaSail implementation.&amp;nbsp; One key feature is that one parameter of an operation may provide type parameters for a later parameter.&amp;nbsp; In this case, the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;Map&lt;/span&gt; parameter has two type parameters, indicated by the use of the "&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;type_name &lt;/span&gt;&lt;b style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;is&lt;/b&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt; interface_name&amp;lt;&amp;gt;&lt;/span&gt;" notation.&amp;nbsp; This says that the type (which must be an instance of module that implements &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;interface_name&lt;/span&gt;) of the corresponding parameter of the actual &lt;i&gt;Map&lt;/i&gt; function is henceforth available as &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;type_name&lt;/span&gt; for use in later parameters and within the body of the operation.&amp;nbsp; It would be possible to make these instead be type parameters of an enclosing module, but it is more natural (and in some cases more powerful) to have the type parameters determined by the actual operation provided.&amp;nbsp; C++ provides a similar capability with template functions, where there is no need to explicitly specify the function template arguments, since the compiler can generally deduce the types from the call on the function, but the type parameters are not generally available outside the template function itself.&amp;nbsp; In ParaSail, the actual operation passed in for a parameter like &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;Map&lt;/span&gt; can determine types that are to be used for later parameters (such as &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;Reduce&lt;/span&gt; and &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;Inputs&lt;/span&gt;) to the module or operation of which they are a parameter.&lt;br /&gt;&lt;br /&gt;A second feature to notice is the use of an anonymous &lt;b&gt;lambda&lt;/b&gt; construct in the call on &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;Map_Reduce&lt;/span&gt; within the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;Test&lt;/span&gt; &lt;b&gt;procedure&lt;/b&gt;, which allows a relatively simple operation (such as squaring) to be created at the point of call.&amp;nbsp; It would also be possible to declare a &lt;b&gt;function&lt;/b&gt; named, for example, &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;Square&lt;/span&gt;,&amp;nbsp; immediately before the call and pass that.&amp;nbsp; Note also that we can pass an operator such as "+" as the actual operation for the formal &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;Reduce&lt;/span&gt; parameter.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8383004232931899216-3207168560731000502?l=parasail-programming-language.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://parasail-programming-language.blogspot.com/feeds/3207168560731000502/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://parasail-programming-language.blogspot.com/2011/02/mapreduce-in-parasail-parameterized.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8383004232931899216/posts/default/3207168560731000502'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8383004232931899216/posts/default/3207168560731000502'/><link rel='alternate' type='text/html' href='http://parasail-programming-language.blogspot.com/2011/02/mapreduce-in-parasail-parameterized.html' title='Map/Reduce in ParaSail; Parameterized operations'/><author><name>Tuck</name><uri>http://www.blogger.com/profile/08866496974237052847</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8383004232931899216.post-8459195031149213571</id><published>2011-02-01T17:28:00.000-05:00</published><updated>2011-02-01T17:28:42.931-05:00</updated><title type='text'>Thinking/Drinking in Parallel in ParaSail</title><content type='html'>As mentioned in an earlier post, we have put up a "Drinking Philosopher's" example in the google group for &lt;b&gt;ParaSail&lt;/b&gt;:&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;a href="http://groups.google.com/group/parasail-programming-language"&gt;http://groups.google.com/group/parasail-programming-language&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;When writing this example, there was only one loop which ended up sequential which seems like it could have been &lt;b&gt;concurrent&lt;/b&gt; -- the one in the Eliminate_Duplicates function:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;b&gt;function&lt;/b&gt; Eliminate_Duplicates(Bottle_Map : Phil_To_Bottle_Map) &lt;br /&gt;      -&amp;gt; Result : Phil_To_Bottle_Map &lt;br /&gt;          &lt;i&gt;{(&lt;b&gt;for&lt;/b&gt; &lt;b&gt;all&lt;/b&gt; P1 &lt;b&gt;in&lt;/b&gt; Philosopher_Index =&amp;gt;&lt;br /&gt;             &lt;b&gt;for&lt;/b&gt; &lt;b&gt;all&lt;/b&gt; P2 &lt;b&gt;in&lt;/b&gt; Philosopher_Index =&amp;gt; &lt;br /&gt;                &lt;b&gt;if&lt;/b&gt; P1 != P2 &lt;b&gt;then&lt;/b&gt; Result[P1] * Result[P2] == [])}&lt;/i&gt;&lt;br /&gt;        &lt;i&gt;// Ensure that there are no duplicates in resulting mapping&lt;/i&gt;&lt;br /&gt;          &lt;i&gt;{(&lt;b&gt;for&lt;/b&gt; &lt;b&gt;all&lt;/b&gt; B &lt;b&gt;in&lt;/b&gt; Bottle_Index =&amp;gt; &lt;b&gt;for&lt;/b&gt; &lt;b&gt;some&lt;/b&gt; P &lt;b&gt;in&lt;/b&gt; Philosopher_Index =&amp;gt;&lt;br /&gt;              B &lt;b&gt;in&lt;/b&gt; Result[P])}&lt;/i&gt;&lt;br /&gt;        &lt;i&gt;// Ensure that every bottle is somewhere&lt;/i&gt;&lt;br /&gt;    &lt;b&gt;is&lt;/b&gt;&lt;br /&gt;        &lt;b&gt;var&lt;/b&gt; Earlier_Bottles : Bottle_Set := [];&lt;br /&gt;&lt;br /&gt;        &lt;b&gt;for&lt;/b&gt; Phil &lt;b&gt;in&lt;/b&gt; Philosopher_Index &lt;b&gt;loop&lt;/b&gt;&lt;br /&gt;            &lt;i&gt;// Remove bottles assigned to earlier philosophers&lt;/i&gt;&lt;br /&gt;            &lt;i&gt;// NOTE: We don't actually need a "forward loop" here&lt;/i&gt;&lt;br /&gt;            &lt;i&gt;//       so long as the loop runs sequentially.&lt;/i&gt;&lt;br /&gt;            &lt;i&gt;//       "Earlier" bottles merely means earlier iterations,&lt;/i&gt;&lt;br /&gt;            &lt;i&gt;//       independent of the order in which they are performed.&lt;/i&gt;&lt;br /&gt;            Result[Phil] := Bottle_Map[Phil] - Earlier_Bottles;&lt;br /&gt;            Earlier_Bottles += Result[Phil];&lt;br /&gt;        &lt;b&gt;end&lt;/b&gt; &lt;b&gt;loop&lt;/b&gt;;&lt;br /&gt;&lt;br /&gt;        &lt;b&gt;if&lt;/b&gt; Count(Earlier_Bottles) != Num_Bottles &lt;b&gt;then&lt;/b&gt;&lt;br /&gt;            &lt;i&gt;// Some bottles not assigned to anyone&lt;/i&gt;&lt;br /&gt;            &lt;i&gt;// Give them to Philosopher 1&lt;/i&gt;&lt;br /&gt;            Result[1] += [1..Num_Bottles] - Earlier_Bottles;&lt;br /&gt;        &lt;b&gt;end&lt;/b&gt; &lt;b&gt;if&lt;/b&gt;;&lt;br /&gt;&lt;br /&gt;    &lt;b&gt;end&lt;/b&gt; &lt;b&gt;function&lt;/b&gt; Eliminate_Duplicates;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;When first written, it was written as a &lt;b&gt;forward&lt;/b&gt; loop, but after looking at the logic, it became clear that there was no particular dependence on order, so making it the default unordered loop seemed preferable.&amp;nbsp; But upon further thought, it seems that there is a straightforward concurrent solution to removing duplicates from a mapping like this.&lt;br /&gt;&lt;br /&gt;The input mapping (Bottle_Map) is a map from philosophers to bottles, where to make it interesting, multiple philosophers are interested in the same bottle.&amp;nbsp; However, to start the simulation going, we want to know where the bottles should start out, so we want a mapping from philosophers to bottles that has no duplicates; that is, a bottle is associated with only one philosopher.&amp;nbsp; As you can see above, we eliminated duplicates by accumulating a set of bottles already assigned (Earlier_Bottles) as we went through the sequence of philosophers, and subtracted this set from each set of bottles in the Bottle_Map as we processed the next philosopher.&amp;nbsp; This is inherently a sequential algorithm (even if the actual sequential order doesn't matter).&lt;br /&gt;&lt;br /&gt;If we want to think in parallel, we might think about a more &lt;i&gt;free for all&lt;/i&gt; approach.&amp;nbsp; Namely, each philosopher tries to grab each of the bottles of interest, and first come, first serve!&amp;nbsp; It turns out with this approach there is one danger: if we end up with a perfectly symmetrical initial state, such that each philosopher ends up with one of the two bottles they want, then the simulation could enter an immediate deadlock.&lt;br /&gt;&lt;br /&gt;In Chandy and Misra's paper, they show that so long as the initial graph of preferences is not cyclic, then the individual steps will preserve the acyclic nature.&amp;nbsp; We accomplished this originally with the sequential loop, where the first philosopher gets all of the bottles they want, the next gets all but those already assigned, and so on.&amp;nbsp; This avoids starting out with a symmetric, deadlock-prone, cyclic preference graph.&lt;br /&gt;&lt;br /&gt;We can accomplish the same thing in a series of concurrent loops using a different approach: we initialize the bottles and bar stools to a default state, and then complete the initialization incrementally, rather than trying to precompute the initial mapping of philosophers to bottles:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&lt;b&gt;var&lt;/b&gt; Bottles : Array&amp;lt;Bottle, Indexed_By=&amp;gt; Bottle_Index&amp;gt; :=&lt;br /&gt;      [Bottle_Index =&amp;gt; Create(1)];&lt;br /&gt;&lt;br /&gt;    &lt;b&gt;var&lt;/b&gt; Bar_Stools : Array&amp;lt;Bar_Stool, Indexed_By=&amp;gt; Philosopher_Index&amp;gt; :=&lt;br /&gt;      [Philosopher_Index =&amp;gt; Create([])];&lt;br /&gt;    &lt;br /&gt;    &lt;b&gt;for&lt;/b&gt; Phil &lt;b&gt;in&lt;/b&gt; Philosopher_Index &lt;b&gt;concurrent loop&lt;/b&gt;&lt;br /&gt;        &lt;b&gt;for&lt;/b&gt; B &lt;b&gt;in&lt;/b&gt; Who_Drinks_What[Phil] &lt;b&gt;concurrent loop&lt;/b&gt;&lt;br /&gt;            Set_Initial_Owner(Bottles[B], Phil);&lt;br /&gt;        &lt;b&gt;end loop&lt;/b&gt;;&lt;br /&gt;    &lt;b&gt;end loop&lt;/b&gt;;&lt;br /&gt;&lt;br /&gt;    &lt;b&gt;for&lt;/b&gt; B &lt;b&gt;in&lt;/b&gt; Bottle_Index &lt;b&gt;concurrent loop&lt;/b&gt;&lt;br /&gt;        Add_Initial_Bottle(Bar_Stools[Initial_Owner(Bottles[B])], B);&lt;br /&gt;    &lt;b&gt;end loop&lt;/b&gt;;&lt;/pre&gt;&lt;br /&gt;The new operations, Set_Initial_Owner/Initial_Owner, and Add_Initial_Bottle, would have to be added to the Bottle and Bar_Stool interfaces, respectively.  Set_Initial_Owner would update the bottle's Who_Gets_It field only if the new owner had a higher Philosopher_Index, thereby ensuring the acyclic preference graph.  Originally initializing the Who_Gets_It to a default value of 1 ensures that Philosopher 1 ends up with any bottles of no interest to anyone.  The Initial_Owner function would simply return the value of Who_Gets_It for the given Bottle, which, at the point of call, is the Philosopher with the highest index with an interest in the bottle.  The Add_Initial_Bottle operation would then add the given bottle to the Used_Bottles set of the Bar_Stool associated with that highest-numbered Philosopher.&lt;br /&gt;&lt;br /&gt;Clearly a programmer's goal with a language like ParaSail is to minimize the amount of sequential code, so that as the number of available processors goes up, the program will have the parallelism to take advantage of them.  Having primitives which make it easy and safe to do things concurrently helps, but the programmer will still have to shift their thinking a bit to achieve the full potential benefit.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8383004232931899216-8459195031149213571?l=parasail-programming-language.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://parasail-programming-language.blogspot.com/feeds/8459195031149213571/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://parasail-programming-language.blogspot.com/2011/02/thinkingdrinking-in-parallel-in.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8383004232931899216/posts/default/8459195031149213571'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8383004232931899216/posts/default/8459195031149213571'/><link rel='alternate' type='text/html' href='http://parasail-programming-language.blogspot.com/2011/02/thinkingdrinking-in-parallel-in.html' title='Thinking/Drinking in Parallel in ParaSail'/><author><name>Tuck</name><uri>http://www.blogger.com/profile/08866496974237052847</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8383004232931899216.post-2463658470035948525</id><published>2011-01-27T10:55:00.000-05:00</published><updated>2011-01-27T10:55:40.636-05:00</updated><title type='text'>Philosopher examples</title><content type='html'>We have just posted two new examples to the &lt;b&gt;ParaSail&lt;/b&gt; Google group -- a very simple &lt;i&gt;dining philosophers&lt;/i&gt; example, and a more interesting &lt;i&gt;drinking philosophers&lt;/i&gt; example, based on Chandy and Misra's 1984 &lt;i&gt;ACM TOPLAS&lt;/i&gt; paper.&amp;nbsp; The &lt;i&gt;drinking philosophers&lt;/i&gt; example was more challenging as it required orchestrating the use of two different &lt;b&gt;concurrent&lt;/b&gt; data structures, one representing a philosopher's &lt;i&gt;bar stool,&lt;/i&gt; and one representing the &lt;i&gt;bottles&lt;/i&gt; being shared between the philosophers.&lt;br /&gt;&lt;br /&gt;To see these examples, visit &lt;a href="http://groups.google.com/group/parasail-programming-language"&gt;ParaSail Google Group.&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8383004232931899216-2463658470035948525?l=parasail-programming-language.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://parasail-programming-language.blogspot.com/feeds/2463658470035948525/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://parasail-programming-language.blogspot.com/2011/01/philosopher-examples.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8383004232931899216/posts/default/2463658470035948525'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8383004232931899216/posts/default/2463658470035948525'/><link rel='alternate' type='text/html' href='http://parasail-programming-language.blogspot.com/2011/01/philosopher-examples.html' title='Philosopher examples'/><author><name>Tuck</name><uri>http://www.blogger.com/profile/08866496974237052847</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8383004232931899216.post-8868502889084008239</id><published>2011-01-04T09:26:00.000-05:00</published><updated>2011-01-04T09:26:38.708-05:00</updated><title type='text'>CUDA, OpenCL, Cilk, and ParaSail</title><content type='html'>NVIDIA, AMD, and Intel have all gotten interested in parallel programming languages over the past few years, and for good reason.&amp;nbsp; It is clear that all programmers will have to start learning how to take advantage of parallelism if they expect their programs to continue to benefit from Moore's law, with its wonderful doubling of computing power every two years.&amp;nbsp; And chips that make it easier to take advantage of parallelism will be the more successful chips.&amp;nbsp;&lt;br /&gt;&lt;br /&gt;NVIDIA has been championing &lt;b&gt;&lt;i&gt;CUDA&lt;/i&gt;&lt;/b&gt; as the way to use their GPUs for general purpose parallel processing (&lt;i&gt;GPGPU&lt;/i&gt;), though they have also been part of the group designing &lt;b&gt;&lt;i&gt;OpenCL&lt;/i&gt;&lt;/b&gt;, which is the more hardware-independent approach first developed by Apple and now being standardized by the Khronos group.&amp;nbsp; AMD (after swallowing ATI) started with &lt;b&gt;&lt;i&gt;CTM&lt;/i&gt;&lt;/b&gt; (Close to Metal) and some other approaches, but now seem to be putting most of their energy behind OpenCL for GPGPU programming.&amp;nbsp; Intel has been encouraging a number of different approaches, including &lt;i&gt;&lt;b&gt;Cilk&lt;/b&gt;&lt;/i&gt;, Threading Building Blocks (&lt;i&gt;&lt;b&gt;TBB&lt;/b&gt;&lt;/i&gt;), Concurrent Collections (&lt;i&gt;&lt;b&gt;CnC&lt;/b&gt;&lt;/i&gt;), etc., and they are part of the OpenCL effort as well.&lt;br /&gt;&lt;br /&gt;Cilk and OpenCL seem to be emerging as two important, rather distinct approaches to parallel programming.&amp;nbsp; Cilk makes it easy to spawn &lt;i&gt;threads&lt;/i&gt; off to compute an arbitrary &lt;i&gt;expression&lt;/i&gt;, and then uses a set of &lt;i&gt;worker&lt;/i&gt; processes to service the threads, using the approach we discussed in an earlier post, where threads spawned by a given worker are serviced &lt;i&gt;LIFO&lt;/i&gt;, but when a worker runs out of threads, it &lt;i&gt;steals&lt;/i&gt; from other workers using a &lt;i&gt;FIFO&lt;/i&gt; strategy.&amp;nbsp; OpenCL, on the other hand, is focused on data parallelism, where many data items are all being manipulated in nearly the same way.&amp;nbsp; It is roughly a &lt;i&gt;SIMD&lt;/i&gt; (Single Instruction Multiple Data) approach, though some variation in control flow is permitted, meaning that it is somewhat closer to the &lt;i&gt;SPMD&lt;/i&gt; (Single Program, Multiple Data) approach fostered by the Connection Machine folks.&amp;nbsp; In OpenCL (and CUDA), the per-data-item code is bundled into a &lt;i&gt;kernel&lt;/i&gt;, which is essentially a function that operates on a single data item in a large array or stream of such items.&lt;br /&gt;&lt;br /&gt;So how does this relate to &lt;b&gt;ParaSail&lt;/b&gt;?&amp;nbsp; In some ways, Cilk and OpenCL can be seen as lower-level languages, where the programmer has to worry about identifying particularly places where threads should be spawned (in Cilk), or worry about extracting kernels from code that operates on an array or stream (in OpenCL).&amp;nbsp; ParaSail on the other hand is focused on expressing the algorithm at a relatively high level with pervasive opportunities for parallelism, presuming the compiler or run-time support routines can identify how best to map all of the opportunities for parallelism on to the underlying parallel hardware.&lt;br /&gt;&lt;br /&gt;One of the key advantages that ParaSail provides is that there is no hidden aliasing, unlike in C, C++, Java, etc., where aliasing is everywhere.&amp;nbsp; (Cilk and OpenCL are both &lt;i&gt;piggy-backed&lt;/i&gt; on C/C++; various threading APIs are available to Java, C#, Python, etc.)&amp;nbsp; This makes it dramatically easier for a compiler or run-time to automatically partition computations into pieces to be executed in parallel.&amp;nbsp; Furthermore, the ParaSail compiler detects all race conditions (and various other problems) at compile time, has no exceptions, allows memory to be partitioned into non-overlapping regions, etc., which simplify both the programmer's model and the process of automatic parallelization.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8383004232931899216-8868502889084008239?l=parasail-programming-language.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://parasail-programming-language.blogspot.com/feeds/8868502889084008239/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://parasail-programming-language.blogspot.com/2011/01/cuda-opencl-cilk-and-parasail.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8383004232931899216/posts/default/8868502889084008239'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8383004232931899216/posts/default/8868502889084008239'/><link rel='alternate' type='text/html' href='http://parasail-programming-language.blogspot.com/2011/01/cuda-opencl-cilk-and-parasail.html' title='CUDA, OpenCL, Cilk, and ParaSail'/><author><name>Tuck</name><uri>http://www.blogger.com/profile/08866496974237052847</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8383004232931899216.post-7049705541716952895</id><published>2010-12-17T12:17:00.005-05:00</published><updated>2010-12-17T17:58:47.406-05:00</updated><title type='text'>Parallel Quicksort in ParaSail and "slicing"</title><content type='html'>Quicksort is a classic "divide-and-conquer" algorithm, and lends itself naturally to parallelization.&amp;nbsp; However, unlike some of the other algorithms we have discussed in past postings, it is updating rather than merely walking a data structure.&amp;nbsp; This means that we need a way to safely partition the array to be sorted so that the &lt;b&gt;ParaSail&lt;/b&gt; compiler knows that the threads are manipulating non-overlapping parts of the array, so it can be certain there are no race conditions possible.&lt;br /&gt;&lt;br /&gt;In several languages there is the notion of an array &lt;i&gt;slice&lt;/i&gt;.&amp;nbsp; In particular, in Fortran and Ada there is built-in syntax for selecting a contiguous part of an array.&amp;nbsp; In newer versions of Fortran this can be done on multi-dimensional arrays.&amp;nbsp; In Ada slicing is limited to single-dimensional arrays.&amp;nbsp; In both Fortran and Ada, array slices are updatable, that is they effectively represent a &lt;i&gt;view&lt;/i&gt; of the underlying array.&amp;nbsp; APL (not surprisingly!) has all of these capabilities and more.&amp;nbsp; In many other languages there are operations for selecting a slice of a string (and in some cases arrays), but these are generally not updatable views, and hence cannot be used on the left-hand side of an assignment nor be passed as an &lt;i&gt;in out&lt;/i&gt; parameter.&amp;nbsp; In some cases there are explicit "replace-slice" operations which do allow for updating a slice of an array.&lt;br /&gt;&lt;br /&gt;In any case, in ParaSail, because we expect the compiler to catch &lt;i&gt;race-conditions&lt;/i&gt; at compile-time, operations that return a view of a part of an object need to have well-defined properties so the compiler can correctly determine whether two different views have any overlap (i.e. are potentially &lt;i&gt;aliased&lt;/i&gt;).&amp;nbsp; The simplest solution seems to be to recognize a &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;"slicing"&lt;/span&gt; &lt;b&gt;operator&lt;/b&gt;, similar to the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;"indexing"&lt;/span&gt; &lt;b&gt;operator&lt;/b&gt;.&amp;nbsp; A &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;"slicing"&lt;/span&gt; &lt;b&gt;operator&lt;/b&gt; would take an &lt;i&gt;indexable&lt;/i&gt; container, and then one or more operands at least one of which is an &lt;i&gt;interval&lt;/i&gt; or a &lt;i&gt;set&lt;/i&gt;, and return a view of the container that represents the subset of components identified by the operand(s).&amp;nbsp; For example, this might be an &lt;b&gt;interface&lt;/b&gt; for a One_Dim_Array with both &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;"indexing"&lt;/span&gt; and &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;"slicing"&lt;/span&gt; &lt;b&gt;operators&lt;/b&gt;&lt;b&gt;&lt;/b&gt;:&lt;br /&gt;&lt;pre&gt;&lt;b&gt;interface&lt;/b&gt; One_Dim_Array&lt;br /&gt;&amp;nbsp; &amp;lt;Element_Type is Assignable&amp;lt;&amp;gt;;&lt;br /&gt;&amp;nbsp;&amp;nbsp; Index_Type is Discrete&amp;lt;&amp;gt;&amp;gt; &lt;b&gt;is&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &lt;b&gt;function&lt;/b&gt; Bounds(A : One_Dim_Array) -&amp;gt; Interval&amp;lt;Index_Type&amp;gt;; &lt;br /&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &lt;b&gt;function&lt;/b&gt; Create(Bounds : Interval&amp;lt;Index_type&amp;gt;)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; -&amp;gt; One_Dim_Array &lt;i&gt;{Bounds(Create) == Bounds}&lt;/i&gt;;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;b&gt;operator&lt;/b&gt; "indexing"(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; A : &lt;b&gt;ref&lt;/b&gt; One_Dim_Array;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Index : Index_Type &lt;i&gt;{Index in Bounds(A)}&lt;/i&gt;)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; -&amp;gt; &lt;b&gt;ref&lt;/b&gt; Element_Type;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;b&gt;operator&lt;/b&gt; "slicing"(&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; A : &lt;b&gt;ref&lt;/b&gt; One_Dim_Array;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Slice : Interval&amp;lt;Index_Type&amp;gt; &lt;i&gt;{Is_Subset(Slice, Bounds(A))}&lt;/i&gt;)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; -&amp;gt; &lt;b&gt;ref&lt;/b&gt; Result: One_Dim_Array &lt;i&gt;{Bounds(Result) == Slice}&lt;/i&gt;;&lt;br /&gt;&amp;nbsp; &amp;nbsp; ... &lt;br /&gt;&lt;b&gt;end interface&lt;/b&gt; One_Dim_Array; &lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;As with the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;"indexing"&lt;/span&gt; operator, the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;"slicing"&lt;/span&gt; operator would be invoked by using &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;A[...]&lt;/span&gt; notation, but where one or more of the operands inside the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;[]&lt;/span&gt; would be intervals or sets.&amp;nbsp; The ParaSail compiler would impose requirements on implementations of &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;"indexing"&lt;/span&gt; and &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;"slicing"&lt;/span&gt; operators.&amp;nbsp; For a given &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;"indexing"&lt;/span&gt; operator, if the operands are different in two different calls, then the resulting elements must be distinct.&amp;nbsp; For a given &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;"slicing"&lt;/span&gt; operator, if the operands are non-overlapping sets or intervals, then the resulting slices must be non-overlapping.&amp;nbsp;&amp;nbsp; Note that the implementor of the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;"slicing"&lt;/span&gt; operator can decide whether the bounds of the result correspond to those of the selecting interval, or &lt;i&gt;slide&lt;/i&gt; back to always starting at zero or one.&amp;nbsp; In the above example, the bounds correspond to the original indices of the selected elements, as indicated by the postcondition on the &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;"slicing"&lt;/span&gt; operator.&amp;nbsp; In an interface designed for string manipulation, it might be more convenient for the slice to have bounds starting at zero or one.&lt;br /&gt;&lt;br /&gt;Note that if there are multiple &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;"indexing"&lt;/span&gt; operators, or multiple &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;"slicing"&lt;/span&gt; operators for the same type, then they are presumed to be creating potentially overlapping elements or views, as they presumably represent different indexing schemes into the same data structure.&amp;nbsp; For example, a hash-table might be indexable both by the key and by some unique internal index.&amp;nbsp; That is, there is no guarantee that A["key"] and A[35] are unaliased just because "key" and 35 are distinct values, presuming these represent invocations of different &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;"indexing"&lt;/span&gt; operators defined for the same indexable container.&lt;br /&gt;&lt;br /&gt;Note that in all languages, you can achieve the equivalent of slicing by passing in the entire array and the bounds for the sub-array of interest.&amp;nbsp; This would however not allow the compiler to determine as easily whether two different calls are manipulating non-overlapping slices by looking only at the call sites.&amp;nbsp; A goal with ParaSail is that the compiler can identify any possible race-conditions by looking only at call sites and associated pre- and postconditions.&amp;nbsp; This argues for having explicit ways of indicating in a precondition or postcondition what parts of an object are read, what parts are updated, and what parts are not referenced at all.&amp;nbsp; Bu this probably comes back to being able to specify slices of a container, if only in annotations.&amp;nbsp; &lt;br /&gt;&lt;br /&gt;In any case, given the above notion of &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;"slicing"&lt;/span&gt; operators, we are now in a position to write our parallel Quicksort:&lt;br /&gt;&lt;pre&gt;&lt;b&gt;interface&lt;/b&gt; Sorting&amp;lt;One_Dim_Array&amp;lt;&amp;gt;&amp;gt; &lt;b&gt;is&lt;/b&gt;&lt;br /&gt;    &lt;b&gt;procedure&lt;/b&gt; Quicksort(Arr : &lt;b&gt;ref var&lt;/b&gt; One_Dim_Array;&lt;br /&gt;       &lt;b&gt;function&lt;/b&gt; Before(Left, Right : One_Dim_Array::Element_Type) &lt;br /&gt;         -&amp;gt; Boolean &lt;b&gt;is&lt;/b&gt; "&amp;lt;");&lt;br /&gt;          &lt;i&gt;// Sort Arr according to the sorting function "Before" which returns&lt;br /&gt;          // True if Left must appear before Right in the sorted order.&lt;br /&gt;          // Before returns False if Left = Right.&lt;/i&gt;&lt;br /&gt;&lt;b&gt;end interface&lt;/b&gt; Sorting;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;class&lt;/b&gt; Sorting &lt;b&gt;is&lt;br /&gt;  exports&lt;br /&gt;    procedure&lt;/b&gt; Quicksort(Arr : &lt;b&gt;ref var&lt;/b&gt; One_Dim_Array;&lt;br /&gt;       &lt;b&gt;function&lt;/b&gt; Before(Left, Right : One_Dim_Array::Element_Type) &lt;br /&gt;         -&amp;gt; Boolean &lt;b&gt;is&lt;/b&gt; "&amp;lt;")&lt;br /&gt;    &lt;b&gt;is&lt;/b&gt;&lt;br /&gt;&lt;i&gt;        // Handle short arrays directly.  Partition longer arrays.&lt;/i&gt;&lt;br /&gt;        &lt;b&gt;case&lt;/b&gt; Length(Arr) &lt;b&gt;of&lt;/b&gt;&lt;br /&gt;          [0..1] =&amp;gt; &lt;b&gt;return&lt;/b&gt;;&lt;br /&gt;          &lt;br /&gt;          [2] =&amp;gt; &lt;br /&gt;               &lt;b&gt;if&lt;/b&gt; Before(Arr[Arr.Last], Arr[Arr.First]) &lt;b&gt;then&lt;/b&gt;&lt;br /&gt;                 &lt;i&gt;  // Swap elements&lt;/i&gt;&lt;br /&gt;                   Arr[Arr.First] :=: Arr[Arr.Last];&lt;br /&gt;               &lt;b&gt;end if&lt;/b&gt;;&lt;br /&gt;               &lt;b&gt;return&lt;/b&gt;;&lt;br /&gt;               &lt;br /&gt;          [..] =&amp;gt;&lt;br /&gt;               &lt;i&gt;// Partition array&lt;/i&gt;&lt;br /&gt;               &lt;b&gt;const&lt;/b&gt; Mid := Arr[Arr.First + Length(Arr)/2];&lt;br /&gt;               &lt;b&gt;var&lt;/b&gt; Left : Index_Type := Arr.First;&lt;br /&gt;               &lt;b&gt;var&lt;/b&gt; Right : Index_Type := Arr.Last;&lt;br /&gt;               &lt;b&gt;until&lt;/b&gt; Left &amp;gt; Right &lt;b&gt;loop&lt;/b&gt;&lt;br /&gt;                 &lt;b&gt;var&lt;/b&gt; New_Left : Index_Type := Right+1;&lt;br /&gt;                 &lt;b&gt;var&lt;/b&gt; New_Right : Index_Type := Left-1;&lt;br /&gt;                 &lt;b&gt;block&lt;/b&gt;&lt;br /&gt;&lt;i&gt;                   // Find item in left half to swap&lt;/i&gt;&lt;br /&gt;                   &lt;b&gt;for&lt;/b&gt; I &lt;b&gt;in&lt;/b&gt; Left .. Right &lt;b&gt;forward loop&lt;/b&gt;&lt;br /&gt;                       &lt;b&gt;if not&lt;/b&gt; Before(Arr[I], Mid) &lt;b&gt;then&lt;/b&gt;&lt;br /&gt;&lt;i&gt;                           // Found an item that can go into right partitition&lt;/i&gt;&lt;br /&gt;                           New_Left := I;&lt;br /&gt;                           &lt;b&gt;if&lt;/b&gt; Before(Mid, Arr[I]) &lt;b&gt;then&lt;/b&gt;&lt;br /&gt;&lt;i&gt;                               // Found an item that *must* go into right part&lt;/i&gt;&lt;br /&gt;                               &lt;b&gt;exit loop&lt;/b&gt;;&lt;br /&gt;                           &lt;b&gt;end if&lt;/b&gt;;&lt;br /&gt;                       &lt;b&gt;end if&lt;/b&gt;;&lt;br /&gt;                   &lt;b&gt;end loop&lt;/b&gt;;&lt;br /&gt;                 ||  &lt;br /&gt;&lt;i&gt;                   // Find item in right half to swap&lt;/i&gt;&lt;br /&gt;                   &lt;b&gt;for&lt;/b&gt; J &lt;b&gt;in&lt;/b&gt; Left .. Right &lt;b&gt;reverse loop&lt;/b&gt;&lt;br /&gt;                       &lt;b&gt;if not&lt;/b&gt; Before(Mid, Arr[J]) &lt;b&gt;then&lt;/b&gt;&lt;br /&gt;&lt;i&gt;                           // Found an item that can go into left partitition&lt;/i&gt;&lt;br /&gt;                           New_Right := J;&lt;br /&gt;                           &lt;b&gt;if&lt;/b&gt; Before(Arr[J], Mid) &lt;b&gt;then&lt;/b&gt;&lt;br /&gt;&lt;i&gt;                               // Found an item that *must* go into left part&lt;/i&gt;&lt;br /&gt;                               &lt;b&gt;exit loop&lt;/b&gt;;&lt;br /&gt;                           &lt;b&gt;end if&lt;/b&gt;;&lt;br /&gt;                       &lt;b&gt;end if&lt;/b&gt;;&lt;br /&gt;                   &lt;b&gt;end loop&lt;/b&gt;;&lt;br /&gt;                 &lt;b&gt;end block&lt;/b&gt;;&lt;br /&gt;                 &lt;br /&gt;                 &lt;b&gt;if&lt;/b&gt; New_Left &amp;gt; New_Right &lt;b&gt;then&lt;/b&gt;&lt;br /&gt;&lt;i&gt;                     // Nothing more to swap&lt;/i&gt;&lt;br /&gt;&lt;i&gt;                     // Exit loop and recurse on two partitions&lt;/i&gt;&lt;br /&gt;                     Left := New_Left;&lt;br /&gt;                     Right := New_Right;&lt;br /&gt;                     &lt;b&gt;exit loop;&lt;/b&gt;&lt;br /&gt;                 &lt;b&gt;end if&lt;/b&gt;;&lt;br /&gt;                 &lt;br /&gt;&lt;i&gt;                 // Swap items&lt;/i&gt;&lt;br /&gt;                 Arr[New_Left] :=: Arr[New_Right];&lt;br /&gt;                 &lt;br /&gt;&lt;i&gt;                 // continue looking for items to swap&lt;/i&gt;&lt;br /&gt;                 Left := New_Left + 1;&lt;br /&gt;                 Right := New_Right - 1;&lt;br /&gt;               &lt;b&gt;end loop&lt;/b&gt;;&lt;br /&gt;               &lt;br /&gt;               &lt;i&gt;// At this point, "Right" is right end of left partition&lt;br /&gt;               // and "Left" is left end of right partition&lt;br /&gt;               // and the partitions don't overlap&lt;br /&gt;               // and neither is the whole array&lt;br /&gt;               // and everything in the left partition can precede Mid&lt;br /&gt;               // and everything in the right partition can follow Mid&lt;br /&gt;               // and everything between the partitions is equal to Mid.&lt;br /&gt;               {Left &amp;gt; Right;&lt;br /&gt;                Right &amp;lt; Arr.Last;&lt;br /&gt;                Left &amp;gt; Arr.First;&lt;br /&gt;                (for all I in Arr.First .. Right : not Before(Mid, Arr[I]));&lt;br /&gt;                (for all J in Left .. Arr.Last : not Before(Arr[J], Mid));&lt;br /&gt;                (for all K in Right+1 .. Left-1 : &lt;br /&gt;                  not Before(Mid, Arr[K]) and not Before(Arr[K], Mid))}&lt;/i&gt;&lt;br /&gt;               &lt;br /&gt;&lt;i&gt;               // Recurse on two halves&lt;/i&gt;&lt;br /&gt;               &lt;b&gt;block&lt;/b&gt;&lt;br /&gt;                   Quicksort(Arr[Arr.First .. Right], Before);&lt;br /&gt;                 ||&lt;br /&gt;                   Quicksort(Arr[Left .. Arr.Last], Before);&lt;br /&gt;        &lt;b&gt;       end block;&lt;br /&gt;        end case&lt;/b&gt;;        &lt;br /&gt;   &lt;b&gt;end procedure&lt;/b&gt; Quicksort;&lt;br /&gt;&lt;b&gt;end class&lt;/b&gt; Sorting;&lt;/pre&gt;We have used slicing as part of the recursion.  Because the compiler can prove &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;Left &amp;gt; Right&lt;/span&gt;, there is no overlap between the two slices, and hence no race condition.&amp;nbsp; It turns out that in ParaSail we could have written this without explicit recursion by using the &lt;b&gt;continue loop with ...&lt;/b&gt; construct.  We will save that for a later posting.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8383004232931899216-7049705541716952895?l=parasail-programming-language.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://parasail-programming-language.blogspot.com/feeds/7049705541716952895/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://parasail-programming-language.blogspot.com/2010/12/parallel-quicksort-in-parasail-and.html#comment-form' title='10 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8383004232931899216/posts/default/7049705541716952895'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8383004232931899216/posts/default/7049705541716952895'/><link rel='alternate' type='text/html' href='http://parasail-programming-language.blogspot.com/2010/12/parallel-quicksort-in-parasail-and.html' title='Parallel Quicksort in ParaSail and &quot;slicing&quot;'/><author><name>Tuck</name><uri>http://www.blogger.com/profile/08866496974237052847</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>10</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8383004232931899216.post-3103331581516700835</id><published>2010-12-03T13:47:00.000-05:00</published><updated>2010-12-03T13:47:10.036-05:00</updated><title type='text'>Deterministic parallelism and aliasing in ParaSail</title><content type='html'>There is growing interest in parallelization approaches that provide deterministic results.&amp;nbsp; See for example Deterministic Parallel Java.&amp;nbsp; In &lt;b&gt;ParaSail&lt;/b&gt;, we have a somewhat different model.&amp;nbsp; Determinism should be provided for computations when it makes sense, but when the program is interactive or part of a real-time system, then clearly the environment is dynamic and time-dependent, and the notion of determinism becomes less relevant, and arguably not even desirable.&amp;nbsp;&lt;br /&gt;&lt;br /&gt;It turns out that it is easy to know when non-determinism might be entering the execution of a ParaSail program.&amp;nbsp; It occurs only as a result of operations on &lt;b&gt;concurrent&lt;/b&gt; objects.&amp;nbsp; Because ParaSail eliminates all race-conditions associated with non-concurrent objects at compile time, the results of a ParaSail program that manipulates only non-concurrent objects are inherently deterministic.&amp;nbsp; However, should the programmer decide to use a &lt;b&gt;concurrent&lt;/b&gt; object, then the order in which operations on the concurrent object are performed by concurrent threads is unspecified, though the programmer can control it to some extent by specifying &lt;i&gt;dequeue conditions&lt;/i&gt; when the operand is marked as &lt;b&gt;queued&lt;/b&gt;.&amp;nbsp; (See blog posting &lt;a href="http://parasail-programming-language.blogspot.com/2009/11/parasail-concurrent-interfaces.html"&gt;parasail-concurrent-interfaces.html&lt;/a&gt; for more information on &lt;b&gt;queued&lt;/b&gt; operands.)&lt;br /&gt;&lt;br /&gt;Minimizing use of &lt;b&gt;concurrent&lt;/b&gt; objects is generally a good idea anyway for performance reasons, as there is inevitably more overhead involved in coordinating access to a shared object, even when using &lt;i&gt;lock-free&lt;/i&gt; approaches.&amp;nbsp; But how can a group of threads work in parallel to build up a large data structure, without the data structure itself being a &lt;b&gt;concurrent&lt;/b&gt; object?&amp;nbsp; The normal answer to such a question is &lt;i&gt;divide and conquer&lt;/i&gt;.&amp;nbsp;&lt;br /&gt;&lt;br /&gt;What does &lt;i&gt;divide and conquer&lt;/i&gt; really mean in ParaSail terms?&amp;nbsp; That means that a data structure needs to be conceptually divided up into non-overlapping parts and passed out to multiple threads for manipulation.&amp;nbsp; In ParaSail, a function can return a reference to a part of an object passed by reference as an input to the function.&amp;nbsp; However, the compiler needs to understand the aliasing implications of that, since in ParaSail, the compiler disallows race-conditions, which implies it must understand all aliasing related to non-concurrent objects at compile-time.&amp;nbsp; If two potentially concurrent computations are both updating parts of the same non-concurrent object, then the compiler must be able to convince itself that the two parts are non-overlapping (i.e. not aliased with one another).&lt;br /&gt;&lt;br /&gt;Because there are no (re)assignable pointers in ParaSail, there are no cycles in data structures, so it is clear that Obj.Left and Obj.Right do not overlap.&amp;nbsp; On the other hand, when dealing with generalized containers, it is more difficult to know whether Container[X] and Container[Y] overlap, and even more complex when we are calling arbitrary functions that happen to return a reference to part of their input parameter, such as Lower_Left(Matrix) and Upper_Right(Matrix).&amp;nbsp; Clearly the programmer needs some way in a postcondition of such a function to convey the aliasing properties of the result.&lt;br /&gt;&lt;br /&gt;ParaSail has a built-in, primitive, &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;Basic_Array&lt;/span&gt; &lt;b&gt;interface&lt;/b&gt;.&amp;nbsp; The compiler has built-in knowledge that, given an object BA based on the Basic_Array interface, BA[X] does not alias with BA[Y] if X != Y.&amp;nbsp; So one way to describe the "part" of a container that is included within the result of calling a function like "Lower_Left" is to describe the set of underlying array indices associated with the elements of the container that can be referenced from the result of Lower_Left.&amp;nbsp; More generally we can see that there is a set of primitive subcomponents accessible via any reference to a part of a container, and the aliasing problem comes down to proving that the subcomponent set from one reference does not overlap with the subcomponent set from some other reference.&amp;nbsp; This all implies that ParaSail needs a notation for identifying the set of accessible subcomponents of a reference, and a built-in &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;Subcomponent_Set&lt;/span&gt; &lt;b&gt;interface&lt;/b&gt; for specifying the values and the relationships between these subcomponent sets.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8383004232931899216-3103331581516700835?l=parasail-programming-language.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://parasail-programming-language.blogspot.com/feeds/3103331581516700835/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://parasail-programming-language.blogspot.com/2010/12/deterministic-parallelism-and-aliasing.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8383004232931899216/posts/default/3103331581516700835'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8383004232931899216/posts/default/3103331581516700835'/><link rel='alternate' type='text/html' href='http://parasail-programming-language.blogspot.com/2010/12/deterministic-parallelism-and-aliasing.html' title='Deterministic parallelism and aliasing in ParaSail'/><author><name>Tuck</name><uri>http://www.blogger.com/profile/08866496974237052847</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8383004232931899216.post-8430355952861955011</id><published>2010-11-01T16:43:00.001-04:00</published><updated>2010-11-24T17:59:56.400-05:00</updated><title type='text'>Type conversion in ParaSail</title><content type='html'>Allowing for user-defined type conversion is complex, as it is an NxN problem, where you want to allow conversion of N different types to each other, and each pair might involve a different set of operations. &lt;b&gt;ParaSail&lt;/b&gt; addresses this problem in the following ways:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Allows use of the [[ ... ]] operation, which converts the operand to a universal type.&amp;nbsp;&amp;nbsp;&lt;/li&gt;&lt;ul&gt;&lt;li&gt;The user defines which universal type(s) a given type converts to by defining the "to_univ" operator(s).&amp;nbsp; Once the value has been converted to a universal type, it will be implicitly converted to any other type which defines a "from_univ" operator from that same universal type.&amp;nbsp;&amp;nbsp;&lt;/li&gt;&lt;ul&gt;&lt;li&gt;Using a prefix can disambiguate if necessary:&amp;nbsp; &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;T2::[[T1_Obj]]&lt;/span&gt; will convert T1_Obj first to a universal type using T1's "from_univ" operator, and then to T2 using T2's "to_univ" operator.&lt;/li&gt;&lt;/ul&gt;&lt;/ul&gt;&lt;li&gt;&amp;nbsp;Allows use of the target type's name as a function name.&lt;/li&gt;&lt;ul&gt;&lt;li&gt;This will convert between two types that are &lt;i&gt;structurally equivalent&lt;/i&gt; (that is, the same module parameters were used in their defining instantiation), but which were distinguished by one or both being defined as &lt;b&gt;new&lt;/b&gt;.&amp;nbsp; For example:&lt;/li&gt;&lt;ul&gt;&lt;li&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;type T1 is new Vector&amp;lt;Integer&amp;lt;&amp;gt;&amp;gt;&lt;/span&gt; and &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;type T2 is new Vector&amp;lt;Integer&amp;lt;&amp;gt;&amp;gt;&lt;/span&gt; define two distinct types because of the use of &lt;b&gt;new&lt;/b&gt;, but &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;T2(T1_Obj)&lt;/span&gt; and &lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;T1(T2_Obj)&lt;/span&gt; will convert T1_Obj to type T2, and T2_Obj to type T1, respectively.&lt;/li&gt;&lt;/ul&gt;&lt;li&gt;The target type's name can also convert an object from some source type if the user defines a "convert" operator for either of the two types, and this operator's input and output parameter types match the source and target of the conversion.&amp;nbsp; Note that this matching might be thanks to the input or output formal being itself parameterized.&amp;nbsp; For example, the interface Int_Vector below provides a "convert" operator that converts to any other instance of Int_Vector:&lt;/li&gt;&lt;/ul&gt;&lt;/ul&gt;&lt;pre&gt;            interface Int_Vector&amp;lt;Element is Integer&amp;lt;&amp;gt;&amp;gt; is&lt;br /&gt;               ...&lt;br /&gt;               operator "convert"(X : Int_Vector) &lt;br /&gt;                 -&amp;gt; Result_Type is&lt;br /&gt;                      Int_Vector&amp;lt;Target_Element is Integer&amp;lt;&amp;gt;&amp;gt;;&lt;br /&gt;            end interface Int_Vector;&lt;br /&gt;&lt;/pre&gt;These capabilities seem to provide enough flexibility for the user to define the desired explicit conversion functions.  Note that the only implicit conversion in ParaSail is from a universal type to a type with an appropriate "from_univ" operator.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8383004232931899216-8430355952861955011?l=parasail-programming-language.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://parasail-programming-language.blogspot.com/feeds/8430355952861955011/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://parasail-programming-language.blogspot.com/2010/11/type-conversion-in-parasail.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8383004232931899216/posts/default/8430355952861955011'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8383004232931899216/posts/default/8430355952861955011'/><link rel='alternate' type='text/html' href='http://parasail-programming-language.blogspot.com/2010/11/type-conversion-in-parasail.html' title='Type conversion in ParaSail'/><author><name>Tuck</name><uri>http://www.blogger.com/profile/08866496974237052847</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8383004232931899216.post-5910478988071182505</id><published>2010-11-01T11:01:00.000-04:00</published><updated>2010-11-01T11:01:20.033-04:00</updated><title type='text'>A virtual machine for ParaSail with picothread scheduling</title><content type='html'>As we have worked toward having an initial compiler/interpreter for &lt;b&gt;ParaSail&lt;/b&gt;, we have decided to define a &lt;i&gt;ParaSail Virtual Machine&lt;/i&gt; (PSVM) which will support the kind of very-light-weight threading structure (&lt;i&gt;picothreading&lt;/i&gt;) needed to be able to evaluate small constructs, like parameters in parallel.&amp;nbsp; We have decided to turn each ParaSail operation into a single PSVM &lt;i&gt;Routine,&lt;/i&gt; even if its execution will involve multiple threads executing bits and pieces of the code for the operation.  Each PSVM routine is identified by a unique index, the &lt;i&gt;routine index, &lt;/i&gt;and is represented by a routine &lt;i&gt;header&lt;/i&gt; and a sequence of PSVM &lt;i&gt;instructions.&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;The ParaSail Virtual Machine instructions use relatively conventional &lt;i&gt;addressing modes&lt;/i&gt; to refer to operands in memory.  Memory is presumed to be organized into &lt;i&gt;areas,&lt;/i&gt; each area being a contiguous sequence of 64-bit words.  While executing, a PSVM routine has access to the following areas:&lt;br /&gt;&lt;dl&gt;&lt;dt&gt;Parameter_Area&lt;/dt&gt;&lt;dd&gt;An area for input and output parameters.  Output parameters, if any, come first, followed by input parameters.  Parameters may be a single 64-bit value, or may be a 64-bit pointer to a larger object.&lt;/dd&gt;&lt;dt&gt;Local_Area&lt;/dt&gt;&lt;dd&gt;An area for storing local variables, and parameter lists being built up to pass as a Parameter_Area to a called routine.  The first word of a local area is a link to the local area of the enclosing block or operation, in the presence of nesting.  This sort of link is generally called a &lt;i&gt;static link.&lt;/i&gt;  The second word of a local area is a link to the associated parameter area.&lt;/dd&gt;&lt;dt&gt;Type_Area&lt;/dt&gt;&lt;dd&gt;Each type, which is an instance of a module, is represented by an area containing the actual module parameters, and a table of operations.  Each operation in the operation table is represented by a pair: routine index and type area.  In many cases the type area for an operation is the same as the enclosing Type_Area, but for inherited operations, the type area for the operation would refer to the type area for the &lt;i&gt;super-class&lt;/i&gt; from which the operation was inherited.  The actual module parameters are most frequently other types (represented by a pointer to their type area), but can be values, object references, or operations.&lt;/dd&gt;&lt;/dl&gt;Instructions identify a memory location of interest by a pair: memory area and offset.  This pair is called an &lt;i&gt;object locator.&lt;/i&gt;  In addition to the Parameter_Area, Local_Area, and Type_Area, an object locator can specify a memory area pointed-to by a local variable, and the locator offset is the offset within the pointed-to area.  The local pointers are called local &lt;i&gt;base registers,&lt;/i&gt; and may reside in any of the first 64 words of the local area. Finally, in the presence of nesting, the chain of static links may be followed to find an enclosing local area or enclosing parameter area.&lt;br /&gt;&lt;br /&gt;Here is a sampling of ParaSail Virtual Machine instructions:&lt;br /&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;Move_Word, Store_Int_Literal, Store_String_Literal, Store_Real_Literal, Jump, Conditional_Jump, Call, Return, Parallel_Call, Parallel_Block, Parallel_Wait. &lt;/div&gt;&lt;br /&gt;Operands are generally identified with object locators, except for literal operands which are identified either by their actual value, or by an index into a table of literals.&lt;br /&gt;&lt;br /&gt;Note that there are no instructions for doing normal arithmetic or logical operations.  These are all implemented by calling routines.  There are a set of &lt;i&gt;built-in&lt;/i&gt; routines for doing the typical set of arithmetic and logical operations, on operands of various sizes.&lt;br /&gt;&lt;br /&gt;The more interesting instructions are the Parallel_Call, Parallel_Block, and Parallel_Wait.  Parallel_Call is essentially equivalent to Call, where the calling routine computes the input parameters and places them in a parameter area, and then calls the routine.  The difference with a Parallel_Call is that the caller also identifies a &lt;i&gt;picothread master&lt;/i&gt; and allocates a small area for a &lt;i&gt;picothread control block&lt;/i&gt; (pTCB), and the instruction completes without waiting for the call to complete.  Instead, the Parallel_Call instruction adds the pTCB to a queue waiting to be serviced by one of the &lt;i&gt;virtual processors&lt;/i&gt; (vCPUs) executing the ParaSail program.  When the caller thread has finished its own work and wants to wait for the Parallel_Call to complete, it uses the Parallel_Wait instruction, identifying the same picothread master as was specified in the Parallel_Call instruction.  This suspends the calling thread until all of the parallel picothreads associated with the picothread master complete.  &lt;br /&gt;&lt;br /&gt;The Parallel_Block instruction is very similar to the Parallel_Call instruction, except that it identifies instructions that are part of the current routine, rather than calling a separate routine.  The execution of these instructions is performed by a separate picothread, which has its own pTCB, and local area.  The static link of the local area for the Parallel_Block picothread refers to the local area of the thread invoking the Parallel_Block instruction, allowing the nested picothread to use up-level references to reach the local variables of the enclosing picothread.&lt;br /&gt;&lt;br /&gt;The Return instruction is used to complete processing of both a Parallel_Call and a Parallel_Block, and the Parallel_Wait is used to wait for either kind of parallel activity.&lt;br /&gt;&lt;br /&gt;We recently completed a prototype implementation of the ParaSail Virtual Machine, including the picothread scheduling.  We learned some interesting lessons along the way.  Initially, a vCPU that was executing a picothread that performed a Parallel_Wait was itself suspended.  That quickly exhausted the number of vCPUs, and led us to start dynamically creating new vCPUs.  That caused the overall stack space to grow dramatically, since each vCPU needed its own heavy-weight threading context in the underlying operating system, along with a stack.  &lt;br /&gt;&lt;br /&gt;At this point, we concluded that a vCPU that executed a Parallel_Wait instruction should service the queue of waiting pTCBs if the picothread master it was waiting for was not yet complete.  That significantly reduced the number of vCPUs needed.  However, it still didn't seem to be as efficient as it could be.  As originally implemented, the queue of waiting pTCBs was first-in, first-out (FIFO).  However, after looking at various traces of execution, we realized that it was the last pTCB that was created which was always the first pTCB to be awaited.  Hence, we concluded that the pTCB queue should be last-in, first-out (LIFO).  That is, a vCPU should preferentially service the most recently queued pTCB when it had cycles to spare, since that would more likely be associated with a picothread master that is being awaited, and by servicing that pTCB first, it will reduce the number of pTCBs that were suspended in a Parallel_Wait instruction.  After making this final change, even a heavily recursive algorithm throwing off lots of parallel picothreads was handled efficiently.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8383004232931899216-5910478988071182505?l=parasail-programming-language.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://parasail-programming-language.blogspot.com/feeds/5910478988071182505/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://parasail-programming-language.blogspot.com/2010/11/virtual-machine-for-parasail-with.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8383004232931899216/posts/default/5910478988071182505'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8383004232931899216/posts/default/5910478988071182505'/><link rel='alternate' type='text/html' href='http://parasail-programming-language.blogspot.com/2010/11/virtual-machine-for-parasail-with.html' title='A virtual machine for ParaSail with picothread scheduling'/><author><name>Tuck</name><uri>http://www.blogger.com/profile/08866496974237052847</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8383004232931899216.post-1336682520063584871</id><published>2010-09-14T09:25:00.000-04:00</published><updated>2010-09-14T09:25:11.972-04:00</updated><title type='text'>Notation for "intervals" in ParaSail</title><content type='html'>It is quite common in a &lt;i&gt;precondition&lt;/i&gt; or &lt;i&gt;postcondition&lt;/i&gt; to want to indicate that the value of a variable must be within some &lt;i&gt;interval&lt;/i&gt; of values (aka "&lt;i&gt;range&lt;/i&gt;" of values), such as 1..10, or 0..+inf.&amp;nbsp; When dealing with &lt;i&gt;real&lt;/i&gt; values (e.g. &lt;i&gt;floating point&lt;/i&gt; values) as opposed to &lt;i&gt;integer&lt;/i&gt; values, it is often desirable to represent an &lt;i&gt;open&lt;/i&gt; or &lt;i&gt;half-open&lt;/i&gt; interval, where the boundary value is &lt;i&gt;not&lt;/i&gt; included in the specified interval.&amp;nbsp; For example, to specify that X must be in the interval 0.0 .. 10.0, but not including zero itself, the notation "(0.0 .. 10.0]" is sometimes used, where where "(" and ")" represent an &lt;i&gt;open&lt;/i&gt; (exclusive) boundary, while "[" and "]" represent a &lt;i&gt;closed&lt;/i&gt; (inclusive) boundary.&lt;br /&gt;&lt;br /&gt;For &lt;b&gt;ParaSail&lt;/b&gt;, because "()" and "[]" are already used in the syntax, we have adopted a different notation for &lt;i&gt;open&lt;/i&gt; and &lt;i&gt;half-open&lt;/i&gt; intervals:&lt;br /&gt;&lt;br /&gt;&amp;nbsp; 0.0 .. 10.0 &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;i&gt;closed&lt;/i&gt; interval&amp;nbsp;&amp;nbsp;&lt;br /&gt;&amp;nbsp; 0.0 &amp;lt;.. 10.0&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;i&gt;half-open&lt;/i&gt; on left&lt;br /&gt;&amp;nbsp; 0.0 ..&amp;lt; 10.0&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;i&gt;half-open&lt;/i&gt; on right&lt;br /&gt;&amp;nbsp; 0.0 &amp;lt;..&amp;lt; 10.0&amp;nbsp;&amp;nbsp; &lt;i&gt;open&lt;/i&gt; on both sides&lt;br /&gt;&lt;br /&gt;Hence, one can write in an annotation:&lt;br /&gt;&lt;br /&gt;&amp;nbsp; { X in A &amp;lt;.. B }&lt;br /&gt;&lt;br /&gt;as a short-hand for&lt;br /&gt;&lt;br /&gt;&amp;nbsp; { A &amp;lt; X and then X &amp;lt;= B }&lt;br /&gt;&lt;br /&gt;with the additional difference that X is only evaluated once (though that will rarely matter in an annotation).&amp;nbsp;&lt;br /&gt;&lt;br /&gt;Like the other relational operators, these interval operators are defined &lt;i&gt;automatically&lt;/i&gt; once the "=?" operator has been appropriately defined.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8383004232931899216-1336682520063584871?l=parasail-programming-language.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://parasail-programming-language.blogspot.com/feeds/1336682520063584871/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://parasail-programming-language.blogspot.com/2010/09/notation-for-intervals-in-parasail.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8383004232931899216/posts/default/1336682520063584871'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8383004232931899216/posts/default/1336682520063584871'/><link rel='alternate' type='text/html' href='http://parasail-programming-language.blogspot.com/2010/09/notation-for-intervals-in-parasail.html' title='Notation for &quot;intervals&quot; in ParaSail'/><author><name>Tuck</name><uri>http://www.blogger.com/profile/08866496974237052847</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8383004232931899216.post-2905490019593256876</id><published>2010-09-01T07:42:00.000-04:00</published><updated>2010-09-01T07:42:16.133-04:00</updated><title type='text'>Finalization (destructors) and multi-thread exits in ParaSail</title><content type='html'>Languages such as C++ and Ada that support both &lt;i&gt;finalization&lt;/i&gt; (&lt;i&gt;destructors&lt;/i&gt;) and &lt;i&gt;exceptions&lt;/i&gt; generally face some degree of distributed overhead due to the complex interactions between these two features.&amp;nbsp; Since exceptions can arise virtually anywhere, if there is finalization to be performed (e.g. destructors to be called) on the way "out" of a scope, there is generally a need for some kind of per-thread cleanup list to be walked as part of propagating exceptions, or the need for numerous implicit exception handlers and a precise indication of exactly how much initialization has been performed (e.g. constructors that have been completed) at any given moment.&lt;br /&gt;&lt;br /&gt;As indicated in an earlier post, we have tentatively decided to do &lt;i&gt;without&lt;/i&gt; exceptions in &lt;b&gt;ParaSail&lt;/b&gt;, but the &lt;b&gt;exit&lt;/b&gt; ... &lt;b&gt;with&lt;/b&gt; feature can result in potentially numerous &lt;i&gt;scopes &lt;/i&gt;being&lt;i&gt; exited&lt;/i&gt; in the various other threads which are all being terminated as a result of some thread initiating an &lt;b&gt;exit&lt;/b&gt; from a compound statement such as a &lt;b&gt;block&lt;/b&gt; or &lt;b&gt;loop&lt;/b&gt;.&amp;nbsp; We have also suggested that ParaSail will support some notion of &lt;i&gt;finalization&lt;/i&gt;, if an "&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;end&lt;/span&gt;" operator is associated with the type of an object, such that on exiting the scope of the object, the "&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;end&lt;/span&gt;" operator will be invoked automatically.&amp;nbsp; So the question is: must these "&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;end&lt;/span&gt;" operator calls be performed on all of the local objects of the threads being terminated as a side effect of an &lt;b&gt;exit&lt;/b&gt; by some parallel thread?&amp;nbsp; Our tentative answer is "no."&amp;nbsp;&lt;br /&gt;&lt;br /&gt;To avoid race conditions between a thread being terminated and the code executing after an &lt;b&gt;exit&lt;/b&gt;, we believe that we need to restrict a thread that might be prematurely terminated, so that it can update only objects local to the exitable construct.&amp;nbsp; The only code of an exitable construct that would be permitted to update objects declared outside the construct would be the code following an "&lt;b&gt;exit&lt;/b&gt; ... &lt;b&gt;with&lt;/b&gt;" or the code following "&lt;b&gt;end&lt;/b&gt; ... &lt;b&gt;with&lt;/b&gt;".&lt;br /&gt;&lt;br /&gt;For example, here is the exitable construct we used in an earlier post:&lt;br /&gt;&lt;br /&gt;&lt;b&gt;const&lt;/b&gt; Result : &lt;b&gt;optional&lt;/b&gt; Tree_Id;&lt;br /&gt;&lt;b&gt;for&lt;/b&gt; T =&amp;gt; Root &lt;b&gt;then&lt;/b&gt; T.Left || T.Right&lt;br /&gt;&lt;b&gt;&amp;nbsp; while &lt;/b&gt;T&lt;b&gt; not null concurrent&lt;/b&gt; &lt;b&gt;loop&lt;/b&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;b&gt;if&lt;/b&gt; T.Value == Desired_Value &lt;b&gt;then&lt;/b&gt;&lt;br /&gt;&lt;i&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; // Found desired node, exit with its identifier &lt;/i&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;b&gt;exit&lt;/b&gt; &lt;b&gt;loop&lt;/b&gt; &lt;b&gt;with&lt;/b&gt; (Result =&amp;gt; T.Id);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;b&gt;end&lt;/b&gt; &lt;b&gt;if&lt;/b&gt;;&lt;br /&gt;&lt;b&gt;end&lt;/b&gt; &lt;b&gt;loop&lt;/b&gt; &lt;b&gt;with&lt;/b&gt; (Result =&amp;gt; &lt;b&gt;null&lt;/b&gt;);&lt;br /&gt;&lt;br /&gt;In this example, we might have many threads all executing inside the loop concurrently.&amp;nbsp; To avoid race conditions, we would not allow any of these threads to update objects declared outside the loop, because they might be terminated at any moment, and the update might be &lt;i&gt;disrupted&lt;/i&gt; in the middle.&amp;nbsp; However, we &lt;i&gt;would&lt;/i&gt; allow the code following the &lt;b&gt;"exit loop with&lt;/b&gt;" to update Result, as well as the code following "&lt;b&gt;end loop with&lt;/b&gt;." This is safe because only one of these is ever executed for a given execution of the loop, and once we begin executing such code it won't be disrupted by some other thread of the same loop initiating an &lt;b&gt;exit&lt;/b&gt;.&lt;br /&gt;&lt;br /&gt;Note that the code following an &lt;b&gt;exit ... with&lt;/b&gt; or &lt;b&gt;end ... with&lt;/b&gt; &lt;i&gt;might&lt;/i&gt; be disrupted by a thread &lt;b&gt;exit&lt;/b&gt;ing some &lt;i&gt;enclosing&lt;/i&gt; construct, but this code would &lt;i&gt;not&lt;/i&gt; be allowed to update objects &lt;i&gt;outside&lt;/i&gt; that enclosing construct, thereby avoiding the race condition.&lt;br /&gt;&lt;br /&gt;Given this rule that code in a compound statement with &lt;i&gt;multiple&lt;/i&gt; &lt;i&gt;threads&lt;/i&gt; may not update objects declared &lt;i&gt;outside&lt;/i&gt; the compound statement, if there is a chance that at least one of those threads might perform an &lt;b&gt;exit&lt;/b&gt; ... &lt;b&gt;with&lt;/b&gt;, we can simplify the &lt;i&gt;finalization&lt;/i&gt; problem.&amp;nbsp; There is no need to invoke the "&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;end&lt;/span&gt;" operator on an object if that operator cannot possibly affect objects that will survive the &lt;b&gt;exit&lt;/b&gt; statement.&lt;br /&gt;&lt;br /&gt;Thinking more specifically about the "&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;end&lt;/span&gt;" operator, and the general lack of access to global variables within an operation, what exactly can an "&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;end&lt;/span&gt;" operator do?&amp;nbsp; The answer is that an "&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;end&lt;/span&gt;" operator cannot really do anything unless the object being finalized includes a &lt;i&gt;reference&lt;/i&gt; of some sort to an object that will outlive the finalization.&amp;nbsp; We will talk more in a future posting about what if any restrictions exist on incorporating a reference to one object as part of another object, but for now let us presume that such objects can exist, but they cannot be overwritten by a whole-object assignment statement (i.e. they are not "&lt;i&gt;assignable&lt;/i&gt;").&amp;nbsp;&lt;br /&gt;&lt;br /&gt;What would be the purpose of such an object with an embedded reference?&amp;nbsp; One use would be to perform a kind of "&lt;i&gt;mark/release&lt;/i&gt;" style of &lt;i&gt;resource allocation&lt;/i&gt;.&amp;nbsp; On entry to a scope, a "&lt;i&gt;mark&lt;/i&gt;" object could be created with a reference to an enclosing &lt;i&gt;resource manager&lt;/i&gt; of some sort.&amp;nbsp; Inside the scope, allocations of the resource would be &lt;i&gt;mediated&lt;/i&gt; by the "&lt;i&gt;mark&lt;/i&gt;" object, such that when exiting the scope, the "&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;end&lt;/span&gt;" operator applied to the "mark" object could automatically &lt;i&gt;release&lt;/i&gt; all of the resources allocated on behalf of objects local to the scope.&lt;br /&gt;&lt;br /&gt;Now returning to our original question about whether finalization needs to be performed on all objects local to a thread that is being &lt;i&gt;prematurely terminated&lt;/i&gt; -- if we presume that the "&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;end&lt;/span&gt;" operators are performing something analogous to a "&lt;i&gt;release&lt;/i&gt;" operation, then we can see how we could safely &lt;i&gt;skip&lt;/i&gt; all intermediary release operations so long as we perform the ones associated with the actual compound statement being &lt;b&gt;exit&lt;/b&gt;ed.&amp;nbsp; This also presumes that the only &lt;i&gt;references&lt;/i&gt; permitted from an object &lt;i&gt;local&lt;/i&gt; to a multi-threaded compound statement with an &lt;b&gt;exit&lt;/b&gt;, to an object declared &lt;i&gt;outside&lt;/i&gt; the compound statement, are references to &lt;b&gt;concurrent&lt;/b&gt; objects that are themselves &lt;i&gt;local&lt;/i&gt; to the &lt;i&gt;innermost&lt;/i&gt; &lt;i&gt;enclosing&lt;/i&gt; multi-threaded-with-&lt;b&gt;exit&lt;/b&gt; compound statement.&amp;nbsp; For example:&lt;br /&gt;&lt;br /&gt;&lt;b&gt;var&lt;/b&gt; Enclosing_Obj1 : &lt;b&gt;concurrent&lt;/b&gt; T := ...&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ...&lt;br /&gt;*Block1*&lt;br /&gt;&lt;b&gt;block&lt;/b&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;b&gt;var&lt;/b&gt; Mark1 := Create_Mark(Enclosing_Obj1, ...);&lt;br /&gt;&lt;i&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; // Mark1 contains a reference to Enclosing_Obj1&lt;/i&gt;&lt;br /&gt;&lt;i&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // and has an "&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;end&lt;/span&gt;" operator which performs a release operation.&lt;/i&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;b&gt;for&lt;/b&gt; I &lt;b&gt;in&lt;/b&gt; 1..10 &lt;b&gt;concurrent loop&lt;/b&gt;&lt;br /&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; var&lt;/b&gt; Mark2 := Create_Mark(Mark1, ...);&lt;b&gt; &lt;/b&gt;&lt;br /&gt;&lt;b&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/b&gt;&lt;i&gt;// Here we have an inner mark&lt;/i&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Allocate_Resource(Mark2, ...);&lt;br /&gt;&lt;i&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp; // Here we allocate some resource using Mark2 to mediate the&lt;/i&gt;&lt;br /&gt;&lt;i&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // allocation from Mark1 which in turn is mediating allocation&lt;/i&gt;&lt;br /&gt;&lt;i&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // from Enclosing_Obj1.&amp;nbsp; The marks allow the resources to be&amp;nbsp;&lt;/i&gt;&lt;br /&gt;&lt;i&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // automatically released on block exit as a side effect of&lt;/i&gt;&lt;br /&gt;&lt;i&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp; // finalization via the "&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;end&lt;/span&gt;" operator. &lt;/i&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;b&gt;if&lt;/b&gt; This_Looks_Good(I, ...) &lt;b&gt;then&lt;/b&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;b&gt;exit block&lt;/b&gt; Block1 &lt;b&gt;with&lt;/b&gt; (Result =&amp;gt; I);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;i&gt;// This terminates any other threads inside Block1&lt;/i&gt;.&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;b&gt;end if&lt;/b&gt;;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;b&gt;end loop&lt;/b&gt;;&lt;br /&gt;&lt;b&gt;end block&lt;/b&gt; Block1 with (Result =&amp;gt; 0);&lt;br /&gt;&lt;br /&gt;Now if some thread is deep within a call on "This_Looks_Good" when some other thread initiates the block &lt;b&gt;exit&lt;/b&gt;, the only object that gets explicitly &lt;i&gt;finalized&lt;/i&gt; will be Mark1.&amp;nbsp; The multiple Mark2 objects (one for each thread of the &lt;b&gt;concurrent&lt;/b&gt; loop) will &lt;i&gt;not&lt;/i&gt; be finalized, as presumably performing an "&lt;span style="font-family: &amp;quot;Courier New&amp;quot;,Courier,monospace;"&gt;end&lt;/span&gt;" on Mark1 will also &lt;i&gt;release&lt;/i&gt; any allocations that were mediated by one of the Mark2 objects.&lt;br /&gt;&lt;br /&gt;The bottom line is that when a tree of threads is terminated by an &lt;b&gt;exit&lt;/b&gt; from a multi-threaded compound statement, the &lt;i&gt;only finalization&lt;/i&gt; that needs to be performed is for the objects &lt;i&gt;immediately local&lt;/i&gt; to the compound statement being &lt;b&gt;exit&lt;/b&gt;ed.&amp;nbsp; Objects local to the various threads being terminated need &lt;i&gt;not&lt;/i&gt; be separately finalized.&amp;nbsp; This &lt;i&gt;avoids&lt;/i&gt; the kind of complex interaction that exists between &lt;i&gt;finalization&lt;/i&gt; and &lt;i&gt;exception propagation&lt;/i&gt;, including avoiding the overhead of maintaining precise initialization information, and avoiding performing a lot of potentially wasteful finalization.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8383004232931899216-2905490019593256876?l=parasail-programming-language.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://parasail-programming-language.blogspot.com/feeds/2905490019593256876/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://parasail-programming-language.blogspot.com/2010/09/finalization-destructors-and-multi.html#comment-form' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8383004232931899216/posts/default/2905490019593256876'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8383004232931899216/posts/default/2905490019593256876'/><link rel='alternate' type='text/html' href='http://parasail-programming-language.blogspot.com/2010/09/finalization-destructors-and-multi.html' title='Finalization (destructors) and multi-thread exits in ParaSail'/><author><name>Tuck</name><uri>http://www.blogger.com/profile/08866496974237052847</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8383004232931899216.post-3020287221300565279</id><published>2010-08-24T13:41:00.000-04:00</published><updated>2010-08-24T13:41:44.435-04:00</updated><title type='text'>No exceptions in ParaSail, but exitable multi-thread constructs</title><content type='html'>We have been mulling over the idea of &lt;i&gt;exceptions&lt;/i&gt; in &lt;b&gt;ParaSail&lt;/b&gt;, and have pretty firmly concluded that they aren't worth the trouble.&amp;nbsp; In a highly parallel language, with lots of threads, exception propagation across threads becomes a significant issue, and that is a nasty area in general.&amp;nbsp; Also, exceptions can introduce many additional paths into a program, making thorough testing that much harder.&amp;nbsp; And the whole business of declaring what exceptions might be propagated, and then deciding what to do if some other exception is propagated can create numerous maintenance headaches.&lt;br /&gt;&lt;br /&gt;There is a feature in ParaSail as currently designed which provides some of the same capabilities of exceptions, but is particularly suited to parallel programming.&amp;nbsp; This is the "&lt;b&gt;exit with&lt;/b&gt;" statement, which allows a construct to be exited with one or more values specified as results, and at the same time &lt;i&gt;terminating&lt;/i&gt; any other threads currently executing within the construct.&amp;nbsp; For example, here is a loop implementing a parallel search of a tree with the first thread finding the desired node exiting and killing off all of the other threads as part of the "&lt;b&gt;exit ... with&lt;/b&gt;" statement:&lt;br /&gt;&lt;br /&gt;&lt;b&gt;const&lt;/b&gt; Result : &lt;b&gt;optional&lt;/b&gt; Tree_Id;&lt;br /&gt;&lt;b&gt;for&lt;/b&gt; T =&amp;gt; Root &lt;b&gt;then&lt;/b&gt; T.Left || T.Right&lt;br /&gt;&lt;b&gt;&amp;nbsp; while &lt;/b&gt;T&lt;b&gt; not null concurrent&lt;/b&gt; &lt;b&gt;loop&lt;/b&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;b&gt;if&lt;/b&gt; T.Value == Desired_Value &lt;b&gt;then&lt;/b&gt;&lt;br /&gt;&lt;i&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; // Found desired node, exit with its identifier &lt;/i&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;b&gt;exit&lt;/b&gt; &lt;b&gt;loop&lt;/b&gt; &lt;b&gt;with&lt;/b&gt; (Result =&amp;gt; T.Id);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;b&gt;end&lt;/b&gt; &lt;b&gt;if&lt;/b&gt;;&lt;br /&gt;&lt;b&gt;end&lt;/b&gt; &lt;b&gt;loop&lt;/b&gt; &lt;b&gt;with&lt;/b&gt; (Result =&amp;gt; &lt;b&gt;null&lt;/b&gt;); &lt;br /&gt;&lt;br /&gt;This declares a Result object of type Tree_Id.&amp;nbsp; It then walks the tree in parallel, starting at Root and continuing with T.Left and T.Right concurrently.&amp;nbsp; It continues until it reaches "&lt;b&gt;null&lt;/b&gt;" on each branch, or some node is found with its Value component matching the Desired_Value.&amp;nbsp; The value of Identifier at the end indicates the identifier of the node having the desired Value, or &lt;b&gt;null&lt;/b&gt; to indicate that no node was found.&amp;nbsp; The presence of &lt;b&gt;optional&lt;/b&gt; in the declaration for Result indicates that its value might be &lt;b&gt;null&lt;/b&gt;.&lt;br /&gt;&lt;br /&gt;Supporting this kind of intentional "race" seems important in parallel programming, as many problems are amenable to a divide and conquer approach, but it is important that as soon as a solution is found, no further time is wasted searching other parts of the solution space.&amp;nbsp; The "&lt;b&gt;end ... with&lt;/b&gt;" phrase allows the specification of one or more results if the construct ends &lt;i&gt;normally&lt;/i&gt;, as opposed to via an "&lt;b&gt;exit ... with&lt;/b&gt;" (in this case, ending &lt;i&gt;normally&lt;/i&gt; means all threads reach a &lt;b&gt;null&lt;/b&gt; branch in the walk of the tree without finding the desired node).&amp;nbsp; Effectively the "&lt;b&gt;exit ... with&lt;/b&gt;" &lt;i&gt;skips&lt;/i&gt; &lt;i&gt;over&lt;/i&gt; the "&lt;b&gt;end ... with&lt;/b&gt;" phrase.&lt;br /&gt;&lt;br /&gt;So how does this all relate to exceptions?&amp;nbsp; Well given the "&lt;b&gt;exit ... with&lt;/b&gt;" capability, one can establish two or more threads, one which monitors for a failure condition, and the others which do the needed computation.&amp;nbsp; The thread monitoring for a failure condition performs an "&lt;b&gt;exit ... with&lt;/b&gt;" if it detects a failure, with the result indicating the nature of the failure, and as a side-effect killing off any remaining computation threads.&amp;nbsp; If the normal computation succeeds, then an "&lt;b&gt;exit ... with&lt;/b&gt;" giving the final result will kill off the monitoring thread.&amp;nbsp; Note that the "&lt;b&gt;exit ... with&lt;/b&gt;" statements must occur &lt;i&gt;textually&lt;/i&gt; &lt;i&gt;within&lt;/i&gt; the construct being exited, so it is visible whether such a &lt;i&gt;premature&lt;/i&gt; &lt;i&gt;exit&lt;/i&gt; can occur, unlike an exception which can arise deep within a call tree and be propagated out many levels.&lt;br /&gt;&lt;br /&gt;As an example of the kind of failure condition which might be amenable to this kind of monitoring, imagine a &lt;i&gt;resource manager&lt;/i&gt; object, which provides up to some fixed maximum of some kind of &lt;i&gt;resource&lt;/i&gt; (e.g. storage) to code within a &lt;b&gt;block&lt;/b&gt;.&amp;nbsp; This resource manager (which is presumably of a &lt;b&gt;concurrent&lt;/b&gt; type) could be passed down to operations called within the &lt;b&gt;block&lt;/b&gt; for their use.&amp;nbsp; Meanwhile, a separate &lt;i&gt;monitoring thread&lt;/i&gt; would be created immediately within the &lt;b&gt;block&lt;/b&gt; which would call an operation on the resource manager which would &lt;i&gt;suspend&lt;/i&gt; the thread until the resource runs out, at which point it would be awakened with an appropriate indication of the resource exhaustion, and any other information that might be helpful in later diagnosis.&amp;nbsp; On return from this Wait_For_Exhaustion operation, the &lt;i&gt;monitoring thread&lt;/i&gt; would do an "&lt;b&gt;exit block with&lt;/b&gt; (Result =&amp;gt; Failure, ...)" or equivalent, to indicate that the computation required more resources than were provided.&amp;nbsp; The code following the &lt;b&gt;block&lt;/b&gt; would then be able to take appropriate action.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8383004232931899216-3020287221300565279?l=parasail-programming-language.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://parasail-programming-language.blogspot.com/feeds/3020287221300565279/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://parasail-programming-language.blogspot.com/2010/08/no-exceptions-in-parasail-but-exitable.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8383004232931899216/posts/default/3020287221300565279'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8383004232931899216/posts/default/3020287221300565279'/><link rel='alternate' type='text/html' href='http://parasail-programming-language.blogspot.com/2010/08/no-exceptions-in-parasail-but-exitable.html' title='No exceptions in ParaSail, but exitable multi-thread constructs'/><author><name>Tuck</name><uri>http://www.blogger.com/profile/08866496974237052847</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8383004232931899216.post-8865168118792627046</id><published>2010-08-23T18:16:00.000-04:00</published><updated>2010-08-23T18:16:05.146-04:00</updated><title type='text'>Initial implementation model for ParaSail types</title><content type='html'>&lt;b&gt;ParaSail&lt;/b&gt; supports object-oriented programming, and as such there needs to be some kind of &lt;i&gt;run-time&lt;/i&gt; representation for types to support &lt;i&gt;dispatching&lt;/i&gt; calls (aka &lt;i&gt;virtual&lt;/i&gt; &lt;i&gt;function&lt;/i&gt; calls, &lt;i&gt;method&lt;/i&gt; calls, etc.).&amp;nbsp; Most "normal" objects need no run-time type information associated with them, but an object or parameter of a polymorphic type (such as "Int_Expr+") needs some run-time type information to support dispatching calls on its operations.&amp;nbsp; In addition, each operation of an interface generally needs an implicit parameter identifying its  "enclosing" type, to gain access to the module parameters, given that  every module is effectively a "&lt;i&gt;generic&lt;/i&gt;" module.&lt;br /&gt;&lt;br /&gt;Because ParaSail supports &lt;i&gt;multiple&lt;/i&gt; &lt;i&gt;inheritance&lt;/i&gt; of interfaces (including &lt;i&gt;ad hoc&lt;/i&gt; interface matching -- see blog entry on that topic), a simple table of operations for each type with a compile-time-known &lt;i&gt;slot-number&lt;/i&gt; in the table doesn't work as it would if ParaSail only supported &lt;i&gt;single&lt;/i&gt; &lt;i&gt;inheritance&lt;/i&gt;.&amp;nbsp; Instead we adopt the notion of a "&lt;i&gt;type view&lt;/i&gt;" which consists of a pointer to the overall table of operations of the type, as well as an "&lt;i&gt;slot-number mapping&lt;/i&gt;" to provide the particular "&lt;i&gt;view&lt;/i&gt;" of the type.&amp;nbsp; The slot-number mapping is a simple vector of &lt;i&gt;operation slot numbers&lt;/i&gt; for the operation table, indexed by the &lt;i&gt;interface slot number&lt;/i&gt; of the particular interface through which the type is being "&lt;i&gt;viewed&lt;/i&gt;."&amp;nbsp; For example, presume we have an &lt;b&gt;interface&lt;/b&gt; "Assignable" with only two operations, say, Assign and Copy, with &lt;i&gt;interface slot numbers&lt;/i&gt; one and two.&amp;nbsp; Given some type with many operations, where the &lt;i&gt;operation slot numbers&lt;/i&gt; of 21 and 33 are for Assign and Copy respectively, then the Assignable "&lt;i&gt;view&lt;/i&gt;" of the type would have a &lt;i&gt;slot-number mapping&lt;/i&gt; of:&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [1 =&amp;gt; 21, 2 =&amp;gt; 33]&lt;br /&gt;&lt;br /&gt;The actual operation table would be a vector of pairs, each pair being a reference to the type from which the code for the operation was inherited, and the reference to the actual code for the operation.&amp;nbsp; Hence, the operation table for Type_C could be imagined as something like:&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [1 =&amp;gt; (Type_A, Op1_Code),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 2 =&amp;gt; (Type_B, Op2_Code),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ...,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 21 =&amp;gt; (Type_A, Assign_Code),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ...,&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 33 =&amp;gt; (Type_C, Copy_Code),&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ...]&lt;br /&gt;&lt;br /&gt;Here we assume that the code for Op1 and Assign originated with Type_A, the code for Op2 originated with Type_B, and the code for Copy originated with Type_C.&lt;br /&gt;&lt;br /&gt;In addition to an operation table, a type would have a table of module actuals, one for each module formal parameter.&amp;nbsp; Module actuals could be themselves "type views," operations, or (constant) objects.&lt;br /&gt;&lt;br /&gt;If an interface declared externally-visible components (&lt;b&gt;const&lt;/b&gt; or &lt;b&gt;var&lt;/b&gt;), these would be represented for uniformity by operations that take a reference to an object of the interface's type and return a reference to the component.&amp;nbsp; This allows multiple inheritance of such (at least conceptual) components from one or more implemented interfaces, though the actual offset of the components within the object (or whether they are true components in the case of &lt;b&gt;const&lt;/b&gt;s) might very well differ from the corresponding components of the interface.&lt;br /&gt;&lt;br /&gt;When an operation is called, in addition to its explicit parameters, it would be passed a reference to the type from which it originated.&amp;nbsp; This would allow it to gain access to the other operations of its module, as well as to the module actuals.&amp;nbsp; Because ParaSail allows the type from which a type is &lt;b&gt;extend&lt;/b&gt;ed to be overridden (see blog entry on &lt;span style="font-size: small;"&gt;&lt;a href="http://parasail-programming-language.blogspot.com/2009/09/parasail-extension-inheritance-and.html"&gt;ParaSail  extension, inheritance, and polymorphism&lt;/a&gt;&lt;/span&gt;&lt;span style="font-size: small;"&gt;), the operation table may vary depending on which type is the base for extension (since the type from which a given operation originates could vary).&amp;nbsp; Hence an operation doesn't necessarily "know" where one of the other operations of its module originates (presuming the operation is inherited rather than redefined within the module's &lt;b&gt;class&lt;/b&gt; directly).&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: small;"&gt;Because each type has its own operation table with pointers to the code for each operation, it is possible for some of the operations to be specially compiled for that type, rather than simply reusing the "generic" code generated when the module was first compiled.&amp;nbsp; This allows the code to incorporate information about the module actuals (as an optimization), rather than having to use the information only at run-time which is what the "generic" code would do.&amp;nbsp; Hence, in the example above, the Copy_Code for Type_C might incorporate directly information about the module actuals or the operation table for Type_C, rather than having to index into the table of module actuals or into the operation table at run-time.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-size: small;"&gt;Other implementation models are of course possible, but this one seems to have the advantage of uniformity and flexibility, with constant-time run-time performance for making a dispatching call.&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8383004232931899216-8865168118792627046?l=parasail-programming-language.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://parasail-programming-language.blogspot.com/feeds/8865168118792627046/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://parasail-programming-language.blogspot.com/2010/08/initial-implementation-model-for.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8383004232931899216/posts/default/8865168118792627046'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8383004232931899216/posts/default/8865168118792627046'/><link rel='alternate' type='text/html' href='http://parasail-programming-language.blogspot.com/2010/08/initial-implementation-model-for.html' title='Initial implementation model for ParaSail types'/><author><name>Tuck</name><uri>http://www.blogger.com/profile/08866496974237052847</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8383004232931899216.post-3981552568294744196</id><published>2010-08-23T15:25:00.000-04:00</published><updated>2010-08-23T15:25:55.936-04:00</updated><title type='text'>Ad hoc interface matching in ParaSail</title><content type='html'>When a &lt;i&gt;module&lt;/i&gt; is instantiated in &lt;b&gt;ParaSail&lt;/b&gt; to form a &lt;i&gt;type,&lt;/i&gt; actual parameters must be specified for each module formal parameter.&amp;nbsp; When the module formal is itself a type, the module actual must be a type that matches the formal appropriately.&amp;nbsp;&amp;nbsp; For example, given:&lt;br /&gt;&lt;br /&gt;&lt;b&gt;interface&lt;/b&gt; Set&amp;lt;Element_Type &lt;b&gt;is&lt;/b&gt; Assignable&amp;lt;&amp;gt;&amp;gt; &lt;b&gt;is&lt;/b&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;b&gt;function&lt;/b&gt; Union(Left, Right : Set) -&amp;gt; Set;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;b&gt;function&lt;/b&gt; Unit_Set(Elem : Element_Type) -&amp;gt; Set;&lt;br /&gt;&amp;nbsp;&amp;nbsp; ...&lt;br /&gt;&lt;b&gt;end&lt;/b&gt; &lt;b&gt;interface&lt;/b&gt; Set;&lt;br /&gt;&lt;br /&gt;we will want to be able to write:&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;b&gt;type&lt;/b&gt; My_Int_Set &lt;b&gt;is&lt;/b&gt; Set&amp;lt;My_Integer_Type&amp;gt;;&lt;br /&gt;&lt;br /&gt;Now the question is whether My_Integer_Type must be based on an &lt;b&gt;interface&lt;/b&gt; that is explicitly indicated as &lt;b&gt;extend&lt;/b&gt;ing or &lt;b&gt;implement&lt;/b&gt;ing Assignable, or should we simply require that My_Integer_Type has all of the operations expected of a type based on Assignable.&amp;nbsp; In other words, does an actual type match a formal type only if it &lt;b&gt;extends&lt;/b&gt; or &lt;b&gt;implements&lt;/b&gt; the specified interface, or is &lt;i&gt;ad hoc&lt;/i&gt; matching permitted, where at the point of instantiation a check is made that all of the required operations are present?&amp;nbsp; A similar question would come up when converting an object of a particular type to a &lt;i&gt;polymorphic&lt;/i&gt; type (such as Assignable+).&lt;br /&gt;&lt;br /&gt;Our initial instincts were to require that the actual type (or the type being converted) explicitly &lt;b&gt;extend&lt;/b&gt; or &lt;b&gt;implement&lt;/b&gt; the formal type (or the target type).&amp;nbsp; However, this will tend to cause a proliferation of interfaces being added to the list of &lt;b&gt;implements&lt;/b&gt; for any given module, such as Assignable or Comparable or Numeric or ..., and still the actual subset of operations of interest might not be mentioned explicitly.&amp;nbsp;&lt;br /&gt;&lt;br /&gt;Given the above concern, we now favor allowing &lt;i&gt;ad hoc&lt;/i&gt; matching requirements for matching of module actuals to module formals, and when converting from a normal type to a polymorphic type.&amp;nbsp; There are some potential problems during maintenance if the operations of an interface change, but those problems exist anyway, since any code that makes calls on individual operations defined in an interface may suffer maintenance issues when operations change.&amp;nbsp; Note, however, that adding operations to the actual type, or removing them from the formal type, don't create maintenance issues.&lt;br /&gt;&lt;br /&gt;In general, there are many fewer places where modules are instantiated, or conversions to polymorphic types occur, than there are normal calls on operations, and defining and using (presumably abstract) interfaces such as Assignable or Comparable as module formals, if they capture exactly what operations of interest are needed by the module, could reduce rather than increase maintenance problems when trying to decide whether to change an existing operation of some interface.&lt;br /&gt;&lt;br /&gt;So the answer to the above question about instantiating Set with My_Integer_Type is now answered as follows:&amp;nbsp; My_Integer_Type must provide the operations defined in the interface Assignable, but it need &lt;i&gt;not&lt;/i&gt; directly or indirectly &lt;b&gt;extend&lt;/b&gt; or &lt;b&gt;implement&lt;/b&gt; Assignable.&amp;nbsp; This generally means that the list of interfaces specified in the &lt;b&gt;implements&lt;/b&gt; list is there primarily for documentation, and for imposing a linkage such that if additional operations are added to the &lt;b&gt;implement&lt;/b&gt;ed interface, the need to define the operations is known at the point of module definition, rather than being deferred until some point of use.&amp;nbsp; This also implies that when &lt;i&gt;ad hoc&lt;/i&gt; matching is used, there is a presumption that the module formal (or target type) is very stable and new operations are not expected to be added to it.&amp;nbsp; A type like Assignable&amp;lt;&amp;gt; certainly qualifies.&amp;nbsp;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8383004232931899216-3981552568294744196?l=parasail-programming-language.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://parasail-programming-language.blogspot.com/feeds/3981552568294744196/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://parasail-programming-language.blogspot.com/2010/08/ad-hoc-interface-matching-in-parasail.html#comment-form' title='10 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8383004232931899216/posts/default/3981552568294744196'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8383004232931899216/posts/default/3981552568294744196'/><link rel='alternate' type='text/html' href='http://parasail-programming-language.blogspot.com/2010/08/ad-hoc-interface-matching-in-parasail.html' title='Ad hoc interface matching in ParaSail'/><author><name>Tuck</name><uri>http://www.blogger.com/profile/08866496974237052847</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>10</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8383004232931899216.post-2003594996874802129</id><published>2010-08-23T14:33:00.002-04:00</published><updated>2010-08-23T17:17:30.202-04:00</updated><title type='text'>Eliminating the need for the Visitor Pattern in ParaSail</title><content type='html'>The &lt;i&gt;"Visitor"&lt;/i&gt; pattern is one of the more widely recognized patterns identified by the "Gang of Four" in &lt;i&gt;Design Patterns: Elements of Reusable Object-Oriented Software.&amp;nbsp;&lt;/i&gt; Object-oriented programming makes it relatively painless to add more types into a type hierarchy, but it makes it relatively painful to add more operations to an existing type hierarchy.&amp;nbsp; The Visitor pattern is intended to allow adding more operations without doing major surgery on the original type hierarchy, but it requires the use of a visitor object, plus an additional operation, often called &lt;i&gt;accept&lt;/i&gt;, on each type, which turns around and calls a &lt;i&gt;visit&lt;/i&gt; operation on the visitor object that is unique to that particular type in the hierarchy.&lt;br /&gt;&lt;br /&gt;Object-oriented frameworks like that of Common Lisp Object System effectively eliminate the need for the visitor pattern by allowing the addition of &lt;i&gt;dispatching&lt;/i&gt; operations (aka &lt;i&gt;virtual functions&lt;/i&gt;, &lt;i&gt;methods&lt;/i&gt;, etc.) after the type hierarchy has been established, with CLOS in particular allowing additional &lt;i&gt;methods&lt;/i&gt; to be added to preexisting &lt;i&gt;generic functions&lt;/i&gt;.&lt;br /&gt;&lt;br /&gt;In &lt;b&gt;ParaSail&lt;/b&gt;, we propose to support the definition of additional &lt;i&gt;dispatching&lt;/i&gt; operations to be used with polymorphic types in a somewhat more &lt;i&gt;modular&lt;/i&gt; way.&amp;nbsp; The basic idea is that an interface hierarchy can be extended &lt;i&gt;horizontally&lt;/i&gt; in addition to &lt;i&gt;vertically&lt;/i&gt;.&amp;nbsp; By this we mean that an additional named bundle of operations may be specified for the root interface of an interface hierarchy, and then this same named bundle may be defined for each descendant of this root interface, such that operations from this new bundle may be "dispatched" to when operating on polymorphic objects, just as can be the operations of the original root interface.&amp;nbsp; &lt;br /&gt;&lt;br /&gt;Here is an example based on a simple interface hierarchy used to represent numeric expressions:&lt;br /&gt;&lt;br /&gt;&lt;b&gt;interface&lt;/b&gt; Expr &amp;lt;Value_Type &lt;b&gt;is&lt;/b&gt; Integer&amp;lt;&amp;gt;&amp;gt; &lt;b&gt;is&lt;/b&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;b&gt;function&lt;/b&gt; Evaluate(E : Expr) -&amp;gt; Value_Type;&lt;br /&gt;&lt;b&gt;end interface&lt;/b&gt; Expr;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;interface&lt;/b&gt; Binary &lt;b&gt;extends&lt;/b&gt; Expr &lt;b&gt;is&lt;/b&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &lt;b&gt;type&lt;/b&gt; Binary_Op_Enum &lt;b&gt;is&lt;/b&gt; Enum&amp;lt;[#add, #sub, #mul, #div, ...]&amp;gt;;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &lt;b&gt;function&lt;/b&gt; Create(Op : Binary_Op_Enum; Left, Right : Expr+) -&amp;gt; Binary;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;b&gt;function&lt;/b&gt; Evaluate(B : Binary) -&amp;gt; Value_Type;&lt;br /&gt;&lt;b&gt;end interface&lt;/b&gt; Binary;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;interface&lt;/b&gt; Unary &lt;b&gt;extends&lt;/b&gt; Expr &lt;b&gt;is&lt;/b&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &lt;b&gt;type&lt;/b&gt; Unary_Op_Enum &lt;b&gt;is&lt;/b&gt; Enum &amp;lt;[#plus, #minus, #not, #abs, ...]&amp;gt;;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &lt;b&gt;function&lt;/b&gt; Create(Op : Unary_Op_Enum; Operand : Expr+) -&amp;gt; Unary; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;b&gt;function&lt;/b&gt; Evaluate(U : Unary) -&amp;gt; Value_Type;&lt;br /&gt;&lt;b&gt;end interface&lt;/b&gt; Unary;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;interface&lt;/b&gt; Leaf &lt;b&gt;extends&lt;/b&gt; Expr &lt;b&gt;is&lt;/b&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;b&gt;function&lt;/b&gt; Create(Value : Value_Type) -&amp;gt; Leaf;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &lt;b&gt;function&lt;/b&gt; Evaluate(L : Leaf) -&amp;gt; Value_Type;&lt;br /&gt;&lt;b&gt;end&lt;/b&gt; &lt;b&gt;interface&lt;/b&gt; Leaf;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ...&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&lt;b&gt;interface&lt;/b&gt; Calculator&amp;lt;Int_Expr is Expr&amp;lt;&amp;gt;&amp;gt; &lt;b&gt;is&lt;/b&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ...&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;b&gt;procedure&lt;/b&gt; Print_Value(Str : Output_Stream; E : Int_Expr+) &lt;b&gt;is&lt;/b&gt;&lt;br /&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;i&gt;&amp;nbsp; // &lt;/i&gt;&lt;/b&gt;E&lt;i&gt; is of the &lt;/i&gt;polymorphic&lt;i&gt; type &lt;/i&gt;Int_Expr&lt;i&gt;+&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/i&gt;&lt;br /&gt;&lt;i&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; // &lt;/b&gt;so calls on its operations will dispatch&lt;/i&gt;&lt;b&gt;.&lt;/b&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;b&gt;const&lt;/b&gt; Result := Evaluate(E);&amp;nbsp;&amp;nbsp; &lt;i&gt;// dispatching call&lt;/i&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Print(Str, Result);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;b&gt;end&lt;/b&gt; &lt;b&gt;procedure&lt;/b&gt; Print_Value;&lt;br /&gt;&lt;b&gt;end&lt;/b&gt; &lt;b&gt;interface&lt;/b&gt; Calculator;&lt;br /&gt;&lt;br /&gt;Now if we decide we want to add some more "dispatching" operations, we could either disrupt the existing hierarchy of interfaces by adding the operation to each interface, or we could add an operation to each interface to support the visitor pattern, and use that for defining additional operations.&amp;nbsp; For ParaSail, we are proposing a third approach:&lt;br /&gt;&lt;br /&gt;&lt;b&gt;interface&lt;/b&gt; Expr[#output] &lt;b&gt;is&lt;/b&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;b&gt;function&lt;/b&gt; Text_Image(E : Expr) -&amp;gt; Univ_String;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &lt;b&gt;function&lt;/b&gt; XML_Image(E : Expr) -&amp;gt; Univ_String;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ...&lt;br /&gt;&lt;b&gt;end&lt;/b&gt; &lt;b&gt;interface&lt;/b&gt; Expr[#output];&lt;br /&gt;&lt;br /&gt;&lt;b&gt;interface&lt;/b&gt; Binary[#output] &lt;b&gt;is&lt;/b&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;b&gt;function&lt;/b&gt; Text_Image(B : Binary) -&amp;gt; Univ_String;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;b&gt;function&lt;/b&gt; XML_Image(B : Binary) -&amp;gt; Univ_String;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ...&lt;br /&gt;&lt;b&gt;end&lt;/b&gt; &lt;b&gt;interface&lt;/b&gt; Binary[#output];&lt;br /&gt;...&lt;br /&gt;&lt;br /&gt;Here we have defined an interface extension labeled "#output".&amp;nbsp; We could define additional interfae extensions with other labels.&amp;nbsp; Now we have effectively added Text_Image and XML_Image as dispatching operations of Expr without a need for a visitor pattern and without disrupting the original Expr interface hierarchy.&amp;nbsp; These operations are available when we refer to "Expr[#output]" rather than simply "Expr".&amp;nbsp; If we had another extension labeled "#input," we could gain access to both by referring to "Expr[#input | #output]".&lt;br /&gt;&lt;br /&gt;Then we could write:&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&lt;b&gt;interface&lt;/b&gt; Calculator&amp;lt;Int_Expr is Expr[#input | #output]&amp;lt;&amp;gt;&amp;gt; &lt;b&gt;is&lt;/b&gt;&lt;br /&gt;&lt;i&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp; // Now we can use operations from the #input and #output extensions&lt;/i&gt;&lt;br /&gt;&lt;i&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // of Expr when manipulating polymorphic objects of type Int_Expr+&lt;/i&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;  ...&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;b&gt;procedure&lt;/b&gt; Print_Expr_And_Value(Str : Output_Stream; E :  Int_Expr+) &lt;b&gt;is&lt;/b&gt;&lt;br /&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;i&gt;&amp;nbsp; // &lt;/i&gt;&lt;/b&gt;E&lt;i&gt; is of the &lt;/i&gt;polymorphic&lt;i&gt;  type &lt;/i&gt;Int_Expr&lt;i&gt;+&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/i&gt;&lt;br /&gt;&lt;i&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; // &lt;/b&gt;so calls  on its operations (including those from the&lt;/i&gt;&lt;br /&gt;&lt;i&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // interface extensions #input and #output) will dispatch&lt;/i&gt;&lt;b&gt;.&lt;br /&gt;&lt;/b&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;b&gt;const&lt;/b&gt; Result := Evaluate(E);&amp;nbsp;&amp;nbsp; &lt;i&gt;//  dispatching call.&lt;/i&gt;&lt;br /&gt;&lt;i&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &lt;/i&gt;Print(Str, Text_Image(E));&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;i&gt;// Now display the expression&lt;/i&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Print(Str, " = ");&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Print(Str, Result);&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;i&gt;// and then display its value.&lt;/i&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;b&gt;end&lt;/b&gt;  &lt;b&gt;procedure&lt;/b&gt; Print_Expr_And_Value;&lt;br /&gt;&lt;b&gt;end&lt;/b&gt; &lt;b&gt;interface&lt;/b&gt;  Calculator;&lt;br /&gt;&lt;br /&gt;This approach allows the definition of additional &lt;i&gt;dispatching &lt;/i&gt;operations in a modular fashion to an existing type hierarchy, while not disrupting existing users.&amp;nbsp; It seems to provide some advantages over the &lt;i&gt;Visitor&lt;/i&gt; pattern approach as well, as the new operations are not second class citizens requiring the construction of a &lt;i&gt;visitor&lt;/i&gt; object, etc.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8383004232931899216-2003594996874802129?l=parasail-programming-language.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://parasail-programming-language.blogspot.com/feeds/2003594996874802129/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://parasail-programming-language.blogspot.com/2010/08/eliminating-need-for-visitor-pattern-in.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8383004232931899216/posts/default/2003594996874802129'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8383004232931899216/posts/default/2003594996874802129'/><link rel='alternate' type='text/html' href='http://parasail-programming-language.blogspot.com/2010/08/eliminating-need-for-visitor-pattern-in.html' title='Eliminating the need for the Visitor Pattern in ParaSail'/><author><name>Tuck</name><uri>http://www.blogger.com/profile/08866496974237052847</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8383004232931899216.post-7015457539087948385</id><published>2010-07-19T10:35:00.000-04:00</published><updated>2010-07-19T10:35:10.637-04:00</updated><title type='text'>Pointer-free primitives for ParaSail</title><content type='html'>Having pretty much settled on eliminating explicit pointers from &lt;b&gt;ParaSail&lt;/b&gt; (largely to simplify compile-time alias analysis and race-condition elimination), the question is: what sorts of primitive data structures are needed in ParaSail to allow the user to construct essentially arbitrary abstractions on top of the primitives without using explicit pointers?  The ParaSail &lt;b&gt;interface&lt;/b&gt;/&lt;b&gt;class&lt;/b&gt; module already provides a basic kind of basic &lt;i&gt;record&lt;/i&gt; or &lt;i&gt;struct&lt;/i&gt; capability.&amp;nbsp; As mentioned in an earlier posting, we have also suggested the use of the keyword &lt;b&gt;optional&lt;/b&gt; to signify that an object might or might not have a value of its specified type, with its default being a &lt;b&gt;null&lt;/b&gt; value.&amp;nbsp; Internally this could be implemented either with an extra bit to signify &lt;b&gt;null&lt;/b&gt;-ness, or with an implicit level of indirection with a null pointer used to indicate &lt;b&gt;null&lt;/b&gt;-ness (some indirection is clearly necessary for a recursive data structure).&amp;nbsp;&lt;br /&gt;&lt;br /&gt;By using the &lt;b&gt;optional&lt;/b&gt; keyword and the basic &lt;i&gt;record&lt;/i&gt; capability provided by a &lt;b&gt;class&lt;/b&gt;, the user can quite easily construct structures such as &lt;i&gt;linked lists&lt;/i&gt; and &lt;i&gt;binary trees&lt;/i&gt;.&amp;nbsp; However, more complex structures will have to end up falling back on a generalized notion of &lt;i&gt;container&lt;/i&gt; with pointers replaced by the use of generalized &lt;i&gt;indexing&lt;/i&gt;.&amp;nbsp; For example, a &lt;i&gt;directed graph&lt;/i&gt; structure can be represented by a vector of nodes with the edges between the nodes being represented by indices into the vector.&amp;nbsp; To some extent this is going back to a Fortran &lt;i&gt;array-oriented&lt;/i&gt; view of the world.&amp;nbsp; However, with the arrays being &lt;i&gt;extensible&lt;/i&gt;, and the elements of the arrays being arbitrarily complex objects, which themselves are potentially &lt;b&gt;optional&lt;/b&gt; and extensible, there is significantly more flexibility available to the programmer than what the original Fortran arrays provided.&lt;br /&gt;&lt;br /&gt;As a first stab at what primitive container types are needed, it would seem that a basic array type, indexed by integers, and extensible only by whole-array assignment with a longer or shorter array, might be adequate.&amp;nbsp; The elements of the array would be of an arbitrary type, including user-defined types.&amp;nbsp; The whole-array assignment would deal with whatever storage management is necessary to reuse or reclaim the prior value of the object being assigned.&amp;nbsp; The compiler would attempt to arrange to have the new value be created in the storage &lt;i&gt;region&lt;/i&gt; associated with the object to which it will be assigned, so as to avoid having to physically move the new value into that storage region as part of the assignment (see earlier post on &lt;i&gt;region-based storage management&lt;/i&gt;).&amp;nbsp; For example, given:&lt;br /&gt;&lt;pre&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;b&gt;var&lt;/b&gt; X : Basic_Array&amp;lt;...&amp;gt; := Build_Array(Length =&amp;gt; 10);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ...&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; X := Extend_Array(X, New_Length =&amp;gt; 20);&lt;br /&gt;&lt;/pre&gt;the compiler would arrange for the calls on Build_Array and Extend_Array to create their resulting array in a storage region appropriate for X, so that the assignment need not move the created array into that region.&amp;nbsp; Essentially, as part of being called, a function would receive information about the &lt;i&gt;region&lt;/i&gt; in which its result(s) should be allocated.&amp;nbsp; This information would be propagated as necessary to try to minimize the unnecessary movement of data between storage regions as part of an assignment operation.&lt;br /&gt;&lt;br /&gt;It would seem that with this combination of the &lt;i&gt;record&lt;/i&gt;-like capability provided by &lt;b&gt;class&lt;/b&gt;es, the notion of &lt;b&gt;optional&lt;/b&gt;, and something like this Basic_Array type extensible only by &lt;i&gt;whole-array assignment&lt;/i&gt;, we have all of the building blocks needed to create arbitrary data structures in ParaSail without the use of pointers.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8383004232931899216-7015457539087948385?l=parasail-programming-language.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://parasail-programming-language.blogspot.com/feeds/7015457539087948385/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://parasail-programming-language.blogspot.com/2010/07/pointer-free-primitives-for-parasail.html#comment-form' title='3 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8383004232931899216/posts/default/7015457539087948385'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8383004232931899216/posts/default/7015457539087948385'/><link rel='alternate' type='text/html' href='http://parasail-programming-language.blogspot.com/2010/07/pointer-free-primitives-for-parasail.html' title='Pointer-free primitives for ParaSail'/><author><name>Tuck</name><uri>http://www.blogger.com/profile/08866496974237052847</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>3</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8383004232931899216.post-3148080399645578083</id><published>2010-07-18T14:56:00.000-04:00</published><updated>2010-07-18T14:56:28.740-04:00</updated><title type='text'>Updated (A)Yacc grammar for ParaSail</title><content type='html'>Here is an update to the &lt;b&gt;ParaSail&lt;/b&gt; (A)Yacc grammar posted a few weeks ago.&amp;nbsp;&amp;nbsp; This one has no shift/reduce or reduce/reduce conflicts.&amp;nbsp;&amp;nbsp; The "N Queens" example is accepted by this grammar.&amp;nbsp; Below the grammar is the slightly updated (A)Flex lexer:&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;--------------------------------------&lt;br /&gt;-- Tentative YACC Grammar for ParaSail&lt;br /&gt;--------------------------------------&lt;br /&gt;&lt;br /&gt;-- Single-character delimiters --&lt;br /&gt;%token ',' ';' ':' '.'&lt;br /&gt;%token '+' '-' '*' '/' &lt;br /&gt;%token '?'&lt;br /&gt;%token '(' ')' '[' ']' '&amp;lt;' '&amp;gt;' '{' '}'&lt;br /&gt;%token '|' &lt;br /&gt;%token PRIME -- '''&lt;br /&gt;&lt;br /&gt;-- Compound delimiters --&lt;br /&gt;%token COMPARE -- "=?"&lt;br /&gt;%token EQ   -- "=="&lt;br /&gt;%token NEQ  -- "!="&lt;br /&gt;%token GEQ  -- "&amp;gt;="&lt;br /&gt;%token LEQ  -- "&amp;lt;="&lt;br /&gt;%token POWER  -- "**"&lt;br /&gt;%token ASSIGN -- ":="&lt;br /&gt;%token SWAP   -- ":=:"&lt;br /&gt;%token DOT_DOT -- ".."&lt;br /&gt;%token DOUBLE_COLON  -- "::"&lt;br /&gt;%token DOUBLE_LEFT_BRACKET  -- "[["&lt;br /&gt;%token DOUBLE_RIGHT_BRACKET -- "]]"&lt;br /&gt;%token REFERS_TO  -- "=&amp;gt;"&lt;br /&gt;%token GIVES    -- "-&amp;gt;"&lt;br /&gt;%token IMPLIES    -- "==&amp;gt;"&lt;br /&gt;%token SEQUENCE   -- ";;"&lt;br /&gt;%token PARALLEL   -- "||"&lt;br /&gt;%token PLUS_ASSIGN -- "+="&lt;br /&gt;%token MINUS_ASSIGN -- "-="&lt;br /&gt;%token TIMES_ASSIGN -- "*="&lt;br /&gt;%token DIVIDE_ASSIGN -- "/="&lt;br /&gt;%token POWER_ASSIGN -- "**="&lt;br /&gt;%token CONCAT_ASSIGN -- "|="&lt;br /&gt;%token AND_ASSIGN -- "and="&lt;br /&gt;%token OR_ASSIGN -- "or="&lt;br /&gt;%token XOR_ASSIGN -- "xor="&lt;br /&gt;&lt;br /&gt;-- Literals --&lt;br /&gt;%token Char_Literal&lt;br /&gt;%token Enum_Literal&lt;br /&gt;%token Integer_Literal &lt;br /&gt;%token Real_Literal&lt;br /&gt;%token String_Literal&lt;br /&gt;&lt;br /&gt;-- Identifier --&lt;br /&gt;%token Identifier &lt;br /&gt;&lt;br /&gt;-- Reserved words --&lt;br /&gt;%token ABS_kw&lt;br /&gt;%token ABSTRACT_kw&lt;br /&gt;%token ALL_kw&lt;br /&gt;%token AND_kw&lt;br /&gt;%token BLOCK_kw&lt;br /&gt;%token CASE_kw&lt;br /&gt;%token CLASS_kw&lt;br /&gt;%token CONCURRENT_kw&lt;br /&gt;%token CONST_kw&lt;br /&gt;%token CONTINUE_kw&lt;br /&gt;%token EACH_kw&lt;br /&gt;%token ELSE_kw&lt;br /&gt;%token ELSIF_kw&lt;br /&gt;%token END_kw&lt;br /&gt;%token EXIT_kw&lt;br /&gt;%token EXPORTS_kw&lt;br /&gt;%token EXTENDS_kw&lt;br /&gt;%token FOR_kw&lt;br /&gt;%token FORWARD_kw&lt;br /&gt;%token FUNCTION_kw&lt;br /&gt;%token IF_kw&lt;br /&gt;%token IMPLEMENTS_kw&lt;br /&gt;%token IMPORT_kw&lt;br /&gt;%token IN_kw&lt;br /&gt;%token INTERFACE_kw&lt;br /&gt;%token IS_kw&lt;br /&gt;%token LOCKED_kw&lt;br /&gt;%token LOOP_kw&lt;br /&gt;%token MOD_kw&lt;br /&gt;%token MUTABLE_kw&lt;br /&gt;%token NEW_kw&lt;br /&gt;%token NOT_kw&lt;br /&gt;%token NULL_kw&lt;br /&gt;%token OF_kw&lt;br /&gt;%token OPERATOR_kw&lt;br /&gt;%token OPTIONAL_kw&lt;br /&gt;%token OR_kw&lt;br /&gt;%token PROCEDURE_kw&lt;br /&gt;%token QUEUED_kw&lt;br /&gt;%token REF_kw&lt;br /&gt;%token REM_kw&lt;br /&gt;%token RETURN_kw&lt;br /&gt;%token REVERSE_kw&lt;br /&gt;%token SELECT_kw&lt;br /&gt;%token SOME_kw&lt;br /&gt;%token THEN_kw&lt;br /&gt;%token TYPE_kw&lt;br /&gt;%token VAR_kw&lt;br /&gt;%token WHILE_kw&lt;br /&gt;%token WITH_kw&lt;br /&gt;%token XOR_kw&lt;br /&gt;&lt;br /&gt;%start module_list&lt;br /&gt;&lt;br /&gt;{ &lt;br /&gt;   subtype yystype is integer;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;%%&lt;br /&gt;&lt;br /&gt;module_list : &lt;br /&gt;    module&lt;br /&gt;  | module_list module&lt;br /&gt;  ;&lt;br /&gt;&lt;br /&gt;module : &lt;br /&gt;    import_clauses interface_declaration ';' &lt;br /&gt;  | import_clauses class_definition ';' &lt;br /&gt;  | import_clauses standalone_operation_definition ';'&lt;br /&gt;  ;&lt;br /&gt;&lt;br /&gt;import_clauses : &lt;br /&gt;  | import_clauses IMPORT_kw qualified_name_list ';'&lt;br /&gt;  ;&lt;br /&gt;&lt;br /&gt;qualified_name_list : &lt;br /&gt;    qualified_name&lt;br /&gt;  | qualified_name_list ',' qualified_name&lt;br /&gt;  ;&lt;br /&gt;&lt;br /&gt;interface_declaration : &lt;br /&gt;   opt_interface_qualifier INTERFACE_kw module_defining_name &lt;br /&gt;     formals_and_implemented_interfaces&lt;br /&gt;     IS_kw&lt;br /&gt;      interface_element_list&lt;br /&gt;   END_kw INTERFACE_kw module_defining_name ;&lt;br /&gt;   &lt;br /&gt;opt_interface_qualifier : interface_qualifier | ;&lt;br /&gt;&lt;br /&gt;interface_qualifier : &lt;br /&gt;    class_qualifier&lt;br /&gt;  | ABSTRACT_kw opt_class_qualifier&lt;br /&gt;  ;&lt;br /&gt;&lt;br /&gt;opt_class_qualifier : class_qualifier | ;&lt;br /&gt;&lt;br /&gt;class_qualifier : CONCURRENT_kw ;&lt;br /&gt;&lt;br /&gt;standalone_operation_definition : &lt;br /&gt;    function_definition&lt;br /&gt;  | procedure_definition&lt;br /&gt;  ;&lt;br /&gt;&lt;br /&gt;formals : '&amp;lt;' opt_module_formal_list '&amp;gt;' ;&lt;br /&gt;&lt;br /&gt;formals_and_implemented_interfaces :&lt;br /&gt;    formals&lt;br /&gt;  | formals implements_list&lt;br /&gt;  | opt_formals EXTENDS_kw interface_name opt_implements_list&lt;br /&gt;  ; &lt;br /&gt;&lt;br /&gt;opt_formals : formals | ;&lt;br /&gt;&lt;br /&gt;opt_implements_list : implements_list | ;&lt;br /&gt;&lt;br /&gt;implements_list : IMPLEMENTS_kw interface_name_list ;&lt;br /&gt;&lt;br /&gt;interface_name_list :&lt;br /&gt;    interface_name&lt;br /&gt;  | interface_name_list ',' interface_name&lt;br /&gt;  ;&lt;br /&gt;&lt;br /&gt;interface_name : module_name | module_instantiation ;&lt;br /&gt;   &lt;br /&gt;module_name : qualified_name ;&lt;br /&gt;&lt;br /&gt;module_defining_name : qualified_name ;&lt;br /&gt;&lt;br /&gt;opt_module_formal_list : module_formal_list | ;&lt;br /&gt;&lt;br /&gt;module_formal_list : &lt;br /&gt;    annotated_module_formal &lt;br /&gt;  | module_formal_list ';' annotated_module_formal &lt;br /&gt;  ;&lt;br /&gt;&lt;br /&gt;annotated_module_formal : &lt;br /&gt;    opt_annotation type_formal opt_annotation&lt;br /&gt;  | opt_annotation operation_formal&lt;br /&gt;  | opt_annotation value_formal opt_annotation&lt;br /&gt;  ;&lt;br /&gt;&lt;br /&gt;opt_annotation : annotation | ;&lt;br /&gt;&lt;br /&gt;type_formal : &lt;br /&gt;    Identifier IS_kw module_instantiation &lt;br /&gt;  | module_instantiation &lt;br /&gt;  ;&lt;br /&gt;&lt;br /&gt;operation_formal : operation_declaration ;&lt;br /&gt;&lt;br /&gt;value_formal : &lt;br /&gt;    id_list ':' type_specifier &lt;br /&gt;  | id_list ':' type_specifier ASSIGN simple_expression  -- to avoid use of '&amp;gt;'&lt;br /&gt;  ;&lt;br /&gt;&lt;br /&gt;id_list : &lt;br /&gt;    Identifier&lt;br /&gt;  | id_list ',' Identifier&lt;br /&gt;  ;&lt;br /&gt;&lt;br /&gt;type_name : &lt;br /&gt;    qualified_name &lt;br /&gt;  | polymorphic_type_name&lt;br /&gt;  ;&lt;br /&gt;&lt;br /&gt;polymorphic_type_name : qualified_name '+' ;&lt;br /&gt;&lt;br /&gt;qualified_name : &lt;br /&gt;    Identifier &lt;br /&gt;  | qualified_name DOUBLE_COLON Identifier ;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;module_instantiation : &lt;br /&gt;  module_name '&amp;lt;' opt_module_actual_list '&amp;gt;' ;&lt;br /&gt;&lt;br /&gt;opt_module_actual_list : module_actual_list | ;&lt;br /&gt;&lt;br /&gt;module_actual_list :&lt;br /&gt;    module_actual &lt;br /&gt;  | module_actual_list ',' module_actual &lt;br /&gt;  ;&lt;br /&gt;&lt;br /&gt;module_actual : &lt;br /&gt;    simple_type_specifier_or_expression&lt;br /&gt;  | Identifier REFERS_TO simple_type_specifier_or_expression&lt;br /&gt;  ;&lt;br /&gt;&lt;br /&gt;-- simple_expression subsumes simple type_name in this rule&lt;br /&gt;simple_type_specifier_or_expression : &lt;br /&gt;    qualified_name annotation      -- polymorphic type name not allowed here&lt;br /&gt;  | simple_expression              -- simple_expr to avoid problems with '&amp;gt;'&lt;br /&gt;  | module_instantiation&lt;br /&gt;  ;&lt;br /&gt;  &lt;br /&gt;annotated_type_specifier : &lt;br /&gt;    type_specifier&lt;br /&gt;  | type_specifier annotation&lt;br /&gt;  ;&lt;br /&gt;&lt;br /&gt;type_specifier : &lt;br /&gt;    opt_CONCURRENT_kw type_name &lt;br /&gt;  | opt_CONCURRENT_kw module_instantiation &lt;br /&gt;  ;&lt;br /&gt;&lt;br /&gt;opt_CONCURRENT_kw : CONCURRENT_kw | ;&lt;br /&gt;&lt;br /&gt;interface_element_list : &lt;br /&gt;  | interface_element_list interface_element ';'&lt;br /&gt;  ;&lt;br /&gt;&lt;br /&gt;interface_element : &lt;br /&gt;    operation_declaration &lt;br /&gt;  | object_declaration &lt;br /&gt;  | interface_declaration &lt;br /&gt;  | type_declaration &lt;br /&gt;  ;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;class_definition :&lt;br /&gt;   opt_class_qualifier CLASS_kw module_defining_name &lt;br /&gt;      class_formals_and_implemented_interfaces&lt;br /&gt;   IS_kw&lt;br /&gt;      class_element_list&lt;br /&gt;   END_kw CLASS_kw module_defining_name ;&lt;br /&gt;&lt;br /&gt;class_formals_and_implemented_interfaces :&lt;br /&gt;    formals_and_implemented_interfaces&lt;br /&gt;  | opt_formals EXTENDS_kw Identifier ':' interface_name opt_implements_list&lt;br /&gt;  ; &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;class_element_list : &lt;br /&gt;    local_class_element_list&lt;br /&gt;  EXPORTS_kw &lt;br /&gt;    exported_class_element_list ;&lt;br /&gt;&lt;br /&gt;local_class_element_list :&lt;br /&gt;  | local_class_element_list local_class_element ';'&lt;br /&gt;  ;&lt;br /&gt;&lt;br /&gt;local_class_element : interface_element | exported_class_element ;&lt;br /&gt;  &lt;br /&gt;exported_class_element_list :&lt;br /&gt;  | exported_class_element_list exported_class_element ';'&lt;br /&gt;  ;&lt;br /&gt;&lt;br /&gt;exported_class_element : &lt;br /&gt;    operation_definition &lt;br /&gt;  | object_definition &lt;br /&gt;  | class_definition &lt;br /&gt;  ;&lt;br /&gt;  &lt;br /&gt;   &lt;br /&gt;annotation : '{' annotation_element_list '}' ;&lt;br /&gt;&lt;br /&gt;annotation_element_list : &lt;br /&gt;    annotation_element&lt;br /&gt;  | annotation_element_list ';' annotation_element&lt;br /&gt;  ;&lt;br /&gt;&lt;br /&gt;annotation_element : interface_element | condition | quantified_expression ;&lt;br /&gt;&lt;br /&gt;condition : expression ;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;operation_declaration : &lt;br /&gt;    function_declaration &lt;br /&gt;  | procedure_declaration &lt;br /&gt;  | operator_declaration &lt;br /&gt;  ;&lt;br /&gt;&lt;br /&gt;function_declaration :&lt;br /&gt;  FUNCTION_kw Identifier operation_inputs GIVES operation_outputs ;&lt;br /&gt;&lt;br /&gt;procedure_declaration :&lt;br /&gt;  PROCEDURE_kw Identifier operation_inputs ;&lt;br /&gt;  &lt;br /&gt;operator_declaration :&lt;br /&gt;  OPERATOR_kw operator_designator operation_inputs opt_gives_operation_outputs ;&lt;br /&gt;&lt;br /&gt;opt_gives_operation_outputs : GIVES operation_outputs | ;&lt;br /&gt;  &lt;br /&gt;operator_designator : String_Literal ;&lt;br /&gt;  &lt;br /&gt;operation_inputs :&lt;br /&gt;    simple_operation_input opt_annotation&lt;br /&gt;  | annotation simple_operation_input opt_annotation&lt;br /&gt;  | '(' opt_annotated_operation_input_list ')' opt_annotation&lt;br /&gt;  ;&lt;br /&gt;&lt;br /&gt;simple_operation_input :   -- avoids trailing use of "IS"&lt;br /&gt;    id_list ':' opt_input_modifier simple_operand_type_specifier &lt;br /&gt;  | input_modifier simple_operand_type_specifier &lt;br /&gt;  | simple_operand_type_specifier &lt;br /&gt;  ;&lt;br /&gt;&lt;br /&gt;opt_annotated_operation_input_list : annotated_operation_input_list | ;&lt;br /&gt;&lt;br /&gt;annotated_operation_input_list : &lt;br /&gt;    annotated_operation_input&lt;br /&gt;  | annotated_operation_input_list ';' annotated_operation_input&lt;br /&gt;  ;&lt;br /&gt;&lt;br /&gt;annotated_operation_input : &lt;br /&gt;    operation_input opt_annotation&lt;br /&gt;  | annotation operation_input opt_annotation &lt;br /&gt;  | opt_annotation function_declaration&lt;br /&gt;  | opt_annotation procedure_declaration&lt;br /&gt;  ;&lt;br /&gt;&lt;br /&gt;operation_input : &lt;br /&gt;    id_list ':' opt_input_modifier operand_type_specifier opt_ASSIGN_expression&lt;br /&gt;  | input_modifier operand_type_specifier opt_ASSIGN_expression&lt;br /&gt;  | operand_type_specifier opt_ASSIGN_expression&lt;br /&gt;  ;&lt;br /&gt;&lt;br /&gt;opt_input_modifier : input_modifier | ;&lt;br /&gt;  &lt;br /&gt;simple_operand_type_specifier :&lt;br /&gt;    type_name&lt;br /&gt;  | module_instantiation&lt;br /&gt;  ;&lt;br /&gt;&lt;br /&gt;operand_type_specifier : &lt;br /&gt;    simple_operand_type_specifier&lt;br /&gt;  | Identifier IS_kw module_instantiation &lt;br /&gt;         -- NOTE: Operation can have "type" parameters &lt;br /&gt;         -- such as "Left_Type is Integer&amp;lt;&amp;gt;"&lt;br /&gt;  ;&lt;br /&gt;&lt;br /&gt;input_modifier : &lt;br /&gt;    output_modifier &lt;br /&gt;  | QUEUED_kw opt_output_modifier&lt;br /&gt;  | LOCKED_kw opt_output_modifier&lt;br /&gt;  ;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;operation_outputs : &lt;br /&gt;    simple_operation_output opt_annotation&lt;br /&gt;  | annotation simple_operation_output opt_annotation&lt;br /&gt;  | '(' annotated_operation_output_list ')' opt_annotation&lt;br /&gt;  ;&lt;br /&gt;&lt;br /&gt;simple_operation_output :   -- avoids trailing use of "IS"&lt;br /&gt;    id_list ':' opt_output_modifier simple_operand_type_specifier&lt;br /&gt;  | output_modifier simple_operand_type_specifier&lt;br /&gt;  | simple_operand_type_specifier&lt;br /&gt;  ;&lt;br /&gt;&lt;br /&gt;annotated_operation_output_list :&lt;br /&gt;    annotated_operation_output&lt;br /&gt;  | annotated_operation_output_list ';' annotated_operation_output&lt;br /&gt;  ;&lt;br /&gt;&lt;br /&gt;annotated_operation_output : &lt;br /&gt;    operation_output opt_annotation&lt;br /&gt;  | annotation operation_output opt_annotation &lt;br /&gt;  ;&lt;br /&gt;&lt;br /&gt;operation_output : &lt;br /&gt;    id_list ':' opt_output_modifier operand_type_specifier&lt;br /&gt;  | output_modifier operand_type_specifier &lt;br /&gt;  | operand_type_specifier &lt;br /&gt;  ;&lt;br /&gt;&lt;br /&gt;opt_output_modifier : output_modifier | ;&lt;br /&gt;&lt;br /&gt;output_modifier :  &lt;br /&gt;    OPTIONAL_kw&lt;br /&gt;  | REF_opt_optional_mutable &lt;br /&gt;  | REF_opt_optional_mutable VAR_kw &lt;br /&gt;  | REF_opt_optional_mutable CONST_kw &lt;br /&gt;  ;&lt;br /&gt;&lt;br /&gt;REF_opt_optional_mutable :&lt;br /&gt;    REF_kw&lt;br /&gt;  | REF_kw OPTIONAL_kw&lt;br /&gt;  | REF_kw MUTABLE_kw&lt;br /&gt;  | REF_kw OPTIONAL_kw MUTABLE_kw&lt;br /&gt;  ;&lt;br /&gt;&lt;br /&gt;object_declaration : &lt;br /&gt;    VAR_kw Identifier ':' &lt;br /&gt;      opt_OPTIONAL_kw opt_MUTABLE_kw annotated_type_specifier &lt;br /&gt;      opt_ASSIGN_expression&lt;br /&gt;  | CONST_kw Identifier ':' opt_OPTIONAL_kw annotated_type_specifier &lt;br /&gt;      opt_ASSIGN_expression&lt;br /&gt;  ;&lt;br /&gt;&lt;br /&gt;opt_ASSIGN_expression : ASSIGN expression | ;&lt;br /&gt;   &lt;br /&gt;object_definition :&lt;br /&gt;    CONST_kw Identifier ASSIGN expression&lt;br /&gt;  | VAR_kw Identifier ASSIGN expression&lt;br /&gt;  | CONST_kw Identifier REFERS_TO name&lt;br /&gt;  | VAR_kw Identifier REFERS_TO name&lt;br /&gt;  ;&lt;br /&gt;&lt;br /&gt;opt_OPTIONAL_kw : OPTIONAL_kw | ;&lt;br /&gt;opt_MUTABLE_kw : MUTABLE_kw | ;&lt;br /&gt;&lt;br /&gt;type_declaration : &lt;br /&gt;    TYPE_kw Identifier IS_kw opt_NEW_kw annotated_type_specifier ;&lt;br /&gt;&lt;br /&gt;opt_NEW_kw : NEW_kw | ;&lt;br /&gt;&lt;br /&gt;operation_definition : &lt;br /&gt;    function_definition &lt;br /&gt;  | procedure_definition &lt;br /&gt;  | operator_definition &lt;br /&gt;  ;&lt;br /&gt;&lt;br /&gt;function_definition : &lt;br /&gt;  function_declaration IS_kw &lt;br /&gt;     statement_list_with_semi &lt;br /&gt;  END_kw FUNCTION_kw Identifier ;&lt;br /&gt;&lt;br /&gt;procedure_definition : &lt;br /&gt;  procedure_declaration IS_kw &lt;br /&gt;     statement_list_with_semi &lt;br /&gt;  END_kw PROCEDURE_kw Identifier ;&lt;br /&gt;&lt;br /&gt;operator_definition : &lt;br /&gt;  operator_declaration IS_kw &lt;br /&gt;     statement_list_with_semi &lt;br /&gt;  END_kw OPERATOR_kw Identifier  ;&lt;br /&gt;&lt;br /&gt;statement_list_opt_semi :&lt;br /&gt;    statement_sequence&lt;br /&gt;  | statement_list_with_semi&lt;br /&gt;  ;&lt;br /&gt;&lt;br /&gt;statement_list_with_semi : &lt;br /&gt;    statement_sequence_with_semi&lt;br /&gt;  | statement_list_opt_semi PARALLEL statement_sequence_with_semi&lt;br /&gt;  ;&lt;br /&gt;&lt;br /&gt;statement_list :                -- "||" is lower precedence than ";" and ";;"&lt;br /&gt;    statement_sequence&lt;br /&gt;  | statement_list_opt_semi PARALLEL statement_sequence&lt;br /&gt;  ;&lt;br /&gt;&lt;br /&gt;statement_sequence_with_semi : statement_sequence ';' ;&lt;br /&gt;&lt;br /&gt;statement_sequence :&lt;br /&gt;    annotated_statement&lt;br /&gt;  | statement_sequence SEQUENCE annotated_statement&lt;br /&gt;  | statement_sequence_with_semi SEQUENCE annotated_statement&lt;br /&gt;  | statement_sequence_with_semi annotated_statement&lt;br /&gt;  ;&lt;br /&gt;  &lt;br /&gt;annotated_statement : &lt;br /&gt;    opt_annotation local_declaration  &lt;br /&gt;            -- NOTE: these already allow trailing annotations&lt;br /&gt;  | opt_annotation statement opt_annotation&lt;br /&gt;  ;&lt;br /&gt;&lt;br /&gt;statement : &lt;br /&gt;    local_definition &lt;br /&gt;  | simple_statement &lt;br /&gt;  | label compound_statement&lt;br /&gt;  | compound_statement&lt;br /&gt;  -- NOTE: now will use BLOCK instead of: '(' statement_list_opt_semi ')' &lt;br /&gt;  ;&lt;br /&gt;&lt;br /&gt;opt_label : label | ;&lt;br /&gt;&lt;br /&gt;simple_statement :&lt;br /&gt;    name assign_operator expression&lt;br /&gt;  | name SWAP name&lt;br /&gt;  | name '(' opt_operation_actual_list ')'&lt;br /&gt;  | '(' operation_actual_list ')' ASSIGN expression  -- multiple assignment&lt;br /&gt;  | RETURN_kw expression&lt;br /&gt;  | RETURN_kw opt_WITH_values &lt;br /&gt;  | CONTINUE_kw LOOP_kw opt_id opt_WITH_values &lt;br /&gt;  | EXIT_kw compound_statement_kind opt_id opt_WITH_values&lt;br /&gt;  ;&lt;br /&gt;&lt;br /&gt;opt_operation_actual_list : operation_actual_list | ;&lt;br /&gt;&lt;br /&gt;opt_WITH_values : WITH_values | ;&lt;br /&gt;&lt;br /&gt;WITH_values : WITH_kw '(' operation_actual_list ')' ;&lt;br /&gt;&lt;br /&gt;opt_id : Identifier | ;&lt;br /&gt;&lt;br /&gt;compound_statement_kind : LOOP_kw | IF_kw | CASE_kw | SELECT_kw | BLOCK_kw ;&lt;br /&gt;&lt;br /&gt;local_declaration : &lt;br /&gt;    operation_declaration &lt;br /&gt;  | type_declaration &lt;br /&gt;  | object_declaration&lt;br /&gt;  ;&lt;br /&gt;&lt;br /&gt;local_definition :&lt;br /&gt;    object_definition &lt;br /&gt;  | operation_definition &lt;br /&gt;  ;&lt;br /&gt;&lt;br /&gt;label : '*' Identifier '*' ;&lt;br /&gt;&lt;br /&gt;compound_statement :&lt;br /&gt;    if_statement&lt;br /&gt;  | case_statement&lt;br /&gt;  | while_loop_statement&lt;br /&gt;  | for_loop_statement&lt;br /&gt;  | block_statement &lt;br /&gt;  | select_statement&lt;br /&gt;  ;&lt;br /&gt;&lt;br /&gt;if_statement : &lt;br /&gt;  IF_kw condition THEN_kw &lt;br /&gt;     statement_list_with_semi&lt;br /&gt;  elsif_list&lt;br /&gt;  opt_else&lt;br /&gt;  END_kw IF_kw opt_id opt_WITH_values ;&lt;br /&gt;&lt;br /&gt;elsif_list : &lt;br /&gt;  | elsif_list elsif_clause&lt;br /&gt;  ;&lt;br /&gt;&lt;br /&gt;elsif_clause :&lt;br /&gt;  ELSIF_kw condition THEN_kw&lt;br /&gt;     statement_list_with_semi ;&lt;br /&gt;&lt;br /&gt;opt_else : ELSE_kw statement_list_with_semi | ;&lt;br /&gt;&lt;br /&gt;case_statement : &lt;br /&gt;  CASE_kw expression OF_kw&lt;br /&gt;    case_alt_list&lt;br /&gt;    opt_default_alt&lt;br /&gt;  END_kw CASE_kw opt_id opt_WITH_values ;&lt;br /&gt;&lt;br /&gt;case_alt_list : &lt;br /&gt;    case_alt&lt;br /&gt;  | case_alt_list case_alt&lt;br /&gt;  ;&lt;br /&gt;&lt;br /&gt;case_alt :&lt;br /&gt;    '[' choice_list ']' REFERS_TO statement_list_with_semi ;&lt;br /&gt;&lt;br /&gt;choice_list : &lt;br /&gt;    choice  &lt;br /&gt;  | choice_list '|' choice &lt;br /&gt;  ;&lt;br /&gt;&lt;br /&gt;choice : term_or_range ;&lt;br /&gt;&lt;br /&gt;opt_default_alt : '[' DOT_DOT ']' REFERS_TO statement_list_with_semi | ;&lt;br /&gt;&lt;br /&gt;while_loop_statement :&lt;br /&gt;  WHILE_kw condition LOOP_kw&lt;br /&gt;    statement_list_with_semi&lt;br /&gt;  END_kw LOOP_kw opt_id opt_WITH_values ;&lt;br /&gt;&lt;br /&gt;for_loop_statement :&lt;br /&gt;  FOR_kw iterator_spec opt_direction LOOP_kw&lt;br /&gt;    statement_list_with_semi&lt;br /&gt;  END_kw LOOP_kw opt_id opt_WITH_values ;&lt;br /&gt;&lt;br /&gt;iterator_spec : &lt;br /&gt;    iterator &lt;br /&gt;  | '(' iterator_list ')'&lt;br /&gt;  ;&lt;br /&gt;&lt;br /&gt;iterator_list :&lt;br /&gt;    iterator&lt;br /&gt;  | iterator_list ';' iterator&lt;br /&gt;  ;&lt;br /&gt;&lt;br /&gt;iterator :&lt;br /&gt;    Identifier IN_kw choice_list&lt;br /&gt;  | EACH_kw Identifier OF_kw expression&lt;br /&gt;  | Identifier ASSIGN expression THEN_kw next_value_list WHILE_kw condition&lt;br /&gt;  | Identifier REFERS_TO name THEN_kw next_name_list WHILE_kw condition&lt;br /&gt;  | Identifier ':' type_specifier ASSIGN expression &lt;br /&gt;  ;&lt;br /&gt;&lt;br /&gt;next_value_list : &lt;br /&gt;    expression &lt;br /&gt;  | next_value_list PARALLEL expression &lt;br /&gt;  ;&lt;br /&gt;&lt;br /&gt;next_name_list : &lt;br /&gt;    name &lt;br /&gt;  | next_name_list PARALLEL name &lt;br /&gt;  ;&lt;br /&gt;&lt;br /&gt;opt_direction : direction | ;&lt;br /&gt;&lt;br /&gt;direction : CONCURRENT_kw | FORWARD_kw | REVERSE_kw ;&lt;br /&gt;&lt;br /&gt;select_statement :&lt;br /&gt;  SELECT_kw &lt;br /&gt;     select_alt_list&lt;br /&gt;  END_kw SELECT_kw opt_id opt_WITH_values ;&lt;br /&gt;&lt;br /&gt;select_alt_list : &lt;br /&gt;    select_alt&lt;br /&gt;  | select_alt_list PARALLEL select_alt&lt;br /&gt;  ;&lt;br /&gt;&lt;br /&gt;select_alt : &lt;br /&gt;  '[' statement_list_opt_semi ']' REFERS_TO statement_sequence_with_semi ;&lt;br /&gt;&lt;br /&gt;block_statement :&lt;br /&gt;  BLOCK_kw&lt;br /&gt;    statement_list_with_semi&lt;br /&gt;  END_kw BLOCK_kw opt_id opt_WITH_values ;&lt;br /&gt; &lt;br /&gt;expression :  &lt;br /&gt;    expression_component&lt;br /&gt;  | expression '|' expression_component&lt;br /&gt;  ;&lt;br /&gt;&lt;br /&gt;expression_component : -- logical operators are non-associative&lt;br /&gt;    comparison_expression&lt;br /&gt;  | comparison_expression logical_operator comparison_expression&lt;br /&gt;  | comparison_expression '?' expression_component ':' expression_component&lt;br /&gt;  ;&lt;br /&gt;&lt;br /&gt;comparison_expression :  -- comparisons are non associative&lt;br /&gt;    simple_expression&lt;br /&gt;  | simple_expression comparison_operator simple_expression&lt;br /&gt;  | simple_expression IN_kw type_or_term_or_range&lt;br /&gt;  | simple_expression NOT_kw IN_kw type_or_term_or_range&lt;br /&gt;  | simple_expression IS_kw NULL_kw&lt;br /&gt;  | simple_expression NOT_kw NULL_kw&lt;br /&gt;  ;&lt;br /&gt;&lt;br /&gt;simple_expression : -- used to avoid use of '&amp;gt;' in module instantiation&lt;br /&gt;    term&lt;br /&gt;  | simple_expression adding_operator term&lt;br /&gt;  ;&lt;br /&gt;&lt;br /&gt;type_or_term_or_range :&lt;br /&gt;    polymorphic_type_name&lt;br /&gt;  | term_or_range       -- includes simple type name&lt;br /&gt;  ;&lt;br /&gt;&lt;br /&gt;term_or_range : &lt;br /&gt;    term&lt;br /&gt;  | term DOT_DOT term  -- avoid ambiguity on use of '+'&lt;br /&gt;  ;&lt;br /&gt;  &lt;br /&gt;term : &lt;br /&gt;    factor&lt;br /&gt;  | term multiplying_operator factor&lt;br /&gt;  ;&lt;br /&gt;&lt;br /&gt;factor : &lt;br /&gt;    primary&lt;br /&gt;  | primary power_operator factor  -- right associative&lt;br /&gt;  | unary_operator factor  -- makes unary ops higher precedence &lt;br /&gt;  ;&lt;br /&gt;&lt;br /&gt;primary :&lt;br /&gt;    name&lt;br /&gt;  | Integer_Literal&lt;br /&gt;  | Real_Literal&lt;br /&gt;  | Char_Literal&lt;br /&gt;  | String_Literal&lt;br /&gt;  | Enum_Literal&lt;br /&gt;  | NULL_kw&lt;br /&gt;  | '(' conditional_expression ')'&lt;br /&gt;  | '(' quantified_expression ')'&lt;br /&gt;  | aggregate&lt;br /&gt;  | DOUBLE_LEFT_BRACKET expression DOUBLE_RIGHT_BRACKET &lt;br /&gt;  ;&lt;br /&gt;  &lt;br /&gt;name :&lt;br /&gt;    qualified_name attribute_list opt_PRIME&lt;br /&gt;  | qualified_name PRIME&lt;br /&gt;  | qualified_name &lt;br /&gt;  | name '(' opt_operation_actual_list ')'&lt;br /&gt;  | name '[' opt_operation_actual_list ']'&lt;br /&gt;  | name '.' selector&lt;br /&gt;  ;&lt;br /&gt;&lt;br /&gt;attribute_list :&lt;br /&gt;    Enum_Literal&lt;br /&gt;  | attribute_list Enum_Literal &lt;br /&gt;  ;&lt;br /&gt;&lt;br /&gt;opt_PRIME : PRIME | ;&lt;br /&gt;&lt;br /&gt;operation_actual_list : &lt;br /&gt;    operation_actual &lt;br /&gt;  | operation_actual_list ',' operation_actual &lt;br /&gt;  ;&lt;br /&gt;&lt;br /&gt;operation_actual : &lt;br /&gt;    expression&lt;br /&gt;  | Identifier REFERS_TO expression &lt;br /&gt;  ;&lt;br /&gt;&lt;br /&gt;selector : Identifier ;&lt;br /&gt;&lt;br /&gt;unary_operator : '+' | '-' | ABS_kw | NOT_kw ;&lt;br /&gt;&lt;br /&gt;adding_operator : '+' | '-' ;&lt;br /&gt;&lt;br /&gt;multiplying_operator : '*' | '/' ;&lt;br /&gt;&lt;br /&gt;power_operator : POWER ;&lt;br /&gt;&lt;br /&gt;assign_operator : &lt;br /&gt;    ASSIGN | PLUS_ASSIGN | MINUS_ASSIGN | TIMES_ASSIGN | DIVIDE_ASSIGN &lt;br /&gt;  | CONCAT_ASSIGN | AND_ASSIGN | OR_ASSIGN | XOR_ASSIGN&lt;br /&gt;  ;&lt;br /&gt;&lt;br /&gt;comparison_operator : COMPARE | EQ | NEQ | '&amp;lt;' | LEQ | '&amp;gt;' | GEQ ;&lt;br /&gt;&lt;br /&gt;logical_operator :&lt;br /&gt;    AND_kw | OR_kw | XOR_kw  &lt;br /&gt;  | AND_kw THEN_kw | OR_kw ELSE_kw | IMPLIES&lt;br /&gt;  ;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;aggregate : class_aggregate | container_aggregate ;&lt;br /&gt;&lt;br /&gt;class_aggregate : '(' opt_operation_actual_list ')' ;&lt;br /&gt;&lt;br /&gt;container_aggregate : '[' opt_container_element_list ']' ;&lt;br /&gt;  &lt;br /&gt;opt_container_element_list : container_element_list | ;&lt;br /&gt;&lt;br /&gt;container_element_list : &lt;br /&gt;    container_element &lt;br /&gt;  | container_element_list ',' container_element &lt;br /&gt;  ;&lt;br /&gt;&lt;br /&gt;container_element : &lt;br /&gt;    expression_component&lt;br /&gt;  | choice_list REFERS_TO filtered_expression_stream &lt;br /&gt;  | DOT_DOT REFERS_TO filtered_expression_stream &lt;br /&gt;  ;&lt;br /&gt;&lt;br /&gt;container_key : expression ;&lt;br /&gt;&lt;br /&gt;filtered_expression_stream : &lt;br /&gt;    expression&lt;br /&gt;  | expression ':' condition&lt;br /&gt;  ;&lt;br /&gt;&lt;br /&gt;conditional_expression :&lt;br /&gt;    if_expression&lt;br /&gt;  | case_expression&lt;br /&gt;  ;&lt;br /&gt;&lt;br /&gt;if_expression : &lt;br /&gt;  IF_kw condition THEN_kw &lt;br /&gt;     expression&lt;br /&gt;  elsif_expr_list&lt;br /&gt;  opt_else_expr ;&lt;br /&gt;&lt;br /&gt;elsif_expr_list : &lt;br /&gt;    elsif_expr_clause&lt;br /&gt;  | elsif_expr_list elsif_expr_clause&lt;br /&gt;  ;&lt;br /&gt;&lt;br /&gt;elsif_expr_clause :&lt;br /&gt;  ELSIF_kw condition THEN_kw expression ;&lt;br /&gt;&lt;br /&gt;opt_else_expr : ELSE_kw expression | ;&lt;br /&gt;&lt;br /&gt;case_expression : &lt;br /&gt;  CASE_kw expression OF_kw&lt;br /&gt;    case_expr_alt_list ;&lt;br /&gt;&lt;br /&gt;case_expr_alt_list : &lt;br /&gt;    case_expr_alt&lt;br /&gt;  | case_expr_alt_list ';' case_expr_alt&lt;br /&gt;  ;&lt;br /&gt;&lt;br /&gt;case_expr_alt : &lt;br /&gt;    '[' choice_list ']' REFERS_TO expression &lt;br /&gt;  | '[' DOT_DOT ']' REFERS_TO expression   -- NOTE: must come last&lt;br /&gt;  ;&lt;br /&gt;&lt;br /&gt;quantified_expression :&lt;br /&gt;    FOR_kw ALL_or_SOME_kw iterator ':' condition ;&lt;br /&gt;&lt;br /&gt;ALL_or_SOME_kw : ALL_kw | SOME_kw ;&lt;br /&gt;&lt;br /&gt;%%&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;package parasail_parser is&lt;br /&gt;&lt;br /&gt;    procedure yyparse;&lt;br /&gt;&lt;br /&gt;    echo : boolean := false;&lt;br /&gt;    number_of_errors : natural := 0;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;end parasail_parser;&lt;br /&gt;&lt;br /&gt;with parasail_tokens, parasail_lex_io, parasail_goto, parasail_shift_reduce;&lt;br /&gt;with parasail_lex, text_io;&lt;br /&gt;&lt;br /&gt;use  parasail_tokens, parasail_lex_io, parasail_goto, parasail_shift_reduce;&lt;br /&gt;use  parasail_lex, text_io;&lt;br /&gt;package body parasail_parser is&lt;br /&gt;&lt;br /&gt;    procedure yyerror(s: in string := "syntax error") is&lt;br /&gt;    begin&lt;br /&gt; number_of_errors := number_of_errors + 1;&lt;br /&gt; put("&amp;lt;&amp;lt;&amp;lt; *** ");&lt;br /&gt; put_line(s);&lt;br /&gt;    end yyerror;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;##%procedure_parse&lt;br /&gt;&lt;br /&gt;end parasail_parser;&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;---------------------------------------------------&lt;br /&gt;And here is the (A)Flex lexer:&lt;br /&gt;---------------------------------------------------&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;%START IDENT Z&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;GRAPHIC_CHAR  [ !"#$%&amp;'()*+,-./0-9:;&amp;lt;=&amp;gt;?@A-Z\[\\\]^_`a-z{|}~]&lt;br /&gt;&lt;br /&gt;STRING_LITERAL  (\"([^\"]|[\\][.])*\")&lt;br /&gt;&lt;br /&gt;CHAR_LITERAL    (\'([^\']|[\\][.])\')&lt;br /&gt;&lt;br /&gt;IDENTIFIER        [a-zA-Z]([_]?[a-zA-Z0-9])*&lt;br /&gt;&lt;br /&gt;  -- The following are used to match all numeric literals.&lt;br /&gt;  -- Note that double underscores are rejected.&lt;br /&gt;DIGIT_SEQUENCE    [0-9]([_]?[0-9])*&lt;br /&gt;HEX_SEQUENCE      [0-9a-fA-F]([_]?[0-9a-fA-F])*&lt;br /&gt;EXPONENT          [Ee][-+]?{DIGIT_SEQUENCE}&lt;br /&gt;&lt;br /&gt;%%&lt;br /&gt;&lt;br /&gt;  -- ParaSail reserved words&lt;br /&gt;"abs"     {ECHO_L; ENTER(Z); return (ABS_kw);}&lt;br /&gt;"abstract" {ECHO_L; ENTER(Z); return (ABSTRACT_kw);}&lt;br /&gt;"all"  {ECHO_L; ENTER(Z); return (ALL_kw);}&lt;br /&gt;"and"  {ECHO_L; ENTER(Z); return (AND_kw);}&lt;br /&gt;"block"  {ECHO_L; ENTER(Z); return (BLOCK_kw);}&lt;br /&gt;"case"  {ECHO_L; ENTER(Z); return (CASE_kw);}&lt;br /&gt;"class"  {ECHO_L; ENTER(Z); return (CLASS_kw);}&lt;br /&gt;"concurrent" {ECHO_L; ENTER(Z); return (CONCURRENT_kw);}&lt;br /&gt;"const"  {ECHO_L; ENTER(Z); return (CONST_kw);}&lt;br /&gt;"continue" {ECHO_L; ENTER(Z); return (CONTINUE_kw);}&lt;br /&gt;"each"  {ECHO_L; ENTER(Z); return (EACH_kw);}&lt;br /&gt;"else"  {ECHO_L; ENTER(Z); return (ELSE_kw);}&lt;br /&gt;"elsif"  {ECHO_L; ENTER(Z); return (ELSIF_kw);}&lt;br /&gt;"end"  {ECHO_L; ENTER(Z); return (END_kw);}&lt;br /&gt;"exit"  {ECHO_L; ENTER(Z); return (EXIT_kw);}&lt;br /&gt;"exports" {ECHO_L; ENTER(Z); return (EXPORTS_kw);}&lt;br /&gt;"extends" {ECHO_L; ENTER(Z); return (EXTENDS_kw);}&lt;br /&gt;"for"  {ECHO_L; ENTER(Z); return (FOR_kw);}&lt;br /&gt;"forward" {ECHO_L; ENTER(Z); return (FORWARD_kw);}&lt;br /&gt;"function" {ECHO_L; ENTER(Z); return (FUNCTION_kw);}&lt;br /&gt;"if"  {ECHO_L; ENTER(Z); return (IF_kw);}&lt;br /&gt;"implements" {ECHO_L; ENTER(Z); return (IMPLEMENTS_kw);}&lt;br /&gt;"import" {ECHO_L; ENTER(Z); return (IMPORT_kw);}&lt;br /&gt;"in"  {ECHO_L; ENTER(Z); return (IN_kw);}&lt;br /&gt;"interface" {ECHO_L; ENTER(Z); return (INTERFACE_kw);}&lt;br /&gt;"is"  {ECHO_L; ENTER(Z); return (IS_kw);}&lt;br /&gt;"locked" {ECHO_L; ENTER(Z); return (LOCKED_kw);}&lt;br /&gt;"loop"  {ECHO_L; ENTER(Z); return (LOOP_kw);}&lt;br /&gt;"mod"  {ECHO_L; ENTER(Z); return (MOD_kw);}&lt;br /&gt;"mutable" {ECHO_L; ENTER(Z); return (MUTABLE_kw);}&lt;br /&gt;"new"  {ECHO_L; ENTER(Z); return (NEW_kw);}&lt;br /&gt;"not"  {ECHO_L; ENTER(Z); return (NOT_kw);}&lt;br /&gt;"null"  {ECHO_L; ENTER(Z); return (NULL_kw);}&lt;br /&gt;"of"  {ECHO_L; ENTER(Z); return (OF_kw);}&lt;br /&gt;"operator" {ECHO_L; ENTER(Z); return (OPERATOR_kw);}&lt;br /&gt;"optional" {ECHO_L; ENTER(Z); return (OPTIONAL_kw);}&lt;br /&gt;"or"  {ECHO_L; ENTER(Z); return (OR_kw);}&lt;br /&gt;"procedure" {ECHO_L; ENTER(Z); return (PROCEDURE_kw);}&lt;br /&gt;"queued" {ECHO_L; ENTER(Z); return (QUEUED_kw);}&lt;br /&gt;"ref"  {ECHO_L; ENTER(Z); return (REF_kw);}&lt;br /&gt;"rem"  {ECHO_L; ENTER(Z); return (REM_kw);}&lt;br /&gt;"return" {ECHO_L; ENTER(Z); return (RETURN_kw);}&lt;br /&gt;"reverse" {ECHO_L; ENTER(Z); return (REVERSE_kw);}&lt;br /&gt;"select" {ECHO_L; ENTER(Z); return (SELECT_kw);}&lt;br /&gt;"some"  {ECHO_L; ENTER(Z); return (SOME_kw);}&lt;br /&gt;"then"  {ECHO_L; ENTER(Z); return (THEN_kw);}&lt;br /&gt;"type"  {ECHO_L; ENTER(Z); return (TYPE_kw);}&lt;br /&gt;"var"  {ECHO_L; ENTER(Z); return (VAR_kw);}&lt;br /&gt;"while"  {ECHO_L; ENTER(Z); return (WHILE_kw);}&lt;br /&gt;"with"  {ECHO_L; ENTER(Z); return (WITH_kw);}&lt;br /&gt;"xor"  {ECHO_L; ENTER(Z); return (XOR_kw);}&lt;br /&gt;&lt;br /&gt;  -- Match all the compound ParaSail delimiters. &lt;br /&gt;"=?"  {ECHO_L; ENTER(Z); return(COMPARE);}&lt;br /&gt;"=="  {ECHO_L; ENTER(Z); return(EQ);}&lt;br /&gt;"!="  {ECHO_L; ENTER(Z); return(NEQ);}&lt;br /&gt;"&amp;gt;="  {ECHO_L; ENTER(Z); return(GEQ);}&lt;br /&gt;"&amp;lt;="  {ECHO_L; ENTER(Z); return(LEQ);}&lt;br /&gt;"**"  {ECHO_L; ENTER(Z); return(POWER);}&lt;br /&gt;":="  {ECHO_L; ENTER(Z); return(ASSIGN);}&lt;br /&gt;":=:"  {ECHO_L; ENTER(Z); return(SWAP);}&lt;br /&gt;".."  {ECHO_L; ENTER(Z); return(DOT_DOT);}&lt;br /&gt;"::"  {ECHO_L; ENTER(Z); return(DOUBLE_COLON);}&lt;br /&gt;"[["  {ECHO_L; ENTER(Z); return(DOUBLE_LEFT_BRACKET);}&lt;br /&gt;"]]"  {ECHO_L; ENTER(Z); return(DOUBLE_RIGHT_BRACKET);}&lt;br /&gt;"=&amp;gt;"  {ECHO_L; ENTER(Z); return(REFERS_TO);}&lt;br /&gt;"-&amp;gt;"  {ECHO_L; ENTER(Z); return(GIVES);}&lt;br /&gt;"==&amp;gt;"  {ECHO_L; ENTER(Z); return(IMPLIES);}&lt;br /&gt;";;"  {ECHO_L; ENTER(Z); return(SEQUENCE);}&lt;br /&gt;"||"  {ECHO_L; ENTER(Z); return(PARALLEL);}&lt;br /&gt;"+="  {ECHO_L; ENTER(Z); return(PLUS_ASSIGN);}&lt;br /&gt;"-="  {ECHO_L; ENTER(Z); return(MINUS_ASSIGN);}&lt;br /&gt;"*="  {ECHO_L; ENTER(Z); return(TIMES_ASSIGN);}&lt;br /&gt;"/="  {ECHO_L; ENTER(Z); return(DIVIDE_ASSIGN);}&lt;br /&gt;"**="  {ECHO_L; ENTER(Z); return(POWER_ASSIGN);}&lt;br /&gt;"|="  {ECHO_L; ENTER(Z); return(CONCAT_ASSIGN);}&lt;br /&gt;"and="  {ECHO_L; ENTER(Z); return(AND_ASSIGN);}&lt;br /&gt;"or="  {ECHO_L; ENTER(Z); return(OR_ASSIGN);}&lt;br /&gt;"xor="  {ECHO_L; ENTER(Z); return(XOR_ASSIGN);}&lt;br /&gt;&lt;br /&gt;  -- Match all the ParaSail single-character delimiters.&lt;br /&gt;&amp;lt;IDENT&amp;gt;\'  {ECHO_L; ENTER(Z);     return(PRIME);}&lt;br /&gt;"("        {ECHO_L; ENTER(Z);     return('(');}&lt;br /&gt;")"        {ECHO_L; ENTER(IDENT); return(')');}&lt;br /&gt;"["        {ECHO_L; ENTER(Z);     return('[');}&lt;br /&gt;"]"        {ECHO_L; ENTER(IDENT); return(']');}&lt;br /&gt;"&amp;lt;"        {ECHO_L; ENTER(Z);     return('&amp;lt;');}&lt;br /&gt;"&amp;gt;"        {ECHO_L; ENTER(Z);     return('&amp;gt;');}&lt;br /&gt;"{"    {ECHO_L; ENTER(Z);   return('{');}&lt;br /&gt;"}"    {ECHO_L; ENTER(Z);   return('}');}&lt;br /&gt;"*"        {ECHO_L; ENTER(Z);     return('*');}&lt;br /&gt;"+"        {ECHO_L; ENTER(Z);     return('+');}&lt;br /&gt;","        {ECHO_L; ENTER(Z);     return(',');}&lt;br /&gt;"-"        {ECHO_L; ENTER(Z);     return('-');}&lt;br /&gt;"."        {ECHO_L; ENTER(Z);     return('.');}&lt;br /&gt;"/"        {ECHO_L; ENTER(Z);     return('/');}&lt;br /&gt;":"        {ECHO_L; ENTER(Z);     return(':');}&lt;br /&gt;";"        {ECHO_L; ENTER(Z);     return(';');}&lt;br /&gt;"|"        {ECHO_L; ENTER(Z);     return('|');}&lt;br /&gt;"?"        {ECHO_L; ENTER(Z);     return('?');}&lt;br /&gt;&lt;br /&gt;  -- The following is used to match all valid ParaSail identifiers&lt;br /&gt;  -- except reserved words. Note that leading digits and underscores&lt;br /&gt;  -- are not allowed and that double underscores are not allowed.&lt;br /&gt;&lt;br /&gt;{IDENTIFIER}       {ECHO_L; ENTER(IDENT);return(Identifier);}&lt;br /&gt;&lt;br /&gt;  -- Enumeration literals&lt;br /&gt;[#]{IDENTIFIER}    {ECHO_L; ENTER(IDENT);return(Enum_Literal);}&lt;br /&gt;&lt;br /&gt;  -- Decimal numeric literals&lt;br /&gt;{DIGIT_SEQUENCE}{EXPONENT}?  {&lt;br /&gt;         ECHO_L; ENTER(Z);&lt;br /&gt;         return(Integer_Literal);}&lt;br /&gt;&lt;br /&gt;{DIGIT_SEQUENCE}[.]{DIGIT_SEQUENCE}{EXPONENT}?  {&lt;br /&gt;         ECHO_L; ENTER(Z);&lt;br /&gt;         return(Real_Literal);}&lt;br /&gt;&lt;br /&gt;  -- Based numeric literals.&lt;br /&gt;&lt;br /&gt;{DIGIT_SEQUENCE}[#]{HEX_SEQUENCE}[#]{EXPONENT}? {&lt;br /&gt;         ECHO_L; ENTER(Z);&lt;br /&gt;         return(Integer_Literal);}&lt;br /&gt;&lt;br /&gt;{DIGIT_SEQUENCE}[#]{HEX_SEQUENCE}[.]{HEX_SEQUENCE}[#]{EXPONENT}? {&lt;br /&gt;         ECHO_L; ENTER(Z);&lt;br /&gt;         return(Real_Literal);}&lt;br /&gt;&lt;br /&gt;"0"[xX]{HEX_SEQUENCE}  {ECHO_L; ENTER(Z); return(Integer_Literal);}&lt;br /&gt;"0"[bB]{DIGIT_SEQUENCE}  {ECHO_L; ENTER(Z); return(Integer_Literal);}&lt;br /&gt;&lt;br /&gt;  -- Match all valid character literals.  See Ada LRM 2.6.&lt;br /&gt;&lt;br /&gt;&amp;lt;Z&amp;gt;{CHAR_LITERAL}      {ECHO_L; ENTER(Z); return(Char_Literal);}&lt;br /&gt;&lt;br /&gt;  -- Match all valid string literals.  See Ada LRM 2.6.&lt;br /&gt;&lt;br /&gt;{STRING_LITERAL}                {ECHO_L; ENTER(Z); return(String_Literal);}&lt;br /&gt;&lt;br /&gt;"//".*    {ECHO_L;}           -- ignore comments to end-of-line&lt;br /&gt;&lt;br /&gt;"--".*    {ECHO_L;}           -- ignore comments to end-of-line&lt;br /&gt;&lt;br /&gt;  -- The following matches all whitespace.  Except for vertical tabs.  AFLEX,&lt;br /&gt;  -- ALEX and LEX does not support vertical tabs.  This causes use to fail&lt;br /&gt;  -- when parsing some of the ACVC Btests.&lt;br /&gt;&lt;br /&gt;[ \r\t\f]+ {ECHO_L;}        -- ignore spaces,Carriage returns,tabs,form feeds&lt;br /&gt;&lt;br /&gt;  -- The following matches all new lines.&lt;br /&gt;&lt;br /&gt;[\n]       {ECHO_L; linenum;}&lt;br /&gt;&lt;br /&gt;  -- The following matches everything else and prints an error message&lt;br /&gt;  -- indicating that something unexpected was found.&lt;br /&gt;&lt;br /&gt;.          {ECHO_L; &lt;br /&gt;            text_io.put_line("?? lexical error '" &amp; &lt;br /&gt;       parasail_lex_dfa.yytext &amp; "' ??");&lt;br /&gt;     num_errors := num_errors + 1;}&lt;br /&gt;&lt;br /&gt;%%&lt;br /&gt;&lt;br /&gt;with parasail_tokens; &lt;br /&gt;use  parasail_tokens;&lt;br /&gt;use text_io;&lt;br /&gt;&lt;br /&gt;package parasail_lex is&lt;br /&gt;  &lt;br /&gt;  lines      : positive := 1;&lt;br /&gt;  num_errors     : natural := 0;&lt;br /&gt;  Trace          : Boolean := False;&lt;br /&gt;&lt;br /&gt;  procedure ECHO_L; --local version_of define_string.&lt;br /&gt;  procedure linenum; &lt;br /&gt;&lt;br /&gt;  function yylex return token;&lt;br /&gt;&lt;br /&gt;end parasail_lex;&lt;br /&gt;&lt;br /&gt;package body parasail_lex is&lt;br /&gt;&lt;br /&gt;  procedure ECHO_L is&lt;br /&gt;  --&lt;br /&gt;  -- Local version of the  define string.&lt;br /&gt;  -- &lt;br /&gt;  begin&lt;br /&gt;-----    if Trace then&lt;br /&gt;-----      TEXT_IO.PUT_Line("Token :" &amp; YYTEXT &amp; ":");&lt;br /&gt;-----    end if;&lt;br /&gt; text_io.put(yytext);&lt;br /&gt;  end ECHO_L;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;  procedure linenum is&lt;br /&gt;    line_number_string : constant string :=&lt;br /&gt;          integer'image ( lines );&lt;br /&gt;  begin&lt;br /&gt;    lines := lines + 1;&lt;br /&gt;    put(line_number_string);&lt;br /&gt;    for i in 1 .. 5 - integer ( line_number_string'length ) loop&lt;br /&gt;      text_io.put(" ");&lt;br /&gt;    end loop;&lt;br /&gt;&lt;br /&gt;  end linenum;&lt;br /&gt;&lt;br /&gt;##&lt;br /&gt;&lt;br /&gt;end parasail_lex;&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8383004232931899216-3148080399645578083?l=parasail-programming-language.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://parasail-programming-language.blogspot.com/feeds/3148080399645578083/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://parasail-programming-language.blogspot.com/2010/07/updated-ayacc-grammar-for-parasail.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8383004232931899216/posts/default/3148080399645578083'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8383004232931899216/posts/default/3148080399645578083'/><link rel='alternate' type='text/html' href='http://parasail-programming-language.blogspot.com/2010/07/updated-ayacc-grammar-for-parasail.html' title='Updated (A)Yacc grammar for ParaSail'/><author><name>Tuck</name><uri>http://www.blogger.com/profile/08866496974237052847</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8383004232931899216.post-4661554429576553041</id><published>2010-07-17T23:33:00.003-04:00</published><updated>2010-07-18T13:37:44.192-04:00</updated><title type='text'>N Queens Problem in ParaSail</title><content type='html'>Here is a (parallel) solution to the "N Queens" problem in &lt;b&gt;ParaSail&lt;/b&gt;, where we try to place N queens on an NxN chess board such that none of them can take each other.  This takes the idea of using the "continue" statement as a kind of implicit recursion to its natural conclusion.&amp;nbsp; This presumes you can turn a "normal" data structure like Vector&amp;lt;&amp;gt; into a concurrent data structure by using the keyword "concurrent," which presumably means that locking is used on all operations to support concurrency.&amp;nbsp; It is debatable whether this use of a "continue" statement to effectively start the next iteration of a loop almost like a recursive call is easier or harder to understand than true recursion.&amp;nbsp; &lt;br /&gt;&lt;br /&gt;&lt;pre&gt;&lt;b&gt;interface&lt;/b&gt; N_Queens &amp;lt;N : Univ_Integer := 8&amp;gt; &lt;b&gt;is&lt;/b&gt;&lt;br /&gt;    &lt;i&gt;// Place N queens on a checkerboard so that none of them can&lt;br /&gt;    // "take" each other.&lt;/i&gt;&lt;br /&gt;    &lt;b&gt;type&lt;/b&gt; Row &lt;b&gt;is&lt;/b&gt; &lt;b&gt;new&lt;/b&gt; Integer&amp;lt;1, N&amp;gt;;&lt;br /&gt;     &lt;br /&gt;    &lt;b&gt;function&lt;/b&gt; Place_Queens() -&amp;gt; Vector&amp;lt;Vector&amp;lt;Row&amp;gt;&amp;gt; &lt;br /&gt;      &lt;i&gt;{&lt;b&gt;for&lt;/b&gt; &lt;b&gt;all&lt;/b&gt; I &lt;b&gt;in&lt;/b&gt; Place_Queens#range : Length(Place_Queens[I]) == N}&lt;/i&gt;;&lt;br /&gt;&lt;b&gt;end&lt;/b&gt; &lt;b&gt;interface&lt;/b&gt; N_Queens;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;class&lt;/b&gt; N_Queens &amp;lt;N : Univ_Integer := 8&amp;gt; &lt;b&gt;is&lt;/b&gt;&lt;br /&gt;    &lt;b&gt;type&lt;/b&gt; Column &lt;b&gt;is&lt;/b&gt; &lt;b&gt;new&lt;/b&gt; Integer&amp;lt;1, N&amp;gt;;&lt;br /&gt;    &lt;b&gt;type&lt;/b&gt; Sum &lt;b&gt;is&lt;/b&gt; Vector&amp;lt;Boolean, Index =&amp;gt; Integer&amp;lt;2, 2*N&amp;gt;&amp;gt;;&lt;br /&gt;    &lt;b&gt;type&lt;/b&gt; Diff &lt;b&gt;is&lt;/b&gt; Vector&amp;lt;Boolean, Index =&amp;gt; Integer&amp;lt;1-N, N-1&amp;gt;&amp;gt;;&lt;br /&gt;    &lt;br /&gt;&lt;b&gt;exports&lt;/b&gt;&lt;br /&gt;    &lt;br /&gt;    &lt;b&gt;function&lt;/b&gt; Place_Queens() -&amp;gt; Vector&amp;lt;Vector&amp;lt;Row&amp;gt;&amp;gt; &lt;br /&gt;      &lt;i&gt;{&lt;b&gt;for&lt;/b&gt; &lt;b&gt;all&lt;/b&gt; I &lt;b&gt;in&lt;/b&gt; Place_Queens#range : Length(Place_Queens[I]) == N}&lt;/i&gt; is&lt;br /&gt;&lt;i&gt;      // Place N queens on checkerboard so that none of them can "take" each other&lt;/i&gt;&lt;br /&gt;      &lt;b&gt;var&lt;/b&gt; Solutions : &lt;b&gt;concurrent&lt;/b&gt; Vector&amp;lt;Vector&amp;lt;Row&amp;gt;&amp;gt; := [];&lt;br /&gt;      &lt;br /&gt;      *Outer_Loop*&lt;br /&gt;      &lt;b&gt;for&lt;/b&gt; (C : Column := 1; Trial : Vector&amp;lt;Row&amp;gt; := [];&lt;br /&gt;        Diag1 : SSum := [.. =&amp;gt; #false]; Diag2 : Diff := [.. =&amp;gt; #false]) &lt;b&gt;loop&lt;/b&gt;&lt;br /&gt;       &lt;i&gt;   // Iterate over the columns&lt;/i&gt;&lt;br /&gt;        &lt;br /&gt;          &lt;b&gt;for&lt;/b&gt; R &lt;b&gt;in&lt;/b&gt; Row &lt;b&gt;concurrent&lt;/b&gt; &lt;b&gt;loop&lt;/b&gt;&lt;br /&gt;&lt;i&gt;              // Iterate over the rows&lt;/i&gt;&lt;br /&gt;              &lt;b&gt;if&lt;/b&gt; &lt;b&gt;not&lt;/b&gt; Diag1[R + C] &lt;b&gt;and&lt;/b&gt; &lt;b&gt;then&lt;/b&gt; &lt;b&gt;not&lt;/b&gt; Diag2[R - C] &lt;b&gt;then&lt;/b&gt;&lt;br /&gt;                  &lt;i&gt;// Found a Row/Column combination that is not on any diagonal&lt;br /&gt;                  // already occupied.&lt;/i&gt;&lt;br /&gt;                  &lt;b&gt;if&lt;/b&gt; C &amp;lt; N &lt;b&gt;then&lt;/b&gt;&lt;br /&gt;&lt;i&gt;                      // Keep going since haven't reached Nth column.&lt;/i&gt;&lt;br /&gt;                      &lt;b&gt;continue&lt;/b&gt; &lt;b&gt;loop&lt;/b&gt; Outer_Loop &lt;b&gt;with&lt;/b&gt; (C =&amp;gt; C+1, Trial =&amp;gt; Trial | R,&lt;br /&gt;                        Diag1 =&amp;gt; Diag1 | [(R+C) =&amp;gt; #true],&lt;br /&gt;                        Diag2 =&amp;gt; Diag2 | [(R-C) =&amp;gt; #true]);&lt;br /&gt;                  &lt;b&gt;else&lt;/b&gt;&lt;br /&gt;&lt;i&gt;                      // All done, remember trial result.&lt;/i&gt;&lt;br /&gt;                      Solutions |= Trial;&lt;br /&gt;                  &lt;b&gt;end&lt;/b&gt; &lt;b&gt;if&lt;/b&gt;;&lt;br /&gt;              &lt;b&gt;end&lt;/b&gt; &lt;b&gt;if&lt;/b&gt;;&lt;br /&gt;          &lt;b&gt;end&lt;/b&gt; &lt;b&gt;loop&lt;/b&gt;;&lt;br /&gt;          &lt;br /&gt;          &lt;br /&gt;      &lt;b&gt;end&lt;/b&gt; &lt;b&gt;loop&lt;/b&gt; Outer_Loop;&lt;br /&gt;      &lt;b&gt;return&lt;/b&gt; Solutions;&lt;br /&gt;      &lt;br /&gt;    &lt;b&gt;end&lt;/b&gt; &lt;b&gt;function&lt;/b&gt; Place_Queens;&lt;br /&gt;&lt;b&gt;end&lt;/b&gt; &lt;b&gt;class&lt;/b&gt; N_Queens;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8383004232931899216-4661554429576553041?l=parasail-programming-language.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://parasail-programming-language.blogspot.com/feeds/4661554429576553041/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://parasail-programming-language.blogspot.com/2010/07/n-queens-problem-in-parasail.html#comment-form' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8383004232931899216/posts/default/4661554429576553041'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8383004232931899216/posts/default/4661554429576553041'/><link rel='alternate' type='text/html' href='http://parasail-programming-language.blogspot.com/2010/07/n-queens-problem-in-parasail.html' title='N Queens Problem in ParaSail'/><author><name>Tuck</name><uri>http://www.blogger.com/profile/08866496974237052847</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8383004232931899216.post-1341508065956908204</id><published>2010-06-24T00:20:00.001-04:00</published><updated>2010-06-24T00:38:45.217-04:00</updated><title type='text'>Some additional examples of ParaSail</title><content type='html'>Here is a grab-bag of &lt;b&gt;ParaSail&lt;/b&gt; examples, with interspersed musings embedded in the comments.&amp;nbsp; These are acceptable to the ayacc/aflex-based parser posted earlier.&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;import XXYZ;  // TBD: Does this precede the interface?&lt;br /&gt;              //      Any notion of "use" or "using"&lt;br /&gt;interface Hello_World &amp;lt;Standard_IO&amp;lt;&amp;gt;&amp;gt; is&lt;br /&gt;    procedure Main(IO : ref Standard_IO);&lt;br /&gt;end interface Hello_World;&lt;br /&gt;&lt;br /&gt;// TBD: What do enumeration type declarations look like?&lt;br /&gt;//      The first parameter is an id-list type.  The other&lt;br /&gt;//      parameters might be something relating to first/last,&lt;br /&gt;//      'image, etc.&lt;br /&gt;&lt;br /&gt;// TBD: What is the comment syntax?  "//" or "--"?  &lt;br /&gt;//      Modula and ML use "(* *)" but ML folks are suggesting&lt;br /&gt;//      the use of "# " as the start of a comment that goes to the EOL.&lt;br /&gt;//      For some reason I find "#" pretty ugly, especially in the&lt;br /&gt;//      middle of a line.&lt;br /&gt;//      C#, C++, and Java all support "//", as well as the&lt;br /&gt;//      partial line '/* ... */'.  That seems error-prone,&lt;br /&gt;//      so sticking with "//" by itself seems simplest.&lt;br /&gt;//      Also "--" means decrement to half the world.&lt;br /&gt;&lt;br /&gt;// Syntax:  module::module, type::operation, type::nested_entity,&lt;br /&gt;//          object.component, object.operation [equiv to type::operation(object, ...)]&lt;br /&gt;&lt;br /&gt;// TBD: When a non-abstract interface has no module parameters, does that mean&lt;br /&gt;//      the module name can be used directly as a type name?  Or are the "&amp;lt;&amp;gt;"&lt;br /&gt;//      mandatory?  Can we say "interface Univ_Enumeration&amp;lt;&amp;gt; is ..."&lt;br /&gt;&lt;br /&gt;// TBD: Should we make aggregates usable when outside the associated class?&lt;br /&gt;//      What about "extension" aggregates?  Operator "aggregate"?&lt;br /&gt;&lt;br /&gt;// TBD: Get rid of "subtype" and just use "type Blah is ..." or "type Blah is new ..."&lt;br /&gt;//      "subtype" is a relationship, not a kind of entity.&lt;br /&gt;&lt;br /&gt;interface Std &amp;lt;&amp;gt; is&lt;br /&gt;&lt;br /&gt;    abstract interface Any&amp;lt;&amp;gt; is&lt;br /&gt;        operator "end" (Obj : ref var Any);&lt;br /&gt;    end interface Any;&lt;br /&gt;    &lt;br /&gt;    abstract interface Assignable&amp;lt;&amp;gt; extends Any is&lt;br /&gt;        operator "copy" Assignable -&amp;gt; Assignable;&lt;br /&gt;    end interface Assignable;&lt;br /&gt;&lt;br /&gt;    -- type Univ_Enumeration is ...; // type with all enumerals&lt;br /&gt;    &lt;br /&gt;    type Boolean is Enum &amp;lt;[#false, #true]&amp;gt;; // True or False&lt;br /&gt;    type Ordering is Enum &amp;lt;[#less, #equal, #greater, #unordered]&amp;gt;;&lt;br /&gt;&lt;br /&gt;    -- type Univ_Integer is ...; // infinite precision integers with +/- inf&lt;br /&gt;    -- type Univ_Real is ...;    // infinite precision rational numbers &lt;br /&gt;         // with +/- zero and inf&lt;br /&gt;    -- type Univ_Character is ...;  // ISO 10646, 31-bit character&lt;br /&gt;    -- type Univ_String is ...;  // UTF-32&lt;br /&gt;    &lt;br /&gt;    &lt;br /&gt;end interface Std;&lt;br /&gt;&lt;br /&gt;interface Std::Integer&amp;lt;First, Last : Univ_Integer&amp;gt; is&lt;br /&gt;    operator "from_univ"(Univ : Univ_Integer {Univ in First .. Last}) &lt;br /&gt;      -&amp;gt; Integer;&lt;br /&gt;    operator "to_univ"(Int : Integer) &lt;br /&gt;      -&amp;gt; Result: Univ_Integer {Result in First .. Last};&lt;br /&gt;&lt;br /&gt;    operator "+"(Left, Right : Integer {[[Left]] + [[Right]] in First .. Last}) &lt;br /&gt;      -&amp;gt; Result : Integer {[[Result]] == [[Left]] + [[Right]]};&lt;br /&gt;end interface Std::Integer;&lt;br /&gt;&lt;br /&gt;// [[x]] means "to_univ"(X), as a nod to the double bracket notation used in&lt;br /&gt;// denotational semantics to define the meaning of an expression in a program.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;abstract interface Std::Ref&amp;lt;Target_Type is Any&amp;lt;&amp;gt;&amp;gt; &lt;br /&gt;is&lt;br /&gt;   function Is_Writable(R : Ref) -&amp;gt; Boolean;&lt;br /&gt;   function Exists(R : Ref) -&amp;gt; Boolean;&lt;br /&gt;   function Fetch(R : Ref {Exists(R)}) -&amp;gt; Target_Type;&lt;br /&gt;   procedure Store(R : Ref {Is_Writable(R)}; &lt;br /&gt;     New_Contents : Target_Type) {Exists(R)};&lt;br /&gt;   procedure Delete(R : Ref {Is_Writable(R)}) {not Exists(R)};&lt;br /&gt;end interface Std::Ref;&lt;br /&gt;&lt;br /&gt;class Hello_World &amp;lt;Context&amp;lt;&amp;gt;; Standard_IO&amp;lt;&amp;gt;&amp;gt; is&lt;br /&gt;  exports&lt;br /&gt;    procedure Main(IO : ref Standard_IO) is&lt;br /&gt;       Put_Line(IO.Output, "Hello World");&lt;br /&gt;    end procedure Main;&lt;br /&gt;end class Hello_World;&lt;br /&gt;&lt;br /&gt;interface String&amp;lt;Character&amp;lt;&amp;gt;; Index is Integer&amp;lt;&amp;gt;&amp;gt; is&lt;br /&gt;    operator "in"(Lit : Univ_String) -&amp;gt; Boolean;&lt;br /&gt;    operator "from_univ"(Lit : Univ_String {Lit in String}) &lt;br /&gt;      -&amp;gt; String;&lt;br /&gt;    operator "to_univ"(Str : String) -&amp;gt; Result : Univ_String&lt;br /&gt;      {Result in String};&lt;br /&gt;    operator "~"(Left, Right : String) -&amp;gt; Result : String&lt;br /&gt;      {Length(Result) == Length(Left) + Length(Right)};&lt;br /&gt;end interface String;&lt;br /&gt;      &lt;br /&gt;interface Standard_IO&amp;lt;Context&amp;lt;&amp;gt;; Input_Stream&amp;lt;&amp;gt;; Output_Stream&amp;lt;&amp;gt;&amp;gt; is&lt;br /&gt;    function Output(Context) -&amp;gt; Output_Stream;&lt;br /&gt;    function Input(Context) -&amp;gt; Input_Stream;&lt;br /&gt;end interface Standard_IO;&lt;br /&gt;&lt;br /&gt;interface Output_Stream&amp;lt;String&amp;lt;&amp;gt;&amp;gt; is&lt;br /&gt;    procedure Put(Output : ref Output_Stream; Char : String::Character);&lt;br /&gt;    procedure Put(Output : ref Output_Stream; Message : String);&lt;br /&gt;    procedure Put_Line(Output : ref Output_Stream; Message : String);&lt;br /&gt;end interface Output_Stream;&lt;br /&gt;&lt;br /&gt;interface Input_Stream&amp;lt;String&amp;lt;&amp;gt;&amp;gt; is&lt;br /&gt;    function Get(Input : ref Input_Stream) -&amp;gt; String::Character;&lt;br /&gt;    function Get_Line(Output : ref Input_Stream) -&amp;gt; String;&lt;br /&gt;end interface Input_Stream;&lt;br /&gt;&lt;br /&gt;interface Integer&amp;lt;First, Last : Univ_Integer&amp;gt; is&lt;br /&gt;    operator "in"(Lit : Univ_Integer) -&amp;gt; Result : Boolean &lt;br /&gt;      {Result == Lit in First .. Last};&lt;br /&gt;    operator "from_univ"(Univ_Integer {Univ_Integer in First .. Last}) &lt;br /&gt;      -&amp;gt; Integer;&lt;br /&gt;    operator "to_univ"(Integer) -&amp;gt; Result : Univ_Integer &lt;br /&gt;      {Result in First .. Last};&lt;br /&gt;    operator "+"(Left, Right : Integer &lt;br /&gt;      {[[Left]] + [[Right]] in First .. Last}) &lt;br /&gt;      -&amp;gt; Result : Integer&lt;br /&gt;        {[[Result]] == [[Left]] + [[Right]]};&lt;br /&gt;    operator "-"(Left, Right : Integer&lt;br /&gt;      {[[Left]] - [[Right]] in First .. Last}) &lt;br /&gt;        -&amp;gt; Integer;&lt;br /&gt;    operator "*"(Left, Right : Integer&lt;br /&gt;      {[[Left]] * [[Right]] in First .. Last}) &lt;br /&gt;        -&amp;gt; Integer;&lt;br /&gt;    operator "/"(Left, Right : Integer&lt;br /&gt;      {[[Left]] / [[Right]] in First .. Last}) &lt;br /&gt;        -&amp;gt; Integer;&lt;br /&gt;    operator "=?"(Left, Right : Integer) -&amp;gt; Ordering;&lt;br /&gt;end interface Integer;&lt;br /&gt;&lt;br /&gt;interface Character&amp;lt;&amp;gt; is&lt;br /&gt;    operator "in"(Lit : Univ_Character) -&amp;gt; Boolean;&lt;br /&gt;    operator "from_univ"(Lit : Univ_Character {Lit in Character}) &lt;br /&gt;      -&amp;gt; Character;&lt;br /&gt;    operator "to_univ"(Char : Character) &lt;br /&gt;      -&amp;gt; Result : Univ_Character &lt;br /&gt;      {Result in Character};&lt;br /&gt;end interface Character;&lt;br /&gt;&lt;br /&gt;interface Vector&amp;lt;Component is Assignable&amp;lt;&amp;gt;; &lt;br /&gt;   First : Univ_Integer := 1;&lt;br /&gt;   Max_Length : Univ_Integer := +inf&amp;gt; is&lt;br /&gt;    function Length(Vec : ref const Vector) -&amp;gt; Univ_Integer &lt;br /&gt;      {Length in 0..Max_Length};&lt;br /&gt;    function Last(Vec : ref const Vector) -&amp;gt; Univ_Integer &lt;br /&gt;      {Last == Length(Vec) + First - 1};&lt;br /&gt;    operator "[]"(Vec : ref Vector; Index : Univ_Integer &lt;br /&gt;      {Index in First..Last(Vec)}) &lt;br /&gt;      -&amp;gt; ref Component_Type;&lt;br /&gt;    operator "~"(Left, Right : Vector) -&amp;gt; Result : Vector &lt;br /&gt;      {Length(Left) + Length(Right) == Length(Result)}; &lt;br /&gt;        // "~" is pronounced "concatenate"&lt;br /&gt;        // or "connect" or "tied to"&lt;br /&gt;        // or "chained to" or "linked to" or ...?&lt;br /&gt;    operator "~"(Left : Vector; Right : Component) -&amp;gt; Result : Vector&lt;br /&gt;      {Length(Left) + 1 == Length(Result)};&lt;br /&gt;    operator "~"(Left : Component; Right : Vector) -&amp;gt; Result : Vector&lt;br /&gt;      {Length(Right) + 1 == Length(Result)};&lt;br /&gt;    operator "~"(Left, Right : Component) -&amp;gt; Result : Vector&lt;br /&gt;      {Length(Result) == 2}; // Do we really need this one?  &lt;br /&gt;                             // Is equivalent to "[Left, Right]"&lt;br /&gt;    operator "null"() -&amp;gt; Result : Vector {Length(Result) == 0};&lt;br /&gt;    procedure Append(Vec : ref mutable Vector; Value : Component)&lt;br /&gt;      {Length(Vec') == Length(Vec) + 1};&lt;br /&gt;    procedure Append(Vec : ref mutable Vector; Other_Vec : Vector)&lt;br /&gt;      {Length(Vec') == Length(Vec) + Length(Other_Vec)}; &lt;br /&gt;                                        // Vec' means new value&lt;br /&gt;                                        // do we prefer "old(...)"?&lt;br /&gt;                                        // How about post(...) and pre(...)?&lt;br /&gt;                                        // or "new(...)" and "old(...)"?&lt;br /&gt;                                        // Since these are appearing in&lt;br /&gt;                                        // a postcondition, it seems&lt;br /&gt;                                        // redundant to say "post" or "new".&lt;br /&gt;                                        // In any case "new" reads better than post.&lt;br /&gt;&lt;br /&gt;    operator ":="(Left : ref var Vector; Right : Vector)&lt;br /&gt;      {Length(Left) == Length(Right)};&lt;br /&gt;      &lt;br /&gt;    operator ":=:"(Left, Right : ref var Vector)&lt;br /&gt;      {Length(Left') == Length(Right) and &lt;br /&gt;       Length(Right') == Length(Left)};&lt;br /&gt;    operator "+"(Left, Right : Vector {Length(Left) == Length(Right)}) &lt;br /&gt;      -&amp;gt; Result : Vector&lt;br /&gt;      {Length(Result) == Length(Left)};  // component-wise addition&lt;br /&gt;    &lt;br /&gt;end interface Vector;&lt;br /&gt;&lt;br /&gt;interface Stack&amp;lt;Component is Assignable&amp;lt;&amp;gt;; &lt;br /&gt;  Size_Type is Integer&amp;lt;&amp;gt;&amp;gt; is&lt;br /&gt;    &lt;br /&gt;    function Max_Stack_Size(S : Stack) -&amp;gt; Size_Type &lt;br /&gt;      {Max_Stack_Size &amp;gt; 0};&lt;br /&gt;    &lt;br /&gt;    function Count(S : Stack) -&amp;gt; Size_Type &lt;br /&gt;      {Count &amp;lt;= Max_Stack_Size(S)};&lt;br /&gt;    &lt;br /&gt;    function Init(Max : Size_Type {Max &amp;gt; 0}) -&amp;gt; Stack &lt;br /&gt;      {Max_Stack_Size(Init) == Max and Count(Init) == 0};&lt;br /&gt;    &lt;br /&gt;    function Is_Empty(S : Stack) -&amp;gt; Boolean&lt;br /&gt;      {Is_Empty == (Count(S) == 0)};&lt;br /&gt;    &lt;br /&gt;    function Is_Full(S : Stack) -&amp;gt; Boolean&lt;br /&gt;      {Is_Full == (Count(S) == Mas_Stack_Size(S))};&lt;br /&gt;      &lt;br /&gt;    function Top(S : Stack {not Is_Empty(S)}) -&amp;gt; Component;&lt;br /&gt;    &lt;br /&gt;    procedure Pop(S : ref var Stack {not Is_Empty(S)}) &lt;br /&gt;      {Count(S') == Count(S) - 1};&lt;br /&gt;      &lt;br /&gt;    procedure Push(S : ref var Stack {not Is_Full(S)}; &lt;br /&gt;      X : Component) {Count(S') == Count(S) + 1};&lt;br /&gt;      &lt;br /&gt;end interface Stack;&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8383004232931899216-1341508065956908204?l=parasail-programming-language.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://parasail-programming-language.blogspot.com/feeds/1341508065956908204/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://parasail-programming-language.blogspot.com/2010/06/some-additional-examples-of-parasail.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8383004232931899216/posts/default/1341508065956908204'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8383004232931899216/posts/default/1341508065956908204'/><link rel='alternate' type='text/html' href='http://parasail-programming-language.blogspot.com/2010/06/some-additional-examples-of-parasail.html' title='Some additional examples of ParaSail'/><author><name>Tuck</name><uri>http://www.blogger.com/profile/08866496974237052847</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8383004232931899216.post-1169279257073545160</id><published>2010-06-23T17:05:00.004-04:00</published><updated>2010-06-23T17:34:52.210-04:00</updated><title type='text'>Flex-based lexical scanner for ParaSail</title><content type='html'>In this entry and the next are Flex and Yacc grammars for the current definition for &lt;b&gt;ParaSail&lt;/b&gt;.&amp;nbsp; They are actually grammars designed for aflex and ayacc, Ada equivalents of flex and yacc produced many years ago by the Arcadia project, so the commenting conventions and the code are for Ada rather than some other language.&amp;nbsp; But hopefully you can make the transformation fairly easily to your language of choice.&lt;br /&gt;&lt;br /&gt;This entry contains the "aflex"-compatible grammar; the next will contain the "ayacc"-compatible grammar. &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;-- Flex-compatible grammar for ParaSail&lt;br /&gt;%START IDENT Z&lt;br /&gt;&lt;br /&gt;STRING_LITERAL&amp;nbsp; (\"([^\"]|[\\][.])*\")&lt;br /&gt;&lt;br /&gt;CHAR_LITERAL&amp;nbsp;&amp;nbsp;&amp;nbsp; (\'([^\']|[\\][.])\')&lt;br /&gt;&lt;br /&gt;IDENTIFIER&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [a-zA-Z]([_]?[a-zA-Z0-9])*&lt;br /&gt;&lt;br /&gt;&amp;nbsp; -- The following are used to match all numeric literals.&lt;br /&gt;&amp;nbsp; -- Note that double underscores are rejected.&lt;br /&gt;DIGIT_SEQUENCE&amp;nbsp;&amp;nbsp;&amp;nbsp; [0-9]([_]?[0-9])*&lt;br /&gt;HEX_SEQUENCE&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [0-9a-fA-F]([_]?[0-9a-fA-F])*&lt;br /&gt;EXPONENT&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; [Ee][-+]?{DIGIT_SEQUENCE}&lt;br /&gt;&lt;br /&gt;%%&lt;br /&gt;&lt;br /&gt;&amp;nbsp; -- ParaSail reserved words&lt;br /&gt;"abs"&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {ECHO_L; ENTER(Z); return (ABS_kw);}&lt;br /&gt;"abstract"&amp;nbsp;&amp;nbsp;&amp;nbsp; {ECHO_L; ENTER(Z); return (ABSTRACT_kw);}&lt;br /&gt;"all"&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {ECHO_L; ENTER(Z); return (ALL_kw);}&lt;br /&gt;"and"&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {ECHO_L; ENTER(Z); return (AND_kw);}&lt;br /&gt;"block"&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {ECHO_L; ENTER(Z); return (BLOCK_kw);}&lt;br /&gt;"case"&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {ECHO_L; ENTER(Z); return (CASE_kw);}&lt;br /&gt;"class"&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {ECHO_L; ENTER(Z); return (CLASS_kw);}&lt;br /&gt;"concurrent"&amp;nbsp;&amp;nbsp;&amp;nbsp; {ECHO_L; ENTER(Z); return (CONCURRENT_kw);}&lt;br /&gt;"const"&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {ECHO_L; ENTER(Z); return (CONST_kw);}&lt;br /&gt;"continue"&amp;nbsp;&amp;nbsp;&amp;nbsp; {ECHO_L; ENTER(Z); return (CONTINUE_kw);}&lt;br /&gt;"each"&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {ECHO_L; ENTER(Z); return (EACH_kw);}&lt;br /&gt;"else"&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {ECHO_L; ENTER(Z); return (ELSE_kw);}&lt;br /&gt;"elsif"&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {ECHO_L; ENTER(Z); return (ELSIF_kw);}&lt;br /&gt;"end"&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {ECHO_L; ENTER(Z); return (END_kw);}&lt;br /&gt;"exit"&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {ECHO_L; ENTER(Z); return (EXIT_kw);}&lt;br /&gt;"exports"&amp;nbsp;&amp;nbsp;&amp;nbsp; {ECHO_L; ENTER(Z); return (EXPORTS_kw);}&lt;br /&gt;"extends"&amp;nbsp;&amp;nbsp;&amp;nbsp; {ECHO_L; ENTER(Z); return (EXTENDS_kw);}&lt;br /&gt;"for"&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {ECHO_L; ENTER(Z); return (FOR_kw);}&lt;br /&gt;"forward"&amp;nbsp;&amp;nbsp;&amp;nbsp; {ECHO_L; ENTER(Z); return (FORWARD_kw);}&lt;br /&gt;"function"&amp;nbsp;&amp;nbsp;&amp;nbsp; {ECHO_L; ENTER(Z); return (FUNCTION_kw);}&lt;br /&gt;"if"&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {ECHO_L; ENTER(Z); return (IF_kw);}&lt;br /&gt;"import"&amp;nbsp;&amp;nbsp;&amp;nbsp; {ECHO_L; ENTER(Z); return (IMPORT_kw);}&lt;br /&gt;"in"&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {ECHO_L; ENTER(Z); return (IN_kw);}&lt;br /&gt;"interface"&amp;nbsp;&amp;nbsp;&amp;nbsp; {ECHO_L; ENTER(Z); return (INTERFACE_kw);}&lt;br /&gt;"is"&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {ECHO_L; ENTER(Z); return (IS_kw);}&lt;br /&gt;"locked"&amp;nbsp;&amp;nbsp;&amp;nbsp; {ECHO_L; ENTER(Z); return (LOCKED_kw);}&lt;br /&gt;"loop"&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {ECHO_L; ENTER(Z); return (LOOP_kw);}&lt;br /&gt;"mod"&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {ECHO_L; ENTER(Z); return (MOD_kw);}&lt;br /&gt;"mutable"&amp;nbsp;&amp;nbsp;&amp;nbsp; {ECHO_L; ENTER(Z); return (MUTABLE_kw);}&lt;br /&gt;"new"&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {ECHO_L; ENTER(Z); return (NEW_kw);}&lt;br /&gt;"not"&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {ECHO_L; ENTER(Z); return (NOT_kw);}&lt;br /&gt;"null"&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {ECHO_L; ENTER(Z); return (NULL_kw);}&lt;br /&gt;"of"&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {ECHO_L; ENTER(Z); return (OF_kw);}&lt;br /&gt;"operator"&amp;nbsp;&amp;nbsp;&amp;nbsp; {ECHO_L; ENTER(Z); return (OPERATOR_kw);}&lt;br /&gt;"optional"&amp;nbsp;&amp;nbsp;&amp;nbsp; {ECHO_L; ENTER(Z); return (OPTIONAL_kw);}&lt;br /&gt;"or"&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {ECHO_L; ENTER(Z); return (OR_kw);}&lt;br /&gt;"procedure"&amp;nbsp;&amp;nbsp;&amp;nbsp; {ECHO_L; ENTER(Z); return (PROCEDURE_kw);}&lt;br /&gt;"queued"&amp;nbsp;&amp;nbsp;&amp;nbsp; {ECHO_L; ENTER(Z); return (QUEUED_kw);}&lt;br /&gt;"ref"&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {ECHO_L; ENTER(Z); return (REF_kw);}&lt;br /&gt;"rem"&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {ECHO_L; ENTER(Z); return (REM_kw);}&lt;br /&gt;"return"&amp;nbsp;&amp;nbsp;&amp;nbsp; {ECHO_L; ENTER(Z); return (RETURN_kw);}&lt;br /&gt;"reverse"&amp;nbsp;&amp;nbsp;&amp;nbsp; {ECHO_L; ENTER(Z); return (REVERSE_kw);}&lt;br /&gt;"select"&amp;nbsp;&amp;nbsp;&amp;nbsp; {ECHO_L; ENTER(Z); return (SELECT_kw);}&lt;br /&gt;"some"&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {ECHO_L; ENTER(Z); return (SOME_kw);}&lt;br /&gt;"then"&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {ECHO_L; ENTER(Z); return (THEN_kw);}&lt;br /&gt;"type"&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {ECHO_L; ENTER(Z); return (TYPE_kw);}&lt;br /&gt;"var"&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {ECHO_L; ENTER(Z); return (VAR_kw);}&lt;br /&gt;"while"&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {ECHO_L; ENTER(Z); return (WHILE_kw);}&lt;br /&gt;"with"&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {ECHO_L; ENTER(Z); return (WITH_kw);}&lt;br /&gt;"xor"&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {ECHO_L; ENTER(Z); return (XOR_kw);}&lt;br /&gt;&lt;br /&gt;&amp;nbsp; -- Match all the compound ParaSail delimiters. &lt;br /&gt;"=?"&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {ECHO_L; ENTER(Z); return(COMPARE);}&lt;br /&gt;"=="&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {ECHO_L; ENTER(Z); return(EQ);}&lt;br /&gt;"!="&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {ECHO_L; ENTER(Z); return(NEQ);}&lt;br /&gt;"&amp;gt;="&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {ECHO_L; ENTER(Z); return(GEQ);}&lt;br /&gt;"&amp;lt;="&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {ECHO_L; ENTER(Z); return(LEQ);}&lt;br /&gt;"**"&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {ECHO_L; ENTER(Z); return(POWER);}&lt;br /&gt;":="&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {ECHO_L; ENTER(Z); return(ASSIGN);}&lt;br /&gt;":=:"&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {ECHO_L; ENTER(Z); return(SWAP);}&lt;br /&gt;".."&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {ECHO_L; ENTER(Z); return(DOT_DOT);}&lt;br /&gt;"::"&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {ECHO_L; ENTER(Z); return(DOUBLE_COLON);}&lt;br /&gt;"[["&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {ECHO_L; ENTER(Z); return(DOUBLE_LEFT_BRACKET);}&lt;br /&gt;"]]"&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {ECHO_L; ENTER(Z); return(DOUBLE_RIGHT_BRACKET);}&lt;br /&gt;"=&amp;gt;"&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {ECHO_L; ENTER(Z); return(REFERS_TO);}&lt;br /&gt;"-&amp;gt;"&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {ECHO_L; ENTER(Z); return(GIVES);}&lt;br /&gt;"==&amp;gt;"&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {ECHO_L; ENTER(Z); return(IMPLIES);}&lt;br /&gt;";;"&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {ECHO_L; ENTER(Z); return(SEQUENCE);}&lt;br /&gt;"||"&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {ECHO_L; ENTER(Z); return(PARALLEL);}&lt;br /&gt;&lt;br /&gt;&amp;nbsp; -- Match all the ParaSail single-character delimiters.&lt;br /&gt;&amp;lt;IDENT&amp;gt;\'&amp;nbsp; {ECHO_L; ENTER(Z);&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return(PRIME);}&lt;br /&gt;"("&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {ECHO_L; ENTER(Z);&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return('(');}&lt;br /&gt;")"&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {ECHO_L; ENTER(IDENT); return(')');}&lt;br /&gt;"["&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {ECHO_L; ENTER(Z);&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return('[');}&lt;br /&gt;"]"&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {ECHO_L; ENTER(IDENT); return(']');}&lt;br /&gt;"&amp;lt;"&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {ECHO_L; ENTER(Z);&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return('&amp;lt;');}&lt;br /&gt;"&amp;gt;"&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {ECHO_L; ENTER(Z);&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return('&amp;gt;');}&lt;br /&gt;"{"&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; {ECHO_L; ENTER(Z);&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp; return('{');}&lt;br /&gt;"}"&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp; {ECHO_L; ENTER(Z);&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp; return('}');}&lt;br /&gt;"*"&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {ECHO_L; ENTER(Z);&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return('*');}&lt;br /&gt;"+"&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {ECHO_L; ENTER(Z);&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return('+');}&lt;br /&gt;","&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {ECHO_L; ENTER(Z);&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return(',');}&lt;br /&gt;"-"&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {ECHO_L; ENTER(Z);&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return('-');}&lt;br /&gt;"."&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {ECHO_L; ENTER(Z);&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return('.');}&lt;br /&gt;"/"&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {ECHO_L; ENTER(Z);&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return('/');}&lt;br /&gt;":"&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {ECHO_L; ENTER(Z);&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return(':');}&lt;br /&gt;";"&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {ECHO_L; ENTER(Z);&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return(';');}&lt;br /&gt;"|"&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {ECHO_L; ENTER(Z);&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return('|');}&lt;br /&gt;"?"&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {ECHO_L; ENTER(Z);&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return('?');}&lt;br /&gt;"~"&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {ECHO_L; ENTER(Z);&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return('~');}&lt;br /&gt;&lt;br /&gt;&amp;nbsp; -- The following is used to match all valid ParaSail identifiers&lt;br /&gt;&amp;nbsp; -- except reserved words. Note that leading digits and underscores&lt;br /&gt;&amp;nbsp; -- are not allowed and that double underscores are not allowed.&lt;br /&gt;&lt;br /&gt;{IDENTIFIER}&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {ECHO_L; ENTER(IDENT);return(Identifier);}&lt;br /&gt;&lt;br /&gt;&amp;nbsp; -- Enumeration literals&lt;br /&gt;[#]{IDENTIFIER}&amp;nbsp;&amp;nbsp;&amp;nbsp; {ECHO_L; ENTER(IDENT);return(Enum_Literal);}&lt;br /&gt;&lt;br /&gt;&amp;nbsp; -- Decimal numeric literals&lt;br /&gt;{DIGIT_SEQUENCE}{EXPONENT}?&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ECHO_L; ENTER(Z);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return(Integer_Literal);}&lt;br /&gt;&lt;br /&gt;{DIGIT_SEQUENCE}[.]{DIGIT_SEQUENCE}{EXPONENT}?&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ECHO_L; ENTER(Z);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return(Real_Literal);}&lt;br /&gt;&lt;br /&gt;&amp;nbsp; -- Based numeric literals.&lt;br /&gt;&lt;br /&gt;{DIGIT_SEQUENCE}[#]{HEX_SEQUENCE}[#]{EXPONENT}? {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ECHO_L; ENTER(Z);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return(Integer_Literal);}&lt;br /&gt;&lt;br /&gt;{DIGIT_SEQUENCE}[#]{HEX_SEQUENCE}[.]{HEX_SEQUENCE}[#]{EXPONENT}? {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; ECHO_L; ENTER(Z);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return(Real_Literal);}&lt;br /&gt;&lt;br /&gt;"0"[xX]{HEX_SEQUENCE}&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {ECHO_L; ENTER(Z); return(Integer_Literal);}&lt;br /&gt;"0"[bB]{DIGIT_SEQUENCE}&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {ECHO_L; ENTER(Z); return(Integer_Literal);}&lt;br /&gt;&lt;br /&gt;&amp;nbsp; -- Match all valid character literals.&lt;br /&gt;&amp;lt;Z&amp;gt;{CHAR_LITERAL}&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; {ECHO_L; ENTER(Z); return(Char_Literal);}&lt;br /&gt;&lt;br /&gt;&amp;nbsp; -- Match all valid string literals.&lt;br /&gt;{STRING_LITERAL}&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {ECHO_L; ENTER(Z); return(String_Literal);}&lt;br /&gt;&lt;br /&gt;"//".*&amp;nbsp;&amp;nbsp;&amp;nbsp; {ECHO_L;}&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; -- ignore comments to end-of-line&lt;br /&gt;&lt;br /&gt;"--".*&amp;nbsp;&amp;nbsp;&amp;nbsp; {ECHO_L;}&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; -- ignore comments to end-of-line&lt;br /&gt;&lt;br /&gt;&amp;nbsp; -- The following matches all whitespace.&amp;nbsp; Except for vertical tabs.&amp;nbsp; AFLEX,&lt;br /&gt;&amp;nbsp; -- ALEX and LEX do not support vertical tabs.&lt;/z&gt;&lt;/ident&gt;&lt;br /&gt;[ \r\t\f]+ {ECHO_L;}&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; -- ignore spaces,Carriage returns,tabs,form feeds&lt;br /&gt;&lt;br /&gt;&amp;nbsp; -- The following matches all new lines.&lt;br /&gt;&lt;br /&gt;[\n]&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {ECHO_L; linenum;}&lt;br /&gt;&lt;br /&gt;&amp;nbsp; -- The following matches everything else and prints an error message&lt;br /&gt;&amp;nbsp; -- indicating that something unexpected was found.&lt;br /&gt;&lt;br /&gt;.&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {ECHO_L; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; text_io.put_line("?? lexical error '" &amp;amp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; parasail_lex_dfa.yytext &amp;amp; "' ??");&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;&amp;nbsp;&amp;nbsp; num_errors := num_errors + 1;}&lt;br /&gt;&lt;br /&gt;%%&lt;br /&gt;with parasail_tokens; &lt;br /&gt;use&amp;nbsp; parasail_tokens;&lt;br /&gt;use text_io;&lt;br /&gt;&lt;br /&gt;package parasail_lex is&lt;br /&gt;&amp;nbsp; &lt;br /&gt;&amp;nbsp; lines&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : positive := 1;&lt;br /&gt;&amp;nbsp; num_errors&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : natural := 0;&lt;br /&gt;&amp;nbsp; Trace&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : Boolean := False;&lt;br /&gt;&lt;br /&gt;&amp;nbsp; procedure ECHO_L; --local version_of define_string.&lt;br /&gt;&amp;nbsp; procedure linenum; &lt;br /&gt;&lt;br /&gt;&amp;nbsp; function yylex return token;&lt;br /&gt;&lt;br /&gt;end parasail_lex;&lt;br /&gt;&lt;br /&gt;package body parasail_lex is&lt;br /&gt;&lt;br /&gt;&amp;nbsp; procedure ECHO_L is&lt;br /&gt;&amp;nbsp; --&lt;br /&gt;&amp;nbsp; -- Local version of the&amp;nbsp; define string.&lt;br /&gt;&amp;nbsp; -- &lt;br /&gt;&amp;nbsp; begin&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; text_io.put(yytext);&lt;br /&gt;&amp;nbsp; end ECHO_L;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp; procedure linenum is&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; line_number_string : constant string :=&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; integer'image ( lines );&lt;br /&gt;&amp;nbsp; begin&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; lines := lines + 1;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; put(line_number_string);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; for i in 1 .. 5 - integer ( line_number_string'length ) loop&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; text_io.put(" ");&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; end loop;&lt;br /&gt;&lt;br /&gt;&amp;nbsp; end linenum;&lt;br /&gt;&lt;br /&gt;##&lt;br /&gt;&lt;br /&gt;end parasail_lex;&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8383004232931899216-1169279257073545160?l=parasail-programming-language.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://parasail-programming-language.blogspot.com/feeds/1169279257073545160/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://parasail-programming-language.blogspot.com/2010/06/flex-based-lexical-scanner-for-parasail.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8383004232931899216/posts/default/1169279257073545160'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8383004232931899216/posts/default/1169279257073545160'/><link rel='alternate' type='text/html' href='http://parasail-programming-language.blogspot.com/2010/06/flex-based-lexical-scanner-for-parasail.html' title='Flex-based lexical scanner for ParaSail'/><author><name>Tuck</name><uri>http://www.blogger.com/profile/08866496974237052847</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8383004232931899216.post-878460941661955841</id><published>2010-06-23T17:05:00.001-04:00</published><updated>2010-06-23T17:05:56.801-04:00</updated><title type='text'>(A)Yacc-based parser for ParaSail</title><content type='html'>Here is the ayacc-compatible grammar for &lt;b&gt;ParaSail&lt;/b&gt; and a simple driver program adapted from an old Ada parser.&amp;nbsp; Again the commenting conventions and the code are in Ada, but it should be straightforward to transform it into some other language.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;--------------------------------------&lt;br /&gt;-- Tentative YACC Grammar for ParaSail&lt;br /&gt;--------------------------------------&lt;br /&gt;&lt;br /&gt;-- Single-character delimiters --&lt;br /&gt;%token ',' ';' ':' '.'&lt;br /&gt;%token '+' '-' '*' '/' &lt;br /&gt;%token '~' '?'&lt;br /&gt;%token '(' ')' '[' ']' '&amp;lt;' '&amp;gt;' '{' '}'&lt;br /&gt;%token '|' &lt;br /&gt;%token PRIME -- '''&lt;br /&gt;&lt;br /&gt;-- Compound delimiters --&lt;br /&gt;%token COMPARE -- "=?"&lt;br /&gt;%token EQ&amp;nbsp;&amp;nbsp; -- "=="&lt;br /&gt;%token NEQ&amp;nbsp; -- "!="&lt;br /&gt;%token GEQ&amp;nbsp; -- "&amp;gt;="&lt;br /&gt;%token LEQ&amp;nbsp; -- "&amp;lt;="&lt;br /&gt;%token POWER&amp;nbsp; -- "**"&lt;br /&gt;%token ASSIGN -- ":="&lt;br /&gt;%token SWAP&amp;nbsp;&amp;nbsp; -- ":=:"&lt;br /&gt;%token DOT_DOT -- ".."&lt;br /&gt;%token DOUBLE_COLON&amp;nbsp; -- "::"&lt;br /&gt;%token DOUBLE_LEFT_BRACKET&amp;nbsp; -- "[["&lt;br /&gt;%token DOUBLE_RIGHT_BRACKET -- "]]"&lt;br /&gt;%token REFERS_TO&amp;nbsp; -- "=&amp;gt;"&lt;br /&gt;%token GIVES&amp;nbsp;&amp;nbsp;&amp;nbsp; -- "-&amp;gt;"&lt;br /&gt;%token IMPLIES&amp;nbsp;&amp;nbsp;&amp;nbsp; -- "==&amp;gt;"&lt;br /&gt;%token SEQUENCE&amp;nbsp;&amp;nbsp; -- ";;"&lt;br /&gt;%token PARALLEL&amp;nbsp;&amp;nbsp; -- "||"&lt;br /&gt;&lt;br /&gt;-- Literals --&lt;br /&gt;%token Char_Literal&lt;br /&gt;%token Enum_Literal&lt;br /&gt;%token Integer_Literal &lt;br /&gt;%token Real_Literal&lt;br /&gt;%token String_Literal&lt;br /&gt;&lt;br /&gt;-- Identifier --&lt;br /&gt;%token Identifier &lt;br /&gt;&lt;br /&gt;-- Reserved words --&lt;br /&gt;%token ABS_kw&lt;br /&gt;%token ABSTRACT_kw&lt;br /&gt;%token ALL_kw&lt;br /&gt;%token AND_kw&lt;br /&gt;%token BLOCK_kw&lt;br /&gt;%token CASE_kw&lt;br /&gt;%token CLASS_kw&lt;br /&gt;%token CONCURRENT_kw&lt;br /&gt;%token CONST_kw&lt;br /&gt;%token CONTINUE_kw&lt;br /&gt;%token EACH_kw&lt;br /&gt;%token ELSE_kw&lt;br /&gt;%token ELSIF_kw&lt;br /&gt;%token END_kw&lt;br /&gt;%token EXIT_kw&lt;br /&gt;%token EXPORTS_kw&lt;br /&gt;%token EXTENDS_kw&lt;br /&gt;%token FOR_kw&lt;br /&gt;%token FORWARD_kw&lt;br /&gt;%token FUNCTION_kw&lt;br /&gt;%token IF_kw&lt;br /&gt;%token IMPORT_kw&lt;br /&gt;%token IN_kw&lt;br /&gt;%token INTERFACE_kw&lt;br /&gt;%token IS_kw&lt;br /&gt;%token LOCKED_kw&lt;br /&gt;%token LOOP_kw&lt;br /&gt;%token MOD_kw&lt;br /&gt;%token MUTABLE_kw&lt;br /&gt;%token NEW_kw&lt;br /&gt;%token NOT_kw&lt;br /&gt;%token NULL_kw&lt;br /&gt;%token OF_kw&lt;br /&gt;%token OPERATOR_kw&lt;br /&gt;%token OPTIONAL_kw&lt;br /&gt;%token OR_kw&lt;br /&gt;%token PROCEDURE_kw&lt;br /&gt;%token QUEUED_kw&lt;br /&gt;%token REF_kw&lt;br /&gt;%token REM_kw&lt;br /&gt;%token RETURN_kw&lt;br /&gt;%token REVERSE_kw&lt;br /&gt;%token SELECT_kw&lt;br /&gt;%token SOME_kw&lt;br /&gt;%token THEN_kw&lt;br /&gt;%token TYPE_kw&lt;br /&gt;%token VAR_kw&lt;br /&gt;%token WHILE_kw&lt;br /&gt;%token WITH_kw&lt;br /&gt;%token XOR_kw&lt;br /&gt;&lt;br /&gt;%start module_list&lt;br /&gt;&lt;br /&gt;{ &lt;br /&gt;&amp;nbsp;&amp;nbsp; subtype yystype is integer;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;%%&lt;br /&gt;&lt;br /&gt;module_list : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; module&lt;br /&gt;&amp;nbsp; | module_list module&lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;module : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; import_clauses interface_declaration ';' &lt;br /&gt;&amp;nbsp; | import_clauses class_definition ';' &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;import_clauses : &lt;br /&gt;&amp;nbsp; | import_clauses IMPORT_kw qualified_name_list ';'&lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;qualified_name_list : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; qualified_name&lt;br /&gt;&amp;nbsp; | qualified_name_list ',' qualified_name&lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;interface_declaration : &lt;br /&gt;&amp;nbsp;&amp;nbsp; opt_ABSTRACT_kw opt_CONCURRENT_kw INTERFACE_kw module_defining_name &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; formals_and_implemented_interfaces&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; IS_kw&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; interface_element_list&lt;br /&gt;&amp;nbsp;&amp;nbsp; END_kw INTERFACE_kw module_defining_name ;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &lt;br /&gt;opt_ABSTRACT_kw :&amp;nbsp; ABSTRACT_kw | ;&lt;br /&gt;&lt;br /&gt;opt_CONCURRENT_kw : CONCURRENT_kw | ;&lt;br /&gt;&lt;br /&gt;formals : '&amp;lt;' opt_module_formal_list '&amp;gt;' ;&lt;br /&gt;&lt;br /&gt;formals_and_implemented_interfaces :&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; formals&lt;br /&gt;&amp;nbsp; | opt_formals EXTENDS_kw interface_name_list&lt;br /&gt;&amp;nbsp; ; &lt;br /&gt;&lt;br /&gt;opt_formals : formals | ;&lt;br /&gt;&lt;br /&gt;interface_name_list :&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; interface_name&lt;br /&gt;&amp;nbsp; | interface_name_list ',' interface_name&lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;interface_name : module_name | module_instantiation ;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &lt;br /&gt;module_defining_name : qualified_name ;&lt;br /&gt;&lt;br /&gt;opt_module_formal_list : module_formal_list | ;&lt;br /&gt;&lt;br /&gt;module_formal_list : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; annotated_module_formal &lt;br /&gt;&amp;nbsp; | module_formal_list ';' annotated_module_formal &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;annotated_module_formal : opt_annotation module_formal opt_annotation ;&lt;br /&gt;&lt;br /&gt;opt_annotation : annotation | ;&lt;br /&gt;&lt;br /&gt;module_formal : type_formal | value_formal ;&lt;br /&gt;&lt;br /&gt;type_formal : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Identifier IS_kw module_instantiation &lt;br /&gt;&amp;nbsp; | module_instantiation &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;value_formal : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; id_list ':' type_name &lt;br /&gt;&amp;nbsp; | id_list ':' type_name ASSIGN simple_expression&amp;nbsp; -- to avoid use of '&amp;gt;'&lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;id_list : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Identifier&lt;br /&gt;&amp;nbsp; | id_list ',' Identifier&lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;type_name : qualified_name ;&lt;br /&gt;&lt;br /&gt;qualified_name : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Identifier &lt;br /&gt;&amp;nbsp; | qualified_name DOUBLE_COLON Identifier ;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;module_instantiation : &lt;br /&gt;&amp;nbsp; module_name '&amp;lt;' opt_module_actual_list '&amp;gt;' ;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;module_name : qualified_name ;&lt;br /&gt;&lt;br /&gt;opt_module_actual_list : module_actual_list | ;&lt;br /&gt;&lt;br /&gt;module_actual_list :&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; module_actual &lt;br /&gt;&amp;nbsp; | module_actual_list ',' module_actual &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;module_actual : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; type_specifier_or_expression&lt;br /&gt;&amp;nbsp; | Identifier REFERS_TO type_specifier_or_expression&lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;-- simple_expression subsumes type_name in this rule&lt;br /&gt;type_specifier_or_expression : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; type_name annotation&lt;br /&gt;&amp;nbsp; | simple_expression&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; -- to avoid problems with '&amp;gt;'&lt;br /&gt;&amp;nbsp; | module_instantiation&lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&amp;nbsp; &lt;br /&gt;type_specifier : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; type_name annotation &lt;br /&gt;&amp;nbsp; | type_name &lt;br /&gt;&amp;nbsp; | module_instantiation &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;interface_element_list : &lt;br /&gt;&amp;nbsp; | interface_element_list interface_element ';'&lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;interface_element : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; operation_declaration &lt;br /&gt;&amp;nbsp; | object_declaration &lt;br /&gt;&amp;nbsp; | interface_declaration &lt;br /&gt;&amp;nbsp; | type_declaration &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;class_definition :&lt;br /&gt;&amp;nbsp;&amp;nbsp; opt_CONCURRENT_kw CLASS_kw module_defining_name &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; formals_and_extended_interface &lt;br /&gt;&amp;nbsp;&amp;nbsp; IS_kw&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; class_element_list&lt;br /&gt;&amp;nbsp;&amp;nbsp; END_kw CLASS_kw module_defining_name ;&lt;br /&gt;&lt;br /&gt;formals_and_extended_interface :&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; formals&lt;br /&gt;&amp;nbsp; | opt_formals EXTENDS_kw interface_name&lt;br /&gt;&amp;nbsp; | opt_formals EXTENDS_kw Identifier ':' interface_name&lt;br /&gt;&amp;nbsp; ; &lt;br /&gt;&lt;br /&gt;&lt;br /&gt;class_element_list : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; local_class_element_list&lt;br /&gt;&amp;nbsp; EXPORTS_kw &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; exported_class_element_list ;&lt;br /&gt;&lt;br /&gt;local_class_element_list :&lt;br /&gt;&amp;nbsp; | local_class_element_list local_class_element ';'&lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;local_class_element : interface_element | exported_class_element ;&lt;br /&gt;&amp;nbsp; &lt;br /&gt;exported_class_element_list :&lt;br /&gt;&amp;nbsp; | exported_class_element_list exported_class_element ';'&lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;exported_class_element : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; operation_definition &lt;br /&gt;&amp;nbsp; | object_definition &lt;br /&gt;&amp;nbsp; | class_definition &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp; &lt;br /&gt;annotation : '{' annotation_element_list '}' ;&lt;br /&gt;&lt;br /&gt;annotation_element_list : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; annotation_element&lt;br /&gt;&amp;nbsp; | annotation_element_list ';' annotation_element&lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;annotation_element : interface_element | condition ;&lt;br /&gt;&lt;br /&gt;condition : expression ;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;operation_declaration : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; function_declaration &lt;br /&gt;&amp;nbsp; | procedure_declaration &lt;br /&gt;&amp;nbsp; | operator_declaration &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;function_declaration :&lt;br /&gt;&amp;nbsp; FUNCTION_kw Identifier operation_inputs GIVES operation_outputs ;&lt;br /&gt;&lt;br /&gt;procedure_declaration :&lt;br /&gt;&amp;nbsp; PROCEDURE_kw Identifier operation_inputs ;&lt;br /&gt;&amp;nbsp; &lt;br /&gt;operator_declaration :&lt;br /&gt;&amp;nbsp; OPERATOR_kw operator_designator operation_inputs opt_gives_operation_outputs ;&lt;br /&gt;&lt;br /&gt;opt_gives_operation_outputs : GIVES operation_outputs | ;&lt;br /&gt;&amp;nbsp; &lt;br /&gt;operator_designator : String_Literal ;&lt;br /&gt;&amp;nbsp; &lt;br /&gt;operation_inputs :&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; annotated_operation_input&lt;br /&gt;&amp;nbsp; | '(' opt_annotated_operation_input_list ')' opt_annotation &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;opt_annotated_operation_input_list : annotated_operation_input_list | ;&lt;br /&gt;&lt;br /&gt;annotated_operation_input_list : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; annotated_operation_input&lt;br /&gt;&amp;nbsp; | annotated_operation_input_list ';' annotated_operation_input&lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;annotated_operation_input : opt_annotation operation_input opt_annotation ;&lt;br /&gt;&lt;br /&gt;operation_input : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; id_list ':' opt_input_modifier operand_type_specifier &lt;br /&gt;&amp;nbsp; | input_modifier operand_type_specifier &lt;br /&gt;&amp;nbsp; | operand_type_specifier &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;opt_input_modifier : input_modifier | ;&lt;br /&gt;&amp;nbsp; &lt;br /&gt;operand_type_specifier : type_name | type_formal ;&lt;br /&gt;&lt;br /&gt;input_modifier : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; output_modifier &lt;br /&gt;&amp;nbsp; | QUEUED_kw opt_output_modifier&lt;br /&gt;&amp;nbsp; | LOCKED_kw opt_output_modifier&lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;operation_outputs : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; annotated_operation_output&lt;br /&gt;&amp;nbsp; | '(' annotated_operation_output_list ')' opt_annotation &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;annotated_operation_output_list :&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; annotated_operation_output&lt;br /&gt;&amp;nbsp; | annotated_operation_output_list ';' annotated_operation_output&lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;annotated_operation_output : opt_annotation operation_output opt_annotation ;&lt;br /&gt;&lt;br /&gt;operation_output : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; id_list ':' opt_output_modifier operand_type_specifier&lt;br /&gt;&amp;nbsp; | output_modifier operand_type_specifier &lt;br /&gt;&amp;nbsp; | operand_type_specifier &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;opt_output_modifier : output_modifier | ;&lt;br /&gt;&lt;br /&gt;output_modifier :&amp;nbsp; &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; REF_opt_optional_mutable &lt;br /&gt;&amp;nbsp; | REF_opt_optional_mutable VAR_kw &lt;br /&gt;&amp;nbsp; | REF_opt_optional_mutable CONST_kw &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;REF_opt_optional_mutable :&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; REF_kw&lt;br /&gt;&amp;nbsp; | REF_kw OPTIONAL_kw&lt;br /&gt;&amp;nbsp; | REF_kw MUTABLE_kw&lt;br /&gt;&amp;nbsp; | REF_kw OPTIONAL_kw MUTABLE_kw&lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;object_declaration : &lt;br /&gt;&amp;nbsp;&amp;nbsp; var_or_const Identifier ':' type_specifier opt_ASSIGN_expression ;&lt;br /&gt;&lt;br /&gt;opt_ASSIGN_expression : ASSIGN expression | ;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &lt;br /&gt;var_or_const : VAR_kw | CONST_kw ;&lt;br /&gt;&lt;br /&gt;object_definition :&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; CONST_kw Identifier opt_colon_type_specifier ASSIGN expression&lt;br /&gt;&amp;nbsp; | VAR_kw Identifier ':' opt_OPTIONAL_kw opt_MUTABLE_kw type_specifier &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; opt_ASSIGN_expression&lt;br /&gt;&amp;nbsp; | VAR_kw Identifier ASSIGN expression &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;opt_colon_type_specifier : ':' type_specifier | ;&lt;br /&gt;&lt;br /&gt;opt_OPTIONAL_kw : OPTIONAL_kw | ;&lt;br /&gt;opt_MUTABLE_kw : MUTABLE_kw | ;&lt;br /&gt;&lt;br /&gt;type_declaration : TYPE_kw Identifier IS_kw opt_NEW_kw type_specifier ;&lt;br /&gt;&lt;br /&gt;opt_NEW_kw : NEW_kw | ;&lt;br /&gt;&lt;br /&gt;operation_definition : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; function_definition &lt;br /&gt;&amp;nbsp; | procedure_definition &lt;br /&gt;&amp;nbsp; | operator_definition &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;function_definition : &lt;br /&gt;&amp;nbsp; function_declaration IS_kw statement_list ';' END_kw FUNCTION_kw Identifier ;&lt;br /&gt;&lt;br /&gt;procedure_definition : &lt;br /&gt;&amp;nbsp; procedure_declaration IS_kw statement_list ';' END_kw PROCEDURE_kw Identifier ;&lt;br /&gt;&lt;br /&gt;operator_definition : &lt;br /&gt;&amp;nbsp; operator_declaration IS_kw statement_list ';' END_kw OPERATOR_kw Identifier&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;statement_list : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; annotated_statement&lt;br /&gt;&amp;nbsp; | statement_list SEQUENCE statement_list&lt;br /&gt;&amp;nbsp; | statement_list ';' statement_list&lt;br /&gt;&amp;nbsp; | statement_list PARALLEL statement_list&lt;br /&gt;&amp;nbsp; | statement_list ';' PARALLEL statement_list&lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&amp;nbsp; &lt;br /&gt;opt_semi : ';' | ;&lt;br /&gt;&lt;br /&gt;annotated_statement : opt_annotation statement opt_annotation ;&lt;br /&gt;&lt;br /&gt;statement : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; local_declaration &lt;br /&gt;&amp;nbsp; | local_definition &lt;br /&gt;&amp;nbsp; | simple_statement &lt;br /&gt;&amp;nbsp; | label compound_statement&lt;br /&gt;&amp;nbsp; | compound_statement&lt;br /&gt;&amp;nbsp; | '(' statement_list opt_semi ')' &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;opt_label : label | ;&lt;br /&gt;&lt;br /&gt;simple_statement :&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; name ASSIGN expression&lt;br /&gt;&amp;nbsp; | name SWAP name&lt;br /&gt;&amp;nbsp; | name '(' opt_operation_actual_list ')'&lt;br /&gt;&amp;nbsp; | RETURN_kw opt_WITH_values &lt;br /&gt;&amp;nbsp; | CONTINUE_kw LOOP_kw opt_id opt_WITH_values &lt;br /&gt;&amp;nbsp; | EXIT_kw compound_statement_kind opt_id opt_WITH_values&lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;opt_operation_actual_list : operation_actual_list | ;&lt;br /&gt;&lt;br /&gt;opt_WITH_values : WITH_values | ;&lt;br /&gt;&lt;br /&gt;WITH_values : WITH_kw '(' operation_actual_list ')' ;&lt;br /&gt;&lt;br /&gt;opt_id : Identifier | ;&lt;br /&gt;&lt;br /&gt;compound_statement_kind : LOOP_kw | IF_kw | CASE_kw | SELECT_kw | BLOCK_kw ;&lt;br /&gt;&lt;br /&gt;local_declaration : operation_declaration | type_declaration ;&lt;br /&gt;&lt;br /&gt;local_definition :&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; object_definition &lt;br /&gt;&amp;nbsp; | operation_definition &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;label : '*' Identifier '*' ;&lt;br /&gt;&lt;br /&gt;compound_statement :&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if_statement&lt;br /&gt;&amp;nbsp; | case_statement&lt;br /&gt;&amp;nbsp; | while_loop_statement&lt;br /&gt;&amp;nbsp; | for_loop_statement&lt;br /&gt;&amp;nbsp; | block_statement &lt;br /&gt;&amp;nbsp; | select_statement&lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;if_statement : &lt;br /&gt;&amp;nbsp; IF_kw condition THEN_kw &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; statement_list ';'&lt;br /&gt;&amp;nbsp; elsif_list&lt;br /&gt;&amp;nbsp; opt_else&lt;br /&gt;&amp;nbsp; END_kw IF_kw opt_id opt_WITH_values ;&lt;br /&gt;&lt;br /&gt;elsif_list : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; elsif_clause&lt;br /&gt;&amp;nbsp; | elsif_list elsif_clause&lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;elsif_clause :&lt;br /&gt;&amp;nbsp; ELSIF_kw condition THEN_kw&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; statement_list ';' ;&lt;br /&gt;&lt;br /&gt;opt_else : ELSE_kw statement_list ';' | ;&lt;br /&gt;&lt;br /&gt;case_statement : &lt;br /&gt;&amp;nbsp; CASE_kw expression OF_kw&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; case_alt_list&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; opt_default_alt&lt;br /&gt;&amp;nbsp; END_kw CASE_kw opt_id opt_WITH_values ;&lt;br /&gt;&lt;br /&gt;case_alt_list : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; case_alt&lt;br /&gt;&amp;nbsp; | case_alt_list case_alt&lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;case_alt :&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; '[' choice_list ']' REFERS_TO statement_list ';' ;&lt;br /&gt;&lt;br /&gt;choice_list : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; choice&amp;nbsp; &lt;br /&gt;&amp;nbsp; | choice_list '|' choice &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;choice : expression_or_range ;&lt;br /&gt;&lt;br /&gt;opt_default_alt : '[' DOT_DOT ']' REFERS_TO statement_list ';' | ;&lt;br /&gt;&lt;br /&gt;while_loop_statement :&lt;br /&gt;&amp;nbsp; WHILE_kw condition LOOP_kw&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; statement_list ';'&lt;br /&gt;&amp;nbsp; END_kw LOOP_kw opt_id opt_WITH_values ;&lt;br /&gt;&lt;br /&gt;for_loop_statement :&lt;br /&gt;&amp;nbsp; FOR_kw iterator_list opt_direction LOOP_kw&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; statement_list ';'&lt;br /&gt;&amp;nbsp; END_kw LOOP_kw opt_id opt_WITH_values ;&lt;br /&gt;&lt;br /&gt;iterator_list : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; iterator &lt;br /&gt;&amp;nbsp; | iterator_list ',' iterator&lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;iterator :&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Identifier IN_kw choice_list&lt;br /&gt;&amp;nbsp; | EACH_kw Identifier OF_kw expression&lt;br /&gt;&amp;nbsp; | Identifier ASSIGN expression THEN_kw next_value_list WHILE_kw condition&lt;br /&gt;&amp;nbsp; | Identifier REFERS_TO name THEN_kw next_name_list WHILE_kw condition&lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;next_value_list : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; expression &lt;br /&gt;&amp;nbsp; | next_value_list PARALLEL expression &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;next_name_list : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; name &lt;br /&gt;&amp;nbsp; | next_name_list PARALLEL name &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;opt_direction : direction | ;&lt;br /&gt;&lt;br /&gt;direction : CONCURRENT_kw | FORWARD_kw | REVERSE_kw ;&lt;br /&gt;&lt;br /&gt;select_statement :&lt;br /&gt;&amp;nbsp; SELECT_kw &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; select_alt_list&lt;br /&gt;&amp;nbsp; END_kw SELECT_kw opt_id opt_WITH_values ;&lt;br /&gt;&lt;br /&gt;select_alt_list : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; select_alt&lt;br /&gt;&amp;nbsp; | select_alt_list PARALLEL select_alt&lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;select_alt : '[' statement_list opt_semi ']' REFERS_TO statement_list opt_semi ;&lt;br /&gt;&lt;br /&gt;block_statement :&lt;br /&gt;&amp;nbsp; BLOCK_kw&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; statement_list ';'&lt;br /&gt;&amp;nbsp; END_kw BLOCK_kw opt_id opt_WITH_values ;&lt;br /&gt;&amp;nbsp;&lt;br /&gt;expression : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; simple_expression&lt;br /&gt;&amp;nbsp; | expression binary_operator expression&lt;br /&gt;&amp;nbsp; | expression IN_kw expression_or_range&lt;br /&gt;&amp;nbsp; | expression NOT_kw IN_kw expression_or_range&lt;br /&gt;&amp;nbsp; | expression '?' expression ':' expression &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;simple_expression :&amp;nbsp; -- used to avoid use of '&amp;gt;' in module instantiation&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; primary&lt;br /&gt;&amp;nbsp; | unary_operator simple_expression&amp;nbsp; -- makes unary ops higher precedence&lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;expression_or_range : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; expression&lt;br /&gt;&amp;nbsp; | expression DOT_DOT expression ;&lt;br /&gt;&amp;nbsp; &lt;br /&gt;primary :&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; name&lt;br /&gt;&amp;nbsp; | Integer_Literal&lt;br /&gt;&amp;nbsp; | Real_Literal&lt;br /&gt;&amp;nbsp; | Char_Literal&lt;br /&gt;&amp;nbsp; | String_Literal&lt;br /&gt;&amp;nbsp; | Enum_Literal&lt;br /&gt;&amp;nbsp; | NULL_kw&lt;br /&gt;&amp;nbsp; | '(' expression ')'&lt;br /&gt;&amp;nbsp; | '(' conditional_expression ')'&lt;br /&gt;&amp;nbsp; | '(' quantified_expression ')'&lt;br /&gt;&amp;nbsp; | aggregate&lt;br /&gt;&amp;nbsp; | DOUBLE_LEFT_BRACKET expression DOUBLE_RIGHT_BRACKET &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&amp;nbsp; &lt;br /&gt;name :&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; qualified_name attribute_list opt_PRIME&lt;br /&gt;&amp;nbsp; | qualified_name PRIME&lt;br /&gt;&amp;nbsp; | qualified_name &lt;br /&gt;&amp;nbsp; | name '(' opt_operation_actual_list ')'&lt;br /&gt;&amp;nbsp; | name '[' opt_operation_actual_list ']'&lt;br /&gt;&amp;nbsp; | name '.' selector&lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;attribute_list :&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Enum_Literal&lt;br /&gt;&amp;nbsp; | attribute_list Enum_Literal &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;opt_PRIME : PRIME | ;&lt;br /&gt;&lt;br /&gt;operation_actual_list : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; operation_actual &lt;br /&gt;&amp;nbsp; | operation_actual_list ',' operation_actual &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;operation_actual : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; expression&lt;br /&gt;&amp;nbsp; | Identifier REFERS_TO expression &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;selector : Identifier ;&lt;br /&gt;&lt;br /&gt;unary_operator : '+' | '-' | ABS_kw | NOT_kw ;&lt;br /&gt;&lt;br /&gt;binary_operator :&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; '+'&amp;nbsp; | '-' | '*'&amp;nbsp; | '/' | POWER | '~' &lt;br /&gt;&amp;nbsp; | COMPARE | EQ | NEQ | '&amp;lt;' | LEQ | '&amp;gt;' | GEQ&lt;br /&gt;&amp;nbsp; | AND_kw | OR_kw | XOR_kw&amp;nbsp; &lt;br /&gt;&amp;nbsp; | AND_kw THEN_kw | OR_kw ELSE_kw | IMPLIES&lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;aggregate : class_aggregate | container_aggregate ;&lt;br /&gt;&lt;br /&gt;class_aggregate : '(' opt_operation_actual_list ')' ;&lt;br /&gt;&lt;br /&gt;container_aggregate : '[' container_element_list ']' ;&lt;br /&gt;&amp;nbsp; &lt;br /&gt;container_element_list : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; container_element &lt;br /&gt;&amp;nbsp; | container_element_list ',' container_element &lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;container_element : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; expression&lt;br /&gt;&amp;nbsp; | choice_list REFERS_TO filtered_expression_stream ;&lt;br /&gt;&lt;br /&gt;container_key : expression ;&lt;br /&gt;&lt;br /&gt;filtered_expression_stream : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; expression_stream&lt;br /&gt;&amp;nbsp; | expression_stream ':' condition&lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;expression_stream : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; expression &lt;br /&gt;&amp;nbsp; | expression_stream '~' expression&lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;conditional_expression :&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if_expression&lt;br /&gt;&amp;nbsp; | case_expression&lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;if_expression : &lt;br /&gt;&amp;nbsp; IF_kw condition THEN_kw &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; expression&lt;br /&gt;&amp;nbsp; elsif_expr_list&lt;br /&gt;&amp;nbsp; opt_else_expr ;&lt;br /&gt;&lt;br /&gt;elsif_expr_list : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; elsif_expr_clause&lt;br /&gt;&amp;nbsp; | elsif_expr_list elsif_expr_clause&lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;elsif_expr_clause :&lt;br /&gt;&amp;nbsp; ELSIF_kw condition THEN_kw expression ;&lt;br /&gt;&lt;br /&gt;opt_else_expr : ELSE_kw expression | ;&lt;br /&gt;&lt;br /&gt;case_expression : &lt;br /&gt;&amp;nbsp; CASE_kw expression OF_kw&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; case_expr_alt_list&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; opt_default_expr_alt ;&lt;br /&gt;&lt;br /&gt;case_expr_alt_list : &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; case_expr_alt&lt;br /&gt;&amp;nbsp; | case_expr_alt_list case_expr_alt&lt;br /&gt;&amp;nbsp; ;&lt;br /&gt;&lt;br /&gt;case_expr_alt : '[' choice_list ']' REFERS_TO expression ;&lt;br /&gt;&lt;br /&gt;opt_default_expr_alt : '[' DOT_DOT ']' REFERS_TO expression | ;&lt;br /&gt;&lt;br /&gt;quantified_expression :&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; FOR_kw ALL_or_SOME_kw iterator ':' condition ;&lt;br /&gt;&lt;br /&gt;ALL_or_SOME_kw : ALL_kw | SOME_kw ;&lt;br /&gt;&lt;br /&gt;%%&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;package parasail_parser is&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; procedure yyparse;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; echo : boolean := false;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; number_of_errors : natural := 0;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;end parasail_parser;&lt;br /&gt;&lt;br /&gt;with parasail_tokens, parasail_lex_io, parasail_goto, parasail_shift_reduce;&lt;br /&gt;with parasail_lex, text_io;&lt;br /&gt;&lt;br /&gt;use&amp;nbsp; parasail_tokens, parasail_lex_io, parasail_goto, parasail_shift_reduce;&lt;br /&gt;use&amp;nbsp; parasail_lex, text_io;&lt;br /&gt;package body parasail_parser is&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; procedure yyerror(s: in string := "syntax error") is&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; begin&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; number_of_errors := number_of_errors + 1;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; put("&amp;lt;&amp;lt;&amp;lt; *** ");&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; put_line(s);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; end yyerror;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;##%procedure_parse&lt;br /&gt;&lt;br /&gt;end parasail_parser;&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;------------------&lt;br /&gt;&lt;br /&gt;And here is the driver program, also written in Ada:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;pre&gt;with parasail_parser, parasail_lex_io, parasail_lex, text_io;&lt;br /&gt;use&amp;nbsp; parasail_parser, text_io;&lt;br /&gt;&lt;br /&gt;with parasail_lex_dfa;&lt;br /&gt;procedure parasail_main is&lt;br /&gt;&amp;nbsp; in_file_name: string(1..80);&lt;br /&gt;&amp;nbsp; last&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; : natural;&lt;br /&gt;begin&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; text_io.put("Enter input file: ");&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; text_io.get_line(in_file_name, last);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; parasail_lex_io.open_input(in_file_name(1..last));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; parasail_lex_io.create_output;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; put_line("---- Starting parse ----");&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; -- parasail_lex_dfa.aflex_debug := True;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; parasail_lex.linenum;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; yyparse;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; parasail_lex_io.close_input;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; parasail_lex_io.close_output;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; put_line("---- Finished parse ----");&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; new_line;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; put(integer'image(number_of_errors));&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; put_line(" errors found");&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;end parasail_main;&lt;br /&gt;&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8383004232931899216-878460941661955841?l=parasail-programming-language.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://parasail-programming-language.blogspot.com/feeds/878460941661955841/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://parasail-programming-language.blogspot.com/2010/06/ayacc-based-parser-for-parasail.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8383004232931899216/posts/default/878460941661955841'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8383004232931899216/posts/default/878460941661955841'/><link rel='alternate' type='text/html' href='http://parasail-programming-language.blogspot.com/2010/06/ayacc-based-parser-for-parasail.html' title='(A)Yacc-based parser for ParaSail'/><author><name>Tuck</name><uri>http://www.blogger.com/profile/08866496974237052847</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8383004232931899216.post-7420334389637314120</id><published>2010-06-09T00:02:00.001-04:00</published><updated>2010-06-09T00:04:46.928-04:00</updated><title type='text'>An intentional race condition in a ParaSail concurrent loop</title><content type='html'>An intriguing question, given the presence of the &lt;b&gt;concurrent&lt;/b&gt; &lt;b&gt;loop&lt;/b&gt; construct in &lt;b&gt;ParaSail&lt;/b&gt;, is what would happen if there were a loop &lt;b&gt;exit&lt;/b&gt; or a &lt;b&gt;return&lt;/b&gt; statement in the body of a &lt;b&gt;concurrent&lt;/b&gt; loop.&amp;nbsp; Earlier we have said that only &lt;b&gt;forward&lt;/b&gt; and &lt;b&gt;reverse&lt;/b&gt; loops would allow an &lt;b&gt;exit&lt;/b&gt; statement.&amp;nbsp; But perhaps we should allow an &lt;b&gt;exit&lt;/b&gt; or a &lt;b&gt;return&lt;/b&gt; from within a &lt;b&gt;concurrent&lt;/b&gt; loop as a way of terminating a concurrent computation, aborting all threads besides the one exiting or returning.&amp;nbsp; This would essentially be an &lt;i&gt;intentional&lt;/i&gt; race condition, where the first thread to &lt;b&gt;exit&lt;/b&gt; or &lt;b&gt;return&lt;/b&gt; wins the race.&amp;nbsp; This would seem to be a relatively common paradigm when doing a parallel search, where you want to stop as soon as the item of interest is found in the data structure being walked, for example, and there is no need for the other threads to continue working.&lt;br /&gt;&lt;br /&gt;In some sense, a &lt;b&gt;return&lt;/b&gt; statement in a &lt;b&gt;concurrent&lt;/b&gt; loop is easier to understand, if we presume we are in a function searching (in parallel) for some item in a data structure, and we want to return the item as soon as any thread finds it.&amp;nbsp; An &lt;b&gt;exit&lt;/b&gt; statement in a &lt;b&gt;concurrent&lt;/b&gt; loop is a bit harder to understand, since we would need a way to record the result of the &lt;i&gt;winning&lt;/i&gt; thread somehow.&amp;nbsp; Perhaps we would want to allow some code associated with the exit statement that occurs after all of the other threads have been aborted.&amp;nbsp; Perhaps "&lt;b&gt;exit&lt;/b&gt; &lt;b&gt;loop&lt;/b&gt; &lt;b&gt;then&lt;/b&gt; &lt;i&gt;record&lt;/i&gt; &lt;i&gt;winner&lt;/i&gt;;" might be a syntax indicating that the &lt;i&gt;record&lt;/i&gt; &lt;i&gt;winner&lt;/i&gt; code is to be executed after the loop has effectively been stopped, but still in the context of the winning thread, with visibility on the local variables of the &lt;i&gt;loop&lt;/i&gt; &lt;i&gt;body&lt;/i&gt; containing the &lt;b&gt;exit&lt;/b&gt; &lt;b&gt;loop&lt;/b&gt; &lt;b&gt;then&lt;/b&gt; ... construct.&lt;br /&gt;&lt;br /&gt;For example, using the generalized &lt;b&gt;for&lt;/b&gt; loop from the previous posting:&lt;br /&gt;&lt;pre&gt;&amp;nbsp;   &lt;b&gt;var&lt;/b&gt; Winner : Node := null;&lt;br /&gt;    &lt;b&gt;for&lt;/b&gt; T := Root &lt;b&gt;then&lt;/b&gt; T.Left || T.Right &lt;br /&gt;      &lt;b&gt;while&lt;/b&gt; T != &lt;b&gt;null&lt;/b&gt; &lt;b&gt;concurrent&lt;/b&gt; &lt;b&gt;loop&lt;/b&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;     &lt;b&gt;if&lt;/b&gt; T.Key == Desired_Key &lt;b&gt;then&lt;/b&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;     &lt;b&gt;exit&lt;/b&gt; &lt;b&gt;loop&lt;/b&gt; &lt;b&gt;then&lt;/b&gt; Winner := T;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;     &lt;b&gt;end&lt;/b&gt; &lt;b&gt;if&lt;/b&gt;;&lt;br /&gt;    &lt;b&gt;end&lt;/b&gt; &lt;b&gt;loop&lt;/b&gt;;&lt;/pre&gt;At this point Winner is either still &lt;b&gt;null&lt;/b&gt; if no node in the tree has the Desired_Key, or is equal to some node whose Key equals the Desired_Key.  If there is more than one such node, it would be non-deterministic which such node Winner designates.&amp;nbsp;&lt;br /&gt;&lt;br /&gt;Clearly this kind of brute force search of the tree would not be needed if the tree were organized based on Key values.&amp;nbsp; This example presumes the Key is not controlling the structure of the tree.&amp;nbsp; Also note that if this were a function whose whole purpose was to find the node of interest, the &lt;b&gt;exit&lt;/b&gt; &lt;b&gt;loop&lt;/b&gt; &lt;b&gt;then&lt;/b&gt; ... statement could presumably be replaced by simply &lt;b&gt;return&lt;/b&gt; T and we wouldn't need the local variable Winner at all.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/8383004232931899216-7420334389637314120?l=parasail-programming-language.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://parasail-programming-language.blogspot.com/feeds/7420334389637314120/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://parasail-programming-language.blogspot.com/2010/06/intentional-race-condition-in-parasail.html#comment-form' title='8 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/8383004232931899216/posts/default/7420334389637314120'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/8383004232931899216/posts/default/7420334389637314120'/><link rel='alternate' type='text/html' href='http://parasail-programming-language.blogspot.com/2010/06/intentional-race-condition-in-parasail.html' title='An intentional race condition in a ParaSail concurrent loop'/><author><name>Tuck</name><uri>http://www.blogger.com/profile/08866496974237052847</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>8</thr:total></entry><entry><id>tag:blogger.com,1999:blog-8383004232931899216.post-3406343288671125653</id><published>2010-06-08T23:09:00.003-04:00</published><updated>2010-06-11T13:52:10.891-04:00</updated><title type='text'>Generalized For loops in ParaSail</title><content type='html'>As we start to dive into the lower-level control structures for &lt;b&gt;ParaSail&lt;/b&gt;, one clearly very important structure is the &lt;b&gt;for&lt;/b&gt; loop.&amp;nbsp; We have already suggested the basic structure:&lt;br /&gt;&lt;pre&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;b&gt;for&lt;/b&gt; I &lt;b&gt;in&lt;/b&gt; 1..10 [&lt;b&gt;forward &lt;/b&gt;| &lt;b&gt;reverse &lt;/b&gt;| &lt;b&gt;concurrent&lt;/b&gt;] &lt;b&gt;loop&lt;/b&gt;&lt;/pre&gt;However, it would be nice if the &lt;b&gt;for&lt;/b&gt; loop could also be used for more general looping structures. A number of languages have adopted a &lt;b&gt;for&lt;/b&gt; loop where there is an initialization, a "next step", and a termination/continuation condition.&amp;nbsp; The best known is probably that of C, inherited by C++ and Java:&lt;br /&gt;&lt;pre&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;b&gt;for&lt;/b&gt; (&lt;i&gt;init&lt;/i&gt;; &lt;i&gt;test&lt;/i&gt;; &lt;i&gt;next&lt;/i&gt;)...&lt;/pre&gt;The &lt;i&gt;init&lt;/i&gt; and &lt;i&gt;next&lt;/i&gt; parts are arbitrary statements (to be more precise, expressions evaluated for their side-effects), while &lt;i&gt;test&lt;/i&gt; is treated as a condition whose truth determines whether iteration continues.&lt;br /&gt;&lt;br /&gt;A number of LISP variants, and languages based to some degree on LISP such as Dylan, also have a similar generalized looping capability:&lt;br /&gt;Scheme:&lt;br /&gt;&lt;pre&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; (&lt;b&gt;do&lt;/b&gt; ((I &lt;i&gt;initial&lt;/i&gt; &lt;i&gt;next&lt;/i&gt;) (J &lt;i&gt;initial&lt;/i&gt; &lt;i&gt;next&lt;/i&gt;) ... )&lt;br /&gt;      (&lt;i&gt;test&lt;/i&gt;) &lt;br /&gt;        &lt;i&gt;loop body&lt;/i&gt;&lt;br /&gt;    )&lt;/pre&gt;Dylan:&lt;br /&gt;&lt;pre&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;b&gt;for&lt;/b&gt; (I = &lt;i&gt;initial&lt;/i&gt; &lt;b&gt;then&lt;/b&gt; &lt;i&gt;next&lt;/i&gt; &lt;b&gt;while:&lt;/b&gt; &lt;i&gt;test&lt;/i&gt;)&lt;br /&gt;        &lt;i&gt;loop body&lt;/i&gt;&lt;br /&gt;    &lt;b&gt;end for&lt;/b&gt;&lt;/pre&gt;In the case of the C &lt;b&gt;for&lt;/b&gt; loop, &lt;i&gt;next&lt;/i&gt; is an arbitrary statement, whereas for the LISP-based languages, &lt;i&gt;next&lt;/i&gt; is the next value for the associated loop variable.  This is perhaps related to the fact that in C there is special syntax for incrementing and decrementing a variable, meaning that a statement that increments the loop variable (e.g. &lt;span style="font-family: &amp;quot;Courier New&amp
