[Dwarf-discuss] Proposal: Add support for "property" with getter/setter (based on Pascal properties)

Martin lists@mfriebe.de
Sat Jun 22 23:22:15 GMT 2024


On 22/06/2024 23:22, Adrian Prantl via Dwarf-discuss wrote:

>> 2) DW_TAG_Property_Default
>> "default value" of a property.
>>
>> property Foo: integer read FFoo default 1;
>> // In Pascal, there is no semicolon before "default" for this.
>>
...
> Here I think it would be appropriate to use DW_AT_default_value (the new 
> variant defined in https://dwarfstd.org/issues/141117.1.html 
> <https://dwarfstd.org/issues/141117.1.html> that takes an arbitrary string).

Yes, that should work.


>> > - What is the purpose of DW_TAG_Property_Stored?
>> > Maybe also add an example for this.
>>
>> The DW_TAG_Property_Stored is used in a similar fashion as default. 
>> But provide just a boolean.
>>
>> It is also accessible via RTTI. It can be a constant but often is a 
>> function.
>>
>> property Foo: integer read FFoo stored GetFooStored;
>>
>> If the properties value is only meaningful when the object is in a 
>> specific state, then GetFooStored could return true/false depending on 
>> that state.
>>
>> E.g. if a RGBA color has a flag "Solid", then when it is solid, it 
>> needs no alpha channel. The object may not want the unused alpha value 
>> to appear in a stream. It could then implement a stored-function for 
>> the Alpha property.
> 
> Interesting, am I misunderstanding or does Pascal use the exact inverse 
> nomenclature that Swift uses 
> (https://docs.swift.org/swift-book/documentation/the-swift-programming-language/properties/ <https://docs.swift.org/swift-book/documentation/the-swift-programming-language/properties/>)?
> In Swift a stored property is one that is backed by a field in the 
> record, and a computed property is value produced by a function. It 
> sounds like in Pascal it's the exact opposite? Or does "stored function" 
> mean something different?

It is something different.

In Pascal the storage/computed depends on the getter/setter.
`property Foo: integer read _Field_Foo_  write _Field_Foo_;`
`property Bar: integer read _Function_Get_Bar  write _Function_Set_Bar;`

It can also be mixed, i.e. a getter reading a field, and a setter 
calling a function.

"stored" is an additional value/function associated with the property 
(and does not depend on the presence of a field).
```
   property Some integer
     read _Function_Get_Some
     write _Function_Set_Some
     stored _Function_Some_IsStored; // should be stored
```
It does not affect setting/getting the value itself.
It is (can be) used when the data is streamed (e.g. ToJson, ToXml, ...).
The code that does the streaming can call the function, and then omit 
the field from the resulting json or xml.





>>
>> > - DW_TAG_Property_Argument_List would also benefit from an example.
>>
>> The current use case would be several properties using the same getter.
>> Each property has an "index" (not the array-like index sorry another 
>> naming conflict, will call this one "property-index").
>>
>> ```
>> class TMyClass
>> function GetProp(AIndex: Integer): integer;
>>  property MyProp1: integer index 1 read GetProp;
>>  property MyProp2: integer index 2 read GetProp
>> end;
>>
>> class TMyOtherClass
>> function GetOtherProp(a: boolean; AIndex: Integer): integer;
>>  property MyProp1[a:integer]: integer index 1 read GetOtherProp;
>>  property MyProp2[a:integer]: integer index 2 read GetOtherProp;
>> end;
>> ```
>>
>> The property-index is passed as one of the arguments to the function.
> 
> Oh interesting, so here you declare on getter that handles multiple 
> properties and the language provides syntax for passing fixed or dynamic 
> arguments to that function. Yes, this will need special support in the 
> form of a custom Tag/Attribute. I'll think about this some more, but it 
> might be nice to come up with a representation that also works for other 
> languages that allow an arbitrary function to be used as a getter/setter 
> (like Objective-C) and maybe it can be combined with the existing 
> DW_AT_default_value, to represent the property index, but I'm not sure 
> about the subscript index.
> 

I probably misread the above (if it is "putting the values as defaults 
in the function itself). Probably not what you meant, as your example 
further down does seem to keep them in the property.

As the function should be able to be specified by referring an existing 
function, that function can already have defaults for its parameters. 
Those would not be used, if invoked for the property.

```
TMyClass
     function GetFoo(AnIndex: integer): char;
     property Foo: char index 1 read GetFoo;
```
Accessing the property will call GetFoo. But code can call the function 
directly too (and then the function params could benefit from defaults).


>>    DW_TAG_Property
>>        DW_AT_Name             :  "MyProp1"
>>        DW_AT_Type             :  <...>
>>      DW_TAG_Property_Getter
>>          DW_AT_Property_Forward :  reference to L1
> 
> Any reason not to use DW_AT_specification for this?

DW_AT_specification should be fine.

> 
>>        DW_TAG_Property_Argument_List
>>            DW_AT_Property_Argument_Number : 1
>>                         ! DW_TAG_formal_parameter at pos 1 "AIndex"
>>            DW_AT_Property_Argument_Value : 1    ! the index value
> 
> We may be able to reuse a sequence of DW_TAG_format_parameter with 
> DW_AT_default_value here to avoid introducing multiple specialized 
> tags/attributes.

Yes, that would work.
In this case we can skip specifying the index/pos, if instead we can 
give special "default values" for:
- _this  (or the _this parameter is never in the list, and always 
allocated following calling conventions)
- new value for setter
- user specified array-like-index values
   (allow reordering by specifying the index in the user given list?)


```
     function GetFoo(x: word; AIndex: Integer): char;
     property Foo[x: word]: char index 1 read GetFoo;
```

```
       DW_TAG_Property_Getter
           DW_AT_Property_Forward :  reference to L1
         DW_TAG_format_parameter
             DW_AT_default_value : <special _this>
             DW_AT_default_value : constant 1  ! property index
             DW_AT_default_value : <special user array index>
```

For some basic cases, there could be language specific defaults listed 
in the dwarf spec. So the list can be omitted.


>>
>> > - If I understand correctly, the purpose of DW_AT_Property_Forward
>> > is to reference a getter or setter DW_TAG_subprogram.
>> >  Is there a specific reason you decided for this representation
>> >  over nesting a DW_TAG_subprogram with a DW_AT_property_getter 
>> (true) inside the DW_TAG_property?
>>
>> Actually it can refer any other (non-property) member of an object. 
>> (function, member, or variable (static member).
>> Or for properties outside a class, it can refer a function or variable.
> 
> I see, so it needs to be a DIE reference. We might be able to reuse 
> DW_AT_specification for this purpose though.

Yes, same as in the example above.




More information about the Dwarf-discuss mailing list