[Oberon] Module aliases - what is the correct way to handle them
Andreas Pirklbauer
andreas_pirklbauer at yahoo.com
Sun Feb 9 12:46:57 CET 2020
The current implementation on projectoberon.com does not handle
aliases correctly in all cases (see appendix below for an example).
Hence an implementation that DOES handle aliases in a correct
way is required. However, this is tricky. One complication arises
due to re-export and re-import of types across potentially many
modules. Imports can be hidden, and a module can be
simultaneously imported indirectly (hidden import) and directly.
Any input on the options shown below for ORB.ThisModule?
- ORB0 and ORB1 correctly detect an "invalid import order”
- ORB1 and ORB2 don’t detect an "invalid import order”
(see http://github.com/andreaspirklbauer/Oberon-test-module-aliases)
Feel free to add other possible ways to handle this correctly.
-ap
—————————— ORB.ThisMod ———————————
**ORB0.Mod** (tests obj.name agains name and obj.orgname against obj.orgname separately)
obj1 := topScope; obj := obj1.next; (*search for module*)
WHILE (obj # NIL) & (obj.name # name) DO obj1 := obj; obj := obj1.next END ;
IF obj = NIL THEN
obj1 := topScope; obj := obj1.next;
WHILE (obj # NIL) & (obj IS Module) & (obj(Module).orgname # orgname) DO
obj1 := obj; obj := obj1.next
END
END ;
**ORB1.Mod** (tests obj.name against name and obj.orgname against obj.orgname in a single loop)
This is similar to ORB0, but now there is a *type test* and a *type guard* for *every* import being checked.
obj1 := topScope; obj := obj1.next; (*search for module*)
WHILE (obj # NIL) & (obj IS Module) & (obj.name # name) & (obj(Module).orgname # orgname) DO
obj1 := obj; obj := obj1.next
END ;
**ORB2.Mod** (tests only obj.orgname against orgname)
obj1 := topScope; obj := obj1.next; (*search for module*)
WHILE (obj # NIL) & (obj IS Module) & (obj(Module).orgname # orgname) DO
obj1 := obj; obj := obj1.next
END ;
**ORB3.Mod** (tests obj.orgname agains name)
obj1 := topScope; obj := obj1.next; (*search for module*)
WHILE (obj # NIL) & (obj IS Module) & (obj(Module).orgname # name) DO
obj1 := obj; obj := obj1.next
END ;
—————————— M.Mod ———————————
MODULE N0;
TYPE T0* = RECORD i: INTEGER END ;
END N0.
MODULE N1;
TYPE T1* = RECORD i: INTEGER END ;
END N1.
MODULE N2;
TYPE T1* = RECORD i: INTEGER END ;
END N2.
MODULE M0;
TYPE T0* = RECORD i: INTEGER END ;
END M0.
MODULE M1;
IMPORT M0;
TYPE T1* = RECORD (M0.T0) j: INTEGER END ;
END M1.
MODULE M2;
IMPORT M1;
TYPE T2* = RECORD (M1.T1) k: INTEGER END ;
END M2.
MODULE M3;
IMPORT N0 := M0, M2, N0;
TYPE T3* = RECORD (M2.T2) k: INTEGER END ;
END M3.
ORP.Compile @/s ~
-----------------------------------------------------------
Try the above sequence with 4 different version of ORB:
ORP.Compile ORB0.Mod/s ~ # correct
System.Free ORP ORG ORB ~
Now recompile M3
-> catches the "invalid import order" error
ORP.Compile ORB1.Mod/s ~ # correct
System.Free ORP ORG ORB ~
Now recompile M3
-> catches the "invalid import order" error
ORP.Compile ORB2.Mod/s ~ # incorrect
System.Free ORP ORG ORB ~
Now recompile M3
-> does NOT catch the "invalid import order" error
ORP.Compile ORB3.Mod/s ~ # incorrect
System.Free ORP ORG ORB ~
Now recompile M3
-> does NOT catch the "invalid import order” error
———— APPENDIX ——————
The current implementation of module ORB does not compile the
following 4 modules correctly.
MODULE M1; TYPE P1* = POINTER TO T1; T1* = RECORD x*: INTEGER END; END M1.
MODULE M2; IMPORT M1; TYPE P2* = POINTER TO T2; T2* = RECORD(M1.T1) y*: INTEGER END; END M2.
MODULE M3; IMPORT M1, M2; VAR x1: M1.P1; x2: M2.P2; BEGIN x1 := x2; END M3.
MODULE M4; IMPORT Y1 := M1, Y2 := M2; VAR x1: Y1.P1; x2: Y2.P2; BEGIN x1 := x2; END M4.
Modules M1 to M3 compile, but M4 (which should do the same as M3) does not.
This was reported on:
http://github.com/schierlm/Oberon2013Modifications/tree/master/BugFixes
More information about the Oberon
mailing list