Post by Xin Wang
It sounds similar to Rust's traits, if I understand correctly.
- *blueprint* vs. *trait*
- *extension module* vs. *impl*
A blueprint has similarities with Smalltalk's protocol. Everybody else, whatever they may call it got the basic idea from Smalltalk, directly or indirectly.
The facility Java calls interface and Scala and others call trait is 100% plagiarised from Smalltalk. A blueprint has significant overlap with a Smalltalk protocol but it is not a 100% overlap.
There are some properties that a library needs to obtain that simply do not make sense to "implement" in the library every time, and sometimes it is not even possible to implement in the library because the property is built into the compiler.
One such example is the compatibility of a library defined type with literals. Most languages do not even bother to provide literal assignment compatibility for library defined types. Our blueprints allow just that.
A blueprint can specify compatibility with a literal of the language and any library that conforms to that blueprint automatically becomes assignment compatible with that literal, and anything that needs to be there to facilitate that compatibility is automatically enforced then.
This way you can define a library defined scalar type for very large integers and then use ordinary integer literals as legal values to be assigned to instances of the type.
VAR n : VeryLargeInteger;
n := 123'456'789'012'345'678'901'234'567'890'123'456'789'012'345'678'901'234'567'890;
The compiler accepts such assignments if the blueprint of the type specifies compatibility with integer literals. There is no type specific conversion involved. Instead the compiler converts the value to the language defined internal representation called scalar exchange format.
Scalar types are required to implement two conversion procedures, one to convert from scalar exchange format to the type's own representation, another for the opposite. The former is then used to convert a literal that has already been converted to scalar exchange format by the compiler at compile time. The conversion procedures are also used for safe type conversions between any two given scalar types.
The conversion procedures are implemented by the type, but the literal compatibility is implemented in the compiler itself thanks to the standardised scalar exchange format.
In this way, a blueprint not only enforces a library's implementation conforms, but it also gives built-in properties to conforming types. This makes blueprints different from other instances where the Smalltalk protocol concept has been adopted.
As for extension modules, they are not comparable with what other languages call implementation.
Like any other Modula-2 library, an extension library consists of two compilation units, a definition part (DEFINITION MODULE) and a corresponding implementation part (IMPLEMENTATION MODULE).
An extension library is simply a piece of a library module that has been stuck into a separate set of files.
Typically library defined types in M2 R10 will follow a pattern where the main part is in a library that has the same name as the type itself, for example type BCD has BCD.def and BCD.mod. However, the IO for the type is placed in an extension library represented by BCDIO.def and BCDIO.mod. The math library is placed in another extension library represented by BCDMath.def and BCDMath.mod.
When BCD is imported, the type itself and all basic operations such as built-in operators are available but not IO operations such as READ, WRITE, WRITEF, nor math library operations like sin, cos, tan etc.
For the IO operations the type's IO library must be imported, for the math library operations, the math library must be imported. However, these imports insert the added identifiers into the type's own name space, thus
IMPORT BCD, BCDMath;
VAR x, y : BCD;
y := BCD.sin(x);
y := BCDMath.sin(x);
Also, an implementation module may mark certain low level procedures as private. These procedures are not visible to clients of the library, but they are visible to extension libraries targeting the library.
The ability to insert new "methods" into an existing library originated in Smalltalk as well, but in Smalltalk there is no specific compilation unit associated with it, it can be done anywhere. Of course such anarchy is entirely unwanted in a disciplined language like Modula-2, hence the extension module.