Project

General

Profile

ETH (Active) Oberon Language Report

Added by Felix Friedrich 9 months ago

Although it is work in progress, we have decided to publish the current state of the ETH Oberon Language Report together with the tools in the A2/Oberon repository.

It can be found here: export:/trunk/LanguageReport/OberonLanguageReport.pdf


Replies (13)

RE: ETH (Active) Oberon Language Report - Added by Yaroslav Romanchenko 9 months ago

Hi Felix,

This is a Great Milestone in Active Oberon language Evolution!
My Congratulations!

We have already talks about this Event at our A2 OS Telegram chat https://t.me/joinchat/GXohMxZGDM6OQlKC1ZBjtg

Mainly, community accepted the Language Report positive, because, it's already awaited for a long time! :)

But, some critics also present.

Victor Miasnikov commented, that using a mathematical sign of inclusion (14.3 Type Inclusion) is not very correct when we talk about relations between SIGNED, UNSIGNED and FLOAT numbers.
Because, almost all of this inclusions are not full, due to loose of the precission.
And also he noted that it would be great to clarify what happens with number values on explicit type casts and type guards expressions: type(value) and value(type). Does type guards throws exceptions?

Best Regards,
Yaroslav

RE: ETH (Active) Oberon Language Report - Added by Serge Durmanov 9 months ago

Some thoughts on improving the object model.
1) The {LIMITED} modifier for types. Variables of types declared as {LIMITED} cannot be instantiated outside the module in which they are declared, but can be passed as parameters.
2) The {FINAL} modifier for any custom types, record / object methods, and variables (fields).
Variables (fields) declared as {FINAL} can only be initialized in certain places. Module-scope variables can be changed in variable initializers and the module body (BEGIN..END). Local variables in the VAR section. Fields in variable initializers and constructors (possibly in the body of the active object to ensure the correct safe restart of activity).
3) Mark new methods with the {NEW} modifier (as in Component Pascal) or overridden methods with the {OVERRIDE} modifier, since now it is not clear whether the method is overridden. The variant with the {OVERRIDE} modifier is preferable, since we see the point of change. Although it is more labor intensive. It can be done optionally.

RE: ETH (Active) Oberon Language Report - Added by Serge Durmanov 9 months ago

A type guard on numbers has been introduced. A guarded number is converted to the
given type if and only if its value is not changed. When it fails (i.e. when the actual
value of a number is not compatible to / cannot be represented by the type), a trap is
raised.

What should happen when signed32: = unsigned32 (SIGNED32) is executed if signed32 does not fit into a positive range of values of type SIGNED32? Physically, the meaning does not change, but semantically it is not. Should an exception be thrown? If we follow the semantics of the concept of "type guard", then an exception must be generated, otherwise there is no difference between the "type conversion" T (v) and the "type guard" v (T), and both options are unsafe. A means of safe type conversion in Oberon should be.

RE: ETH (Active) Oberon Language Report - Added by Felix Friedrich 9 months ago

The "type guard" on numbers is syntactic sugar.

x(SIGNEDx)

stands for
IF SIGNEDx(x) = x THEN RETURN SIGNEDx(x) ELSE TRAP END; 

It is intended for cases where the type casting to a smaller type would imply loosing precision. We would like to avoid any further complication and leave it at that. Even if, mathematically, SIGNEDx(y) does not always equal UNSIGNEDx(y), an (unsigned) comparison of UNSIGNEDx(y) with SIGNEDx(y) in Oberon will always yields TRUE.

RE: ETH (Active) Oberon Language Report - Added by Yaroslav Romanchenko 9 months ago

A module with template parameters can import another module with template parameters and pass template arguments if that is your question:

MODULE A (TYPE T);
TYPE Type* = T;
END A.

MODULE B (TYPE T);
IMPORT A := A (T);
TYPE Type* = A.Type;
END B.

MODULE C;
IMPORT B := B (INTEGER);
TYPE Type = B.Type;
END C.

RE: ETH (Active) Oberon Language Report - Added by Yaroslav Romanchenko 9 months ago

I mean the ability to have template with some base objects, then have template that acts as client module for base template and template both, that uses base template by specifying base objects by parameters and additionally extends base objects.
This code, actually does not compile.

MODULE A(TYPE T, CONST L);
TYPE    Type* = OBJECT
    VAR
        t1, t2: T;
    PROCEDURE P;
    BEGIN
        IGNORE L(t1, t2)
    END P;
    END Type;
END A.

