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
| OPT.Var: node := OPT.NewNode(OPT.Nvar);
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);
node^.conval := OPT.NewConst();
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)
ELSE CheckLeaf(ap, FALSE)
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)
ELSIF (fp^.typ^.comp = OPT.Record) & (ap^.typ^.comp = OPT.Record) THEN
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
IF sym = OPS.ident THEN
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 firstPar = NIL THEN firstPar := par ELSE last^.link := par END ;
last := par

View file

@ -56,7 +56,7 @@ CONST
SProc* = 8; CProc* = 9; IProc* = 10; Mod* = 11; Head* = 12; TProc* = 13;
(* 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 *)
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;
Sipro* = 32; Scpro* = 33; Sstruct* = 34; Ssys* = 35; Sptr* = 36;
Sarr* = 37; Sdarr* = 38; Srec* = 39; Spro* = 40; Slink* = 37;
Scomment* = 41;
Scomment* = 41; Srpar* = 42;
TYPE
ImpCtxt = RECORD
@ -835,7 +835,10 @@ BEGIN
new := NewObj();
new^.mnolev := -mno;
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);
new^.adr := OPM.SymRInt(); InName(new^.name);
last := new;
@ -1238,7 +1241,10 @@ END Import;
BEGIN
OutStr(result);
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);
OPM.SymWInt(par^.adr);
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
309 you should name this parameter type, or else no actual parameter will match
310 redefining standard predefined type
246 read-only parameter '-' cannot be combined with VAR
Run-time Error Messages
-1 assertion failed, cf. SYSTEM_assert