Assigning values to pointers or passing pointers to VAR args
Assigning values to pointers or passing pointers to VAR args
After studying several versions of the Component Pascal language report including the Windows and Linux amendments still many questions remain.
E.g. why is it possible to assign (:=) a value, e.g. a non-open ARRAY OF T, to a pointer of the value type, e.g. a POINTER TO ARRAY OF T? How can I infer this to be legal from the language report? What exactly is supposed to happen when I do this? There are many examples of this in both the Windows and the Linux version of the code, with both regular and [untagged] data on left or right side.
Same question for assigning a string literal to a POINTER TO ARRAY OF CHAR.
Similar question for passing a POINTER TO RECORD to a formal parameter e.g. IN ANYREC.
Thanks for help.
E.g. why is it possible to assign (:=) a value, e.g. a non-open ARRAY OF T, to a pointer of the value type, e.g. a POINTER TO ARRAY OF T? How can I infer this to be legal from the language report? What exactly is supposed to happen when I do this? There are many examples of this in both the Windows and the Linux version of the code, with both regular and [untagged] data on left or right side.
Same question for assigning a string literal to a POINTER TO ARRAY OF CHAR.
Similar question for passing a POINTER TO RECORD to a formal parameter e.g. IN ANYREC.
Thanks for help.
Re: Assigning values to pointers or passing pointers to VAR
I don't think it is. I get the compile error "incompatible assignment".rochus wrote:After studying several versions of the Component Pascal language report ... why is it possible to ...
Same question for assigning a string literal to a POINTER TO ARRAY OF CHAR.
Code: Select all
PROCEDURE Do*;
VAR
dart : POINTER TO ARRAY OF CHAR;
BEGIN
dart := 'Fred'
END Do;
Re: Assigning values to pointers or passing pointers to VAR
Thanks for your reply.
Here are some examples I found in the 1.7.2 Windows Blackbox framework:
(module, procedure, statement, lhs type, rhs type)
1. HostCFrames, WinInsertItem, tvi.pszText := s, pointer to array [untagged] of char, array 256 of char
2. HostCFrames, InitClass, class.lpszClassName := "Oberon Ctrl", pointer to array [untagged] of char, string literal
3. StdDialog, CheckFilter, par.label := i.item$, array 256 of char, pointer to array of char
4. StdLinks, InitDialog, dialog.cmd := p.cmd$, array 512 of char, pointer to array of char
5. StdLinks, GetCmd, cmd := v.cmd$, array of char, pointer to array of char
EDIT: here are some more
6. HostDialog, InitDialogs, col.lpCustColors := customColors, pointer to array [untagged] of integer, array 16 of integer
7. Meta, GetThisItem, i.ptr := attr.ptr, pointer to record, SYSTEM.PTR
Here are some examples I found in the 1.7.2 Windows Blackbox framework:
(module, procedure, statement, lhs type, rhs type)
1. HostCFrames, WinInsertItem, tvi.pszText := s, pointer to array [untagged] of char, array 256 of char
2. HostCFrames, InitClass, class.lpszClassName := "Oberon Ctrl", pointer to array [untagged] of char, string literal
3. StdDialog, CheckFilter, par.label := i.item$, array 256 of char, pointer to array of char
4. StdLinks, InitDialog, dialog.cmd := p.cmd$, array 512 of char, pointer to array of char
5. StdLinks, GetCmd, cmd := v.cmd$, array of char, pointer to array of char
EDIT: here are some more
6. HostDialog, InitDialogs, col.lpCustColors := customColors, pointer to array [untagged] of integer, array 16 of integer
7. Meta, GetThisItem, i.ptr := attr.ptr, pointer to record, SYSTEM.PTR
Last edited by rochus on Fri Jan 22, 2021 3:45 pm, edited 1 time in total.
Re: Assigning values to pointers or passing pointers to VAR
I have looked at the first three examples.rochus wrote:Thanks for your reply.
Here are some examples I found in the 1.7.2 Windows Blackbox framework:
(module, procedure, statement)
HostCFrames, WinInsertItem, tvi.pszText := s
HostCFrames, InitClass, class.lpszClassName := "Oberon Ctrl"
StdDialog, CheckFilter, par.label := i.item$ ...
I & 2 involve "untagged" fields. If my example had been
Code: Select all
PROCEDURE Do*;
VAR
dart : POINTER TO ARRAY [untagged] OF CHAR;
BEGIN
dart := 'Fred'
END Do;
In the third example "par.label" is not a POINTER, and I think this assignment is covered by
If p designates a pointer, p^ denotes the variable which is referenced by p. The designators p^.f, p^[e], and p^$ may be abbreviated as p.f, p[e], and p$, i.e., record, array, and string selectors imply dereferencing. Dereferencing is also implied if a pointer is assigned to a variable of a record or array type (Ch. 9.1), if a pointer is used as actual parameter for a formal parameter of a record or array type (Ch. 10.1), or if a pointer is used as argument of the standard procedure LEN (Ch. 10.3).
Re: Assigning values to pointers or passing pointers to VAR
Thanks again for your reply.
I now added the lhs and rhs types to my examples and numbered them.
>> but I would expect it to be explained in "Language Specific Issues", not in the Language Report
I also read that document, but didn't find enough information to deduce this to be legal. But apparently it takes the address of the string literal.
>> In the third example "par.label" is not a POINTER, and I think this assignment is covered by
I now also understand examples 3 to 5. I was confused by $ because I misinterpreted it as a kind of pointer dereferencing specialized for strings (so p^$ would be a double dereferencing); but apparently it can be just ignored.
I'm still investigating 1, 6 and 7.
I now added the lhs and rhs types to my examples and numbered them.
>> but I would expect it to be explained in "Language Specific Issues", not in the Language Report
I also read that document, but didn't find enough information to deduce this to be legal. But apparently it takes the address of the string literal.
>> In the third example "par.label" is not a POINTER, and I think this assignment is covered by
I now also understand examples 3 to 5. I was confused by $ because I misinterpreted it as a kind of pointer dereferencing specialized for strings (so p^$ would be a double dereferencing); but apparently it can be just ignored.
I'm still investigating 1, 6 and 7.
Re: Assigning values to pointers or passing pointers to VAR
Careful!rochus wrote:I now also understand examples 3 to 5. I was confused by $ because I misinterpreted it as a kind of pointer dereferencing specialized for strings (so p^$ would be a double dereferencing); but apparently it can be just ignored.
The example below shows some differences; open up the strings in the TRAP window.
"b^ := a" copies all 25 characters, but "c^ := a$" only copies the first 12.
The b^ line requires less code to be generated, but the c^ line is presumably faster if the string is much larger than the amount used before the 0X.
In normal use you would not notice any difference. But note that the b^ assignment is illegal if the declaration had been
Code: Select all
a : POINTER TO ARRAY 25 OF CHAR;
b, c : POINTER TO ARRAY 25 OF CHAR;
Code: Select all
PROCEDURE Do*;
VAR
m, n : INTEGER;
a, b, c : POINTER TO ARRAY 25 OF CHAR;
BEGIN
NEW (a); NEW (b); NEW (c);
a^ := 'Hello world';
a [16] := 'Q';
b^ := a;
c^ := a$;
m := LEN (a);
n := LEN (a$);
HALT (66)
END Do;
- adimetrius
- Posts: 68
- Joined: Sun Aug 04, 2019 1:02 pm
Re: Assigning values to pointers or passing pointers to VAR
The $ cannot be ignored!! And it has nothing to do with pointers. It is the string selector:
Now, a designates the whole array of N chars; while a$ designates the null-terminated string contained in array a. As you can see, no pointers involved here.
************
The [untagged] rules are somewhat poorly documented in the Platform-Specific issues. I remember I was also confused when I saw a string literal assigned to an uninitialized untagged pointer. My guess is the compiler assigns the address of the string literal in the module's constants section (MetaBlk) to the pointer, thus initializing it.
Also, FYI, BlackBox has a decent disassembler shipped within it; so you can see exactly the code that is generated for your program. Just open the ocf file thru File->Open or Info-Repository. In Herschel, the amd64 compiler, I've improved the disassembler to show global variable names and references to string and real literals, as well as some other low-level stuff.
Code: Select all
VAR a: ARRAY N OF CHAR
************
The [untagged] rules are somewhat poorly documented in the Platform-Specific issues. I remember I was also confused when I saw a string literal assigned to an uninitialized untagged pointer. My guess is the compiler assigns the address of the string literal in the module's constants section (MetaBlk) to the pointer, thus initializing it.
Also, FYI, BlackBox has a decent disassembler shipped within it; so you can see exactly the code that is generated for your program. Just open the ocf file thru File->Open or Info-Repository. In Herschel, the amd64 compiler, I've improved the disassembler to show global variable names and references to string and real literals, as well as some other low-level stuff.
Re: Assigning values to pointers or passing pointers to VAR
Thank you Robert and Adimetrius for your support.
I was able to infer and verify the following rules with untagged assignments so that only half a dozen unresolved cases remain:
If the left hand side of the assignment is a pointer to an untagged record or array, then the right hand side is assignment compatible if
a) in case of record types the right hand side is a type extension of the left side, or
b) in case of an array type the right hand side is array compatible with the left hand side.
Still open is my example 7. and also some calls to Kernel.NewObj(VAR SYSTEM.PTR, ...).
I was able to infer and verify the following rules with untagged assignments so that only half a dozen unresolved cases remain:
If the left hand side of the assignment is a pointer to an untagged record or array, then the right hand side is assignment compatible if
a) in case of record types the right hand side is a type extension of the left side, or
b) in case of an array type the right hand side is array compatible with the left hand side.
Still open is my example 7. and also some calls to Kernel.NewObj(VAR SYSTEM.PTR, ...).
Re: Assigning values to pointers or passing pointers to VAR
Rochus
I can well believe that the Platform-Specific Issues document is incomplete or unclear in this regard (specifically assignment rules with untagged variables).
If you are in a position to draft a new or improved section for the document I will ask the Center to consider updating the document accordingly.
Regards, Robert
I can well believe that the Platform-Specific Issues document is incomplete or unclear in this regard (specifically assignment rules with untagged variables).
If you are in a position to draft a new or improved section for the document I will ask the Center to consider updating the document accordingly.
Regards, Robert
- adimetrius
- Posts: 68
- Joined: Sun Aug 04, 2019 1:02 pm
Re: Assigning values to pointers or passing pointers to VAR
Can you specify your question regarding your point 7?
SYSTEM.PTR is a "pointer to anything". You may notice that in the language itself, there is no 'generic pointer': ANYPTR is a POINTER TO ANYREC, and so ANYPTR is not compatible with POINTER TO ARRAY ...
SYSTEM.PTR is compatible with both ANYPTR and POINTER TO ARRAY ... - that is, for the lhs. Importantly, afaik SYSTEM.PTR is known to the garbage collector - dynamic variables pointed at by variables of SYSTEM.PTR type are NOT collected.
SYSTEM.PTR is a "pointer to anything". You may notice that in the language itself, there is no 'generic pointer': ANYPTR is a POINTER TO ANYREC, and so ANYPTR is not compatible with POINTER TO ARRAY ...
SYSTEM.PTR is compatible with both ANYPTR and POINTER TO ARRAY ... - that is, for the lhs. Importantly, afaik SYSTEM.PTR is known to the garbage collector - dynamic variables pointed at by variables of SYSTEM.PTR type are NOT collected.