implementing read-only value parameters using the '-' marker (oakwood guidelines 5.13)

declaring a parameter as 'name-: TYPE' passes it by reference for
efficiency but prevents assignment within the procedure body.
per xds oberon-2 documentation, '-' is a modifier on value parameters
only; combining it with VAR is an error (246).

adding 'readOnlyPar = 3' to the vis field constants on OPT.Object.
setting node^.readonly in OPB.Ident for VarPar nodes whose object
has vis = readOnlyPar, which causes OPB.Assign to emit err(76) on
any attempt to write the parameter or its components.

relaxing OPB.Param to allow passing a read-only variable as an
actual argument to a read-only formal (previously blocked by err(76)
because VarPar checked ap^.readonly unconditionally).

adding Srpar = 42 symbol file tag so that read-only parameters
survive across module boundaries: OutSign writes Srpar and InSign
reconstructs the mode and vis correctly when importing.

code generation in OPV is unchanged; read-only parameters produce
the same C as VAR parameters since the restriction is purely semantic.
This commit is contained in:
Norayr Chilingarian 2026-07-10 01:06:47 +04:00
parent 0db5141423
commit 63ec99e0bc
4 changed files with 20 additions and 7 deletions

View file

@ -24,7 +24,7 @@ MODULE OPB; (* RC 6.3.89 / 21.2.94 *) (* object model 17.1.93 *)
CASE obj^.mode OF CASE obj^.mode OF
| OPT.Var: node := OPT.NewNode(OPT.Nvar); | OPT.Var: node := OPT.NewNode(OPT.Nvar);
node^.readonly := (obj^.vis = OPT.externalR) & (obj^.mnolev < 0) node^.readonly := (obj^.vis = OPT.externalR) & (obj^.mnolev < 0)
| OPT.VarPar: node := OPT.NewNode(OPT.Nvarpar) | OPT.VarPar: node := OPT.NewNode(OPT.Nvarpar); node^.readonly := obj^.vis = OPT.readOnlyPar
| OPT.Con: node := OPT.NewNode(OPT.Nconst); | OPT.Con: node := OPT.NewNode(OPT.Nconst);
node^.conval := OPT.NewConst(); node^.conval := OPT.NewConst();
node^.conval^ := obj^.conval^ (* string is not copied, only its ref *) node^.conval^ := obj^.conval^ (* string is not copied, only its ref *)
@ -1390,7 +1390,7 @@ MODULE OPB; (* RC 6.3.89 / 21.2.94 *) (* object model 17.1.93 *)
IF NotVar(ap) THEN err(122) IF NotVar(ap) THEN err(122)
ELSE CheckLeaf(ap, FALSE) ELSE CheckLeaf(ap, FALSE)
END ; END ;
IF ap^.readonly THEN err(76) END ; IF ap^.readonly & (fp^.vis # OPT.readOnlyPar) THEN err(76) END ;
IF fp^.typ^.comp = OPT.DynArr THEN DynArrParCheck(fp^.typ, ap^.typ, TRUE) IF fp^.typ^.comp = OPT.DynArr THEN DynArrParCheck(fp^.typ, ap^.typ, TRUE)
ELSIF (fp^.typ^.comp = OPT.Record) & (ap^.typ^.comp = OPT.Record) THEN ELSIF (fp^.typ^.comp = OPT.Record) & (ap^.typ^.comp = OPT.Record) THEN
q := ap^.typ; q := ap^.typ;

View file

@ -206,7 +206,13 @@ MODULE OPP; (* NW, RC 6.3.89 / 10.2.94 *) (* object model 4.12.93 *)
LOOP LOOP
IF sym = OPS.ident THEN IF sym = OPS.ident THEN
OPT.Insert(OPS.name, par); OPS.Get(sym); OPT.Insert(OPS.name, par); OPS.Get(sym);
par^.mode := mode; par^.link := NIL; IF sym = OPS.minus THEN
IF mode = OPT.VarPar THEN err(246) END;
OPS.Get(sym); par^.mode := OPT.VarPar; par^.vis := OPT.readOnlyPar
ELSE
par^.mode := mode; par^.vis := OPT.internal
END;
par^.link := NIL;
IF first = NIL THEN first := par END ; IF first = NIL THEN first := par END ;
IF firstPar = NIL THEN firstPar := par ELSE last^.link := par END ; IF firstPar = NIL THEN firstPar := par ELSE last^.link := par END ;
last := par last := par

View file

@ -56,7 +56,7 @@ CONST
SProc* = 8; CProc* = 9; IProc* = 10; Mod* = 11; Head* = 12; TProc* = 13; SProc* = 8; CProc* = 9; IProc* = 10; Mod* = 11; Head* = 12; TProc* = 13;
(* Object.vis - module visibility of objects *) (* Object.vis - module visibility of objects *)
internal* = 0; external* = 1; externalR* = 2; internal* = 0; external* = 1; externalR* = 2; readOnlyPar* = 3;
(* Object.history - History of imported objects *) (* Object.history - History of imported objects *)
inserted* = 0; same* = 1; pbmodified* = 2; pvmodified* = 3; removed* = 4; inconsistent* = 5; inserted* = 0; same* = 1; pbmodified* = 2; pvmodified* = 3; removed* = 4; inconsistent* = 5;
@ -179,7 +179,7 @@ CONST
Shdptr* = 27; Shdpro* = 28; Stpro* = 29; Shdtpro* = 30; Sxpro* = 31; Shdptr* = 27; Shdpro* = 28; Stpro* = 29; Shdtpro* = 30; Sxpro* = 31;
Sipro* = 32; Scpro* = 33; Sstruct* = 34; Ssys* = 35; Sptr* = 36; Sipro* = 32; Scpro* = 33; Sstruct* = 34; Ssys* = 35; Sptr* = 36;
Sarr* = 37; Sdarr* = 38; Srec* = 39; Spro* = 40; Slink* = 37; Sarr* = 37; Sdarr* = 38; Srec* = 39; Spro* = 40; Slink* = 37;
Scomment* = 41; Scomment* = 41; Srpar* = 42;
TYPE TYPE
ImpCtxt = RECORD ImpCtxt = RECORD
@ -835,7 +835,10 @@ BEGIN
new := NewObj(); new := NewObj();
new^.mnolev := -mno; new^.mnolev := -mno;
IF last = NIL THEN par := new ELSE last^.link := new END; IF last = NIL THEN par := new ELSE last^.link := new END;
IF tag = Svalpar THEN new^.mode := Var ELSE new^.mode := VarPar END; IF tag = Svalpar THEN new^.mode := Var
ELSIF tag = Srpar THEN new^.mode := VarPar; new^.vis := readOnlyPar
ELSE new^.mode := VarPar
END;
InStruct(new^.typ); InStruct(new^.typ);
new^.adr := OPM.SymRInt(); InName(new^.name); new^.adr := OPM.SymRInt(); InName(new^.name);
last := new; last := new;
@ -1238,7 +1241,10 @@ END Import;
BEGIN BEGIN
OutStr(result); OutStr(result);
WHILE par # NIL DO WHILE par # NIL DO
IF par^.mode = Var THEN OPM.SymWInt(Svalpar) ELSE OPM.SymWInt(Svarpar) END; IF par^.mode = Var THEN OPM.SymWInt(Svalpar)
ELSIF par^.vis = readOnlyPar THEN OPM.SymWInt(Srpar)
ELSE OPM.SymWInt(Svarpar)
END;
OutStr(par^.typ); OutStr(par^.typ);
OPM.SymWInt(par^.adr); OPM.SymWInt(par^.adr);
OutName(par^.name); par := par^.link OutName(par^.name); par := par^.link

View file

@ -178,6 +178,7 @@ Compiler Warnings
308 SYSTEM.VAL result includes memory past end of source variable; use SYSTEM.GET 308 SYSTEM.VAL result includes memory past end of source variable; use SYSTEM.GET
309 you should name this parameter type, or else no actual parameter will match 309 you should name this parameter type, or else no actual parameter will match
310 redefining standard predefined type 310 redefining standard predefined type
246 read-only parameter '-' cannot be combined with VAR
Run-time Error Messages Run-time Error Messages
-1 assertion failed, cf. SYSTEM_assert -1 assertion failed, cf. SYSTEM_assert