Syntax-wide this would be enough:
procedure p (const N: string);
const K: PInteger = @N; // or ... = Pointer(@N) for {$T+} if not a special case made
begin
...
end;
Make it. Compiler is not divine scripture, that mortals dare not touching. Especially as i explicitly talked about some imaginary "ideal Pascal".
You are not looking at the big picture
I think that is exactly what i do here, looking at the big picture of imaginary ideal, while ignoring small details of backward compatibility and legacy implementations :-)
First, the value of "K" changes every time the function is called.
So what? outside of the function execution span it does not exist, and inside the funcito neexecution span it does not change. Fine by me.
That hardly meets the definition of "constant".
To me it does.
procedure N(const K: integer);
begin
...
end;
Would you argue K is not constant enough, if it does not have one and the same, fixed in compile-time value no matter how many time the funciton is called ?
So, i see no more a problem with local constant getting value in the prologue, than i do with constant parameter.
In addition to that, neither O/Ss, nor any CPUs I know of provide read/write protection at the single byte/word/dword/qword level
Irrelevant, as long as we talk about language domain.
Should i repeat it again? If i look outside pure Pascal - i can call VirtualProtect or WriteProcessMemory and change eveyrthing, including string literals.
If you look at CPU level or OS level - then there is no such thing as constant at all.
So my proposal is no worse and is no less a constant than string literals, which are perfectly mutable then.
the best they can do these days is page level (often 4096) bytes.
Did you hear about DR0 .. DR3 (or was it DR7 ?) on 80386 CPU ? About TD386 debugger?
But okay, since the went THAT level of abstraction, you can dispatch a separate page for every constant. The challenge (strange one, if you ask me) complete.
But don't ask me what alleged defiiciences of mass market hardware has with hypothetical "ideal" language syntax. I did not bring it.
That means, there is no mechanism to ensure your "constant" remains constant.
False. There is. It is called language-level security/safety.
If you really need to be absolutely watertight, then Pascal should just not provide for procedure calls outside RTL and should provide no means in the language to write the code violating those constants.
For example, every pointer operation in runtime is checked by compiler against white and black lists of allowed addresses. So does Move, FillChar and everyone. So do indexed array accesses.
OS calls are barred, so is asm. No way to upset a constant.
...otherwise there is no "true constant" at all as even string literals are easily assignable using OS API.
Additionally, your constant "K" isn't a constant, it is a variable which means another variable could take its address and change its value by de-referencing it.
It is no different from all the other typed constants of today, so is not making a languageworse than it already is.
procedure N(var P: string);
var
A: string absolute P;
B: PPointer;
C: Pointer absolute B;
begin
C := @P;
B^ := nil;
A := 'absoutely safe and immutable pointer - come to me now!';
end;
actually needs the address of that "constant" for something other than changing its value ?... what then ?
Same as with de facto assignable string literals of today Pascal.
It would be enough if "normal code" would not do it by accident, protecting me from shooting my own foot.
As long as i can call OS API you can not prevent me from assigning to ANY constant. Even the constant onlined into the code can be changed together with code.
BTW, i think i saw warnings in some Pascal flavours exactly about taking pointers to specific letters in the string. And taking char pointer from a string is expensive operation (in Delphi at least), as it enforces call to UniqueString to keep preserve COW semantics in the presence of pointers. So, yeah, in practical languages abstractions do leak.
You have "writeable constants", you have managed variables that compiler DOES intialize (assign to NULL) in every funciton prologue.
Initializing typed consts would be just maryring those already existing things.
the "writeable constants" thing is a disgrace, making it even worse than it already is, is not a good idea (some of the reasons were mentioned above.) At least, in the case of writeable constants, it is fairly simple to inform a programmer that those things aren't constants, they are _variables_ (or more accurately, an identifier that is a memory address - which may or may not be writeable.)
Is it some divine rule that constant must only be calculated in compile time? Constant should not be changed by application code, and that is it. Using OS memory protection API i can easily change string literals - does it make them not constants? It does not.
Any value that is calculated at runtime, is by definition not constant because its value will change from whatever initial value the compiler assigned to it to whatever value is calculated at runtime. Therefore it is not a constant. That's not a "divine rule", it's the definition of constant, if it changes, it is _not_ a constant. What you want is a "one-time" variable.
[/quote]
Call it an ex-parenthesis constant parameter then. Whatever. A rose is a rose is a rose.
Also let's push for FPC devs to finally recognize cons parameters are not really constant butt are "externally assigned varables" and force them to change it in documentaiton first, and in syntax later.
procedure N(const Z: double); begin ... end;
If Z value can not be calcuated in compile-time it is not true constant and compilation should be aborted! Yeee-hooo!
P.S. Frankly, compared to all the low-level sideeffects use of "absolute" can bring - can anyone even make a comprehensive list of them? - the need to explain that function parameters might have different addresses on different calls seems to me a manageable problem.
Additionally, the compiler equally does NOT know that address of N in compile time when compiling "absolute N" - but this lack of knowledge does not break compilation. Because, sure, the value of @N is not known, but the value of @@N relative to the function's data frame - is known in compile time.
strictly speaking, you are correct when you say that the compiler does NOT know the address of N at compile time BUT, it _knows_ the offset from whatever point it is relative to and that's all it needs to know.
You just said the same thing i said starting with "@@N" in a more verbose form. Now, this would be EXACTLY the same with my "const-ptr-based absolute". Because it is one and the same thing, just dressed in different syntax sgar.
That's all the magic and the compiler has all the information it needs _at compile time_ to make it happen.
Bingo!!! The compiler has all the information it needs to compile the const-ptr-initialization into the function prologue!!!
You're the one who mixed Apples and Oranges by mixing "absolute" with multiple variable initialization in one of your examples.
False.
And not only false - it is impossible to mix, as absolute variables can NOT be initialized.
Surprise, right?
I always told about multiple variable defined in a single declaration, but never about being initialized.
This strawman is rotting for so long - it is getting slimey now.
1. It volates Pascal norm by de facto precluding declaring several variables in one single declaration.
It would be a contradiction, not to mention meaningless and redundant, to allow absolute in a multiple variable declaration.
No it won't. Addresses should be different which i repeated over and over again. Yet another strawman you invented to put your words into my mouths. Don't.
The rest is skipped as having zero relation to what i ever said.
This adds cognitive burden on the programmer. Wirth and Pascal proponents always championed that Pascal (and European languages) are better than C (and American languages) in their strive to simplify, remove "special cases" and lessen cognitive burden.
I see more "cognitive burden" in putting the programmer in a situation where he/she wonders why some variable "A" is being absolute-d multiple times all using the same data type. That doesn't make any sense.
So, you just said that because use of "absolute" makes program harder to READ it makes sense to make "absolute" syntax harder to WRITE.
For the sake of programmers who would later
read it makes sense in this case to put more burden on the programmer who
writes.
I agree.
"Absolute" is made in an unpascalish way explicitly discouraging its use and that is a good thing.
2. It forces programmer to copy-paste declarations if he need two "absoluted" variables of same type but different offsets.
if the offsets differ then it means that _different_ variables are being absolute-d.[/quote]
You mean the opposite thing that i meant. "Absolute-d" variable, when i wrote it, is one which declaration was changed by "absolute" keyword.
This is not only code bloat, but violating DRY principle it also becomes a maintainance bloat, as copy-pasted pieces tend to eventually diverge, link between them be forgotten, and eventually when program is updated - only some of copy-pasted pieces gets edited, introducing errors.
if anything, "absolute" makes code much clearer
Than what?
How exactly
var X: integer absolute Z; Y: integer;
more clear than
var X origin Z: integer; Y: integer;
and
var X origin Z, Y: integer;
it doesn't generate any bloat (no code is generated
It is the bloat itself, even if results in no executable opcodes.
Type declarations do not generate code just by existing, still they can be bloat and still they are source code.
should substantially reduce the need for copy/pasting.
If we think that "absolute should be promoted and make easy to use" then PDP-11 syntax is the ideal to strive for.
Then about "should" but in fact they increase.
var X origin A, Y origin B, Z: array[Low(TMyRange) .. High(TMyRange)] of array [TMyAnotherRange] of record U: double; V: real; end;
and we compare it with equivalent
var
X: array[Low(TMyRange) .. High(TMyRange)] of array [TMyAnotherRange] of record U: double; V: real; end absolute A;
Y: array[Low(TMyRange) .. High(TMyRange)] of array [TMyAnotherRange] of record U: double; V: real; end absolute B;
Z: array[Low(TMyRange) .. High(TMyRange)] of array [TMyAnotherRange] of record U: double; V: real; end;
It would take a special mindset to say the latter "should reduce the copy/paste" of the former.
And please, do not suggest me workarounds that reduce copy-paste by introducing boilerplate. I know them.However, if we consider that reducing of language vocabulary (number of keywords and special cases in syntax patterns) is a virtue and "absolute" is to be discourages because it is dangerous, then we have another pattern:
type
TMyAbsolutedArray = array[Low(TMyRange) .. High(TMyRange)] of array [TMyAnotherRange] of record U: double; V: real; end absolute A;
PMyAbsolutedArray = ^TMyAbsolutedArray;
const
X: PMyAbsolutedArray = @A;
Y: PMyAbsolutedArray = @B;
var
Z: TMyAbsolutedArray;
and it has to be compared with the same
var
X: array[Low(TMyRange) .. High(TMyRange)] of array [TMyAnotherRange] of record U: double; V: real; end absolute A;
Y: array[Low(TMyRange) .. High(TMyRange)] of array [TMyAnotherRange] of record U: double; V: real; end absolute B;
Z: array[Low(TMyRange) .. High(TMyRange)] of array [TMyAnotherRange] of record U: double; V: real; end;
or with intermediate
type
TMyAbsolutedArray = array[Low(TMyRange) .. High(TMyRange)] of array [TMyAnotherRange] of record U: double; V: real; end absolute A;
var
X: TMyAbsolutedArray absolute A;
Y: TMyAbsolutedArray absolute B;
Z: TMyAbsolutedArray;
And it is no less clear at least.
It also clearly separates normal and safe vars from absoluted and dangerous vars into different sections.
It would also clealy visually separate their consequent use later;
Z[100][20].U := 0; // safe and trivial
X^[100][20].U := 0; // non-trivial and unsafe
The visual cue that both "absolute" and "origin" lack totally.
-----------
TL;DR:
One can come from two presumptions.
Actually three, but "My habits are good, because i don't have to make effort and re-learn" is not an interesting one, so - skipped.Either the unsafe trick with absolute is good to use as often as possible and should be made as easier to use as possible.
Or this unsafe trick is dangerous and should be discouraged, and programmers should be goaded to only use it when safer approaches have worse penalties.
If the former is taken, then address should be bound to the variable name, as it was done in examples with "origin".
If the latter is taken - typed const pointer approach is better than absolute, as it achives the same without a one-use keyword and without a special case in syntax, and also provides visual cues to tell safe uses from unsafe ones.
the "absolute" keyword as it was conceived in TP combines worst aspects of those approaches.