MODULE B (TYPE T1, TYPE T2, CONST L);
IMPORT    A_Base := A(T1, L), A_INT := A(INTEGER, L_INT);
TYPE
    Type* = OBJECT(A_Base.Type)
    VAR
        u1, u2: T1;
        u3: T2;
        a_int: A_INT.Type;
    PROCEDURE P;
    BEGIN
        IGNORE L(u1, u2)
    END P;
    END Type;
    PROCEDURE L_INT(i1, i2: INTEGER): BOOLEAN;
    BEGIN
    END L_INT;
END B.

MODULE C;
IMPORT
    Strings,
    A_FLOAT32 := A(FLOAT32, L_FLOAT32),
    B_FLOAT32_String := B(FLOAT32, Strings.String, L_FLOAT32);
    PROCEDURE L_FLOAT32(f1, f2: FLOAT32): BOOLEAN;
    BEGIN
    END L_FLOAT32;    
END C.

RE: ETH (Active) Oberon Language Report - Added by Yaroslav Romanchenko 9 months ago

Base template may be used in that case, for example, for implementation of base value containers. Extended template (B) may implement some Key-Value containers (trees, dictionaries...)

RE: ETH (Active) Oberon Language Report - Added by Florian Negele 9 months ago

Your code should work. There is at least one problem with the compiler, see issue #57.

RE: ETH (Active) Oberon Language Report - Added by Florian Negele 9 months ago

Your code should work now. Please update.

RE: ETH (Active) Oberon Language Report - Added by S M 8 months ago

Found a typo in 7.0.1

UNSIGNE64

RE: ETH (Active) Oberon Language Report - Added by Andreas Pirklbauer 8 months ago

This is a question regarding scope rules in Active Oberon:

The Active Oberon language reports states on p.12 (“Declaration and Scope Rules”): “An item may be directly referenced within its scope only."

Question: Does Active Oberon implement "shadowing through scope”?

I.e. does an intermediate variable (such as the variable g declared in P below) block access to a global variable with the same name from within a nested scope Q?

MODULE M;  (assume that access to intermediate variables is not allowed)
VAR g: INTEGER; --> global variable g
PROCEDURE P*;
VAR g: INTEGER; --> DOES this intermediate variable g “shadow” (block access to) the global variable g?
PROCEDURE Q;
BEGIN g := 1 --> OR can a nested procedure Q still access the global variable g here?
END Q;
BEGIN Q
END P;
END M.

For example, in Oberon-07 this leads to a “pos 195 inaccessible” compile time error. This is because Oberon-07 does NOT allow access to intermediate variables (e.g. access to the variable g in procedure P in the above example), yet implements "shadowing through scope", i.e. the intermediate variable g declared in P hides, or shadows, the global variable g.

Historically, most Algol-like languages have traditionally implemented "shadowing through scope". However, in the earlier languages (e.g., Algol, Pascal, Modula-2, Oberon 1988/90) access to surrounding scopes WAS actually ALLOWED, so the shadowing concept, as described above, made sense.

But in Oberon-07 (and Active Oberon I suppose) intermediate variables (such as variable g in P in the above example) can no longer be accessed from within nested scopes (such as procedure Q in the above example). So the question is whether shadowing still has its place in such languages or whether it should be abolished.

Allowing access to the global scope - regardless of whether intermediate variables with the same name exist or not - would effectively make nested procedures self-contained in the sense that they can be moved around freely. For example, procedure Q could now be made local to procedure P without having to worry about whether one can still access the global variable g or not (as the surrounding scope of Q, i.e. the scope of P is simply ignored).

RE: ETH (Active) Oberon Language Report - Added by Florian Negele 8 months ago

Yes, Active Oberon implements shadowing through scope. A nested procedure implies recursive activation and is thus not necessarily self-contained.

RE: ETH (Active) Oberon Language Report - Added by Andreas Pirklbauer 8 months ago

Thanks for the clarification. In my own single-pass Oberon-2 compiler for FPGA Oberon 2013 I had, for some time, hesitated to relax the shadowing rules and actually allow "piercing through the shadow" in order to grant access to the global scope level, even when intermediate variables with the same name in surrounding scopes exist. But I ended up keeping "shadowing through scope" in order not to break with the language tradition. Making a nested procedure self-contained appears to be of marginal utility, besides nested procedure themselves are quite rare. Overall, I think it is a sound choice to keep the shadowing semantics. Perhaps it should be made explicit in the language report..

    (1-13/13)