From 63ec99e0bcf88c3be00042b27842519e787db858 Mon Sep 17 00:00:00 2001 From: Norayr Chilingarian Date: Fri, 10 Jul 2026 01:06:47 +0400 Subject: [PATCH] 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. --- src/compiler/OPB.Mod | 4 ++-- src/compiler/OPP.Mod | 8 +++++++- src/compiler/OPT.Mod | 14 ++++++++++---- src/runtime/Errors.Txt | 1 + 4 files changed, 20 insertions(+), 7 deletions(-) diff --git a/src/compiler/OPB.Mod b/src/compiler/OPB.Mod index 718d9b9e..8dedaaaa 100644 --- a/src/compiler/OPB.Mod +++ b/src/compiler/OPB.Mod @@ -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; diff --git a/src/compiler/OPP.Mod b/src/compiler/OPP.Mod index 96117cad..7af2cbdf 100644 --- a/src/compiler/OPP.Mod +++ b/src/compiler/OPP.Mod @@ -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 diff --git a/src/compiler/OPT.Mod b/src/compiler/OPT.Mod index 228a8226..7a68a701 100644 --- a/src/compiler/OPT.Mod +++ b/src/compiler/OPT.Mod @@ -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 diff --git a/src/runtime/Errors.Txt b/src/runtime/Errors.Txt index 29ed7063..7fc4c3ad 100644 --- a/src/runtime/Errors.Txt +++ b/src/runtime/Errors.Txt @@ -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