[Oberon] Procedure variables and local procedures
chris at cfbsoftware.com
Sun Oct 1 06:12:46 CEST 2017
> -----Original Message-----
> From: Chris Burrows [mailto:chris at cfbsoftware.com]
> Sent: Sunday, 1 October 2017 9:52 AM
> To: chris at cfbsoftware.com
> Subject: FW: [Oberon] Procedure variables and local procedures
> CharPtr = POINTER TO ARRAY OF CHAR;
> p : CharPtr;
> NEW(p, 1234);
> Ah I see, you are referring to Oberon-2 (1993)
> NW designed two languages:
> - the original Oberon
> - and his revision Oberon-07
> In the original Oberon, NW defined in the low level compiler module
> SYSTEM the procedure NEW(v, n).
> In Oberon-07 this is not existing anymore. As Andreas Pickelbauer
> demonstrated, this functionality can be introduced with Oberon-07
> without changing the language.
Not exactly. Oberon-07 doesn't allow ARRAY OF <type> in a type or variable declaration (excluding open array parameters which are a different concept). Nor does Oberon-07 allow POINTER TO ARRAY - pointers can only point to RECORDS (which can have ARRAYs as fields).
If these syntax changes were introduced they would need to be considered as language extensions. There would also be the question of whether the feature would be restricted to single-dimensional arrays, what notation would be used if multi-dimensional arrays would be used, how many dimensions would be allowed, what are the rules of assignment compatibility issues etc. etc.
I have seen various Oberon-style implementations of this over the years e.g.
ARRAY OF ARRAY OF ARRAY 3 OF INTEGER
ARRAY *, *, 3 OF INTEGER
All in all it is far from a trivial matter. Considering that the sort of low-level system software that Oberon-07 is suited to rarely needs such a feature then I can understand why Wirth hasn't yet bothered to include it.
> Whether the index i of the expression a[i] shall be checked is not
> defined in Oberon either. This is left to the implementation as you
> might want your code to be finetuned for speed (no checks) or
> security (with checks). Oberon-07 offers different methods for your
> ASSERT( (0 <= i) & (i <= 255) ); b := i; or
> b := i MOD 256;
Alternatively, and, most likely, more efficiently:
ASSERT(i DIV 256 = 0); b := i;
Note that depending on the context / requirements the latter might need to be either:
b := ABS(i MOD 256);
b := ABS(i) MOD 256;
> I find BYTE quite useful.
I'd go further than that. I find BYTE *absolutely essential* for embedded system software development. Hardware engineers have a particular talent for defining weird and wonderful data items. For example a particular temperature sensor I use returns the data in this form:
(* The result is a 10-bit 2's complement integer: result:9:2 := msb:7:0, result:0:1 = lsb:7:6 *)
Consequently I often find myself looking forward to the day when we might have BIT ARRAY and BIT FIELDS constructs in Oberon.
The usual notion of Language portability is generally a non-issue for Oberon-07 in practice. A programmer cannot afford to make any assumptions about which byte of an integer a byte value is to be stored in. When dealing with data structures like this the programmer needs to know the excruciating details of BYTE and BIT ordering and needs a language and compiler (e.g. Oberon-07) which generates predictable code according to the programmer's instructions.
Any resulting algorithm is non-portable by definition from one manufacturer's sensor to another - or even two different sensors from the same manufacturer! Wishing for anything else is just dreaming.
> In the original Oberon, the comparable
> SHORTINT was signed, BYTE is unsigned. When e.g. parsing TCP packets
> and you wanted to calculate the port nbr, you couldn t easily use
> SHORTINT. So, I often misused CHAR, as ORD(c) returns an unsigned
> value. As in the majority of cases bytes are treated unsigned, BYTEs
> makes the code a little bit more intuitive to read.
I totally agree.
More information about the Oberon