Assigning values to pointers or passing pointers to VAR args

Programming language questions
rochus
Posts: 13
Joined: Sat Dec 12, 2020 1:15 pm

Assigning values to pointers or passing pointers to VAR args

Post by rochus »

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.
User avatar
Robert
Posts: 177
Joined: Sat Sep 28, 2013 11:04 am
Location: Edinburgh, Scotland

Re: Assigning values to pointers or passing pointers to VAR

Post by Robert »

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.
I don't think it is. I get the compile error "incompatible assignment".

Code: Select all

PROCEDURE  Do*;
  VAR
    dart  :  POINTER  TO  ARRAY  OF  CHAR;
  BEGIN
    dart :=  'Fred'
  END  Do;
rochus
Posts: 13
Joined: Sat Dec 12, 2020 1:15 pm

Re: Assigning values to pointers or passing pointers to VAR

Post by rochus »

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
Last edited by rochus on Fri Jan 22, 2021 3:45 pm, edited 1 time in total.
User avatar
Robert
Posts: 177
Joined: Sat Sep 28, 2013 11:04 am
Location: Edinburgh, Scotland

Re: Assigning values to pointers or passing pointers to VAR

Post by Robert »

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 have looked at the first three examples.
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;
it would compile ok. I don't fully understand untagged, but I would expect it to be explained in "Language Specific Issues", not in the Language Report.

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).
rochus
Posts: 13
Joined: Sat Dec 12, 2020 1:15 pm

Re: Assigning values to pointers or passing pointers to VAR

Post by rochus »

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.
User avatar
Robert
Posts: 177
Joined: Sat Sep 28, 2013 11:04 am
Location: Edinburgh, Scotland

Re: Assigning values to pointers or passing pointers to VAR

Post by Robert »

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.
Careful!

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;
User avatar
adimetrius
Posts: 68
Joined: Sun Aug 04, 2019 1:02 pm

Re: Assigning values to pointers or passing pointers to VAR

Post by adimetrius »

The $ cannot be ignored!! And it has nothing to do with pointers. It is the string selector:

Code: Select all

VAR a: ARRAY N OF CHAR
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.
rochus
Posts: 13
Joined: Sat Dec 12, 2020 1:15 pm

Re: Assigning values to pointers or passing pointers to VAR

Post by rochus »

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, ...).
User avatar
Robert
Posts: 177
Joined: Sat Sep 28, 2013 11:04 am
Location: Edinburgh, Scotland

Re: Assigning values to pointers or passing pointers to VAR

Post by Robert »

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
User avatar
adimetrius
Posts: 68
Joined: Sun Aug 04, 2019 1:02 pm

Re: Assigning values to pointers or passing pointers to VAR

Post by adimetrius »

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.
Post Reply