This article describes three possible approaches how to enforce permitted operator bindings based on semantic types but also taking into account that some semantic types are static in nature while others are dynamic.
The grammar (status April 14, 2010) defines syntax that allows a semantic type to be specified in a RECORD
declaration only. If a type is declared as an opaque pointer, such as would be the case for types of dynamic nature, e.g. string and collection types, then there is no syntax to specify a semantic type.
With this approach no additional syntax is added. No type specifiers exist for strings and collections.
TYPE SHORTINT = OPAQUE RECORD ("Z-Type") ... END; TYPE String = OPAQUE; (* strings and collections share the same bindings *)
With this approach additional syntax is provided for opaque pointer declarations. Each semantic type requires a type specifier.
TYPE SHORTINT = OPAQUE RECORD ("Z-Type") ... END; TYPE String = OPAQUE ("S-Type");
With this approach the syntax is changed to put the type specifier into the module header. Each semantic type requires a type specifier.
DEFINITION MODULE SHORTINT ("Z-Type"); DEFINITION MODULE String ("S-Type");
With approach #1 string and collection types would have to share one set of permitted bindings. Either the bindings for <
and >
would have to be permitted for collection types, or the presence of a binding for LENGTH
or COUNT
would have to determine which set of bindings are permitted. The former would leave the semantics of operators <
and >
for collection types undefined and open to library implementors. The latter would lead to some overhead in semantic analysis. Either way would introduce some inconsistency into the language. Overall this approach may give the impression that operator bindings for string and collection types were bolted-on afterwards. Adding further semantic types in the future may become difficult without rendering existing source code incompatible.
Approaches #2 and #3 both have consistent syntax and semantics. Bindings are only permitted if a semantic type is specified. Every semantic type has a specifier and an associated set of permitted bindings. Both approaches can accommodate the addition of further semantic types in the future without rendering existing source code incompatible.
The syntax of approach #2 emphasises the notion that bindings are a property of the type. In the event that the same library also defines other auxiliary types, this syntax has the advantage that it is always clear to which type the semantic type specifier applies.
The syntax of approach #3 emphasises the notion that bindings are a property of the library. Since the definition module of a library also serves as its documentation, this syntax has the advantage that it indicates the semantic model of the library at the top of its documentation. It also has a minor advantage in that the grammar is slightly simpler.
Since approaches #2 and #3 require a specifier for each semantic type, both necessitate the introduction of a new specifier for collection types. The most obvious mnemonic "C-Type" is not available because it is already in use for complex number types. Suitable alternatives would be "A-Type" as a mnemonic for "array notation", or "AA-Type" as a mnemonic for "associative array".
TYPE Dictionary = OPAQUE ("A-Type"); TYPE UniString = OPAQUE ("S-Type");
Another alternative would be "Collection" but this would be inconsistent with other semantic type specifiers. This inconsistency could be resolved by using "String" instead of "S-Type" and reserve single letter based specifiers for numeric types only.
TYPE Dictionary = OPAQUE ("Collection"); TYPE UniString = OPAQUE ("String");
Overall, "A-Type", "S-Type", "Z-Type", "R-Type", "C-Type" and "V-Type" would seem to be the more consistent set of specifiers.
For approach #1 the static semantics would be as follows:
LENGTH
and COUNT
bindings are mutually exclusive.
LENGTH
, then only string bindings are permitted.
COUNT
, then only collection bindings are permitted.
For approach #2 the static semantics would be as follows:
For approach #3 the static semantics would be as follows:
Approach #1 is the least favourable because it introduces inconsistencies, requires more semantic analysis and may inhibit the addition of more semantic types in the future. Approaches #2 and #3 are favourable and both are equally suitable. If it is desired to emphasise bindings as a property of the type, #2 may be given preference. If it is desired to emphasise bindings as a property of the library, #3 may be given preference. If the newly required type specifier for collection types is to be chosen with the highest overall consistency in mind then "A-Type" is the most suitable choice.