Sorry for the late reply. I've been away.
> - What does it mean for a property to be default? I couldn't find that
> defined in the linked FreePascal documentation.
The property can be accessed without its name being specified.
This currently exists for (array-like) indexed properties.
` property Foo [AnIndex: TSomeType]: TPropType read GetVal; default;`
If variable Bar is of a type having above property, then instead of
`Bar.Foo[SomeVal]`
The code/expression can read
`Bar[SomeVal]`
Bar as on object itself does not have an index. So by giving an index it
is clear that the expression accesses the property.
Currently this is limited to array-like properties. There are some ideas
to extend this, but nothing concrete.
The determination, if an expression accesses a "default property" does
not belong to the DWARF specs, it has to be done by a language specific
expression parser.
Also right now, only one indexed property can be marked default, but
this may get extended. Multiply properties with different index-types
could be each default.
> - Why is there both a DW_AT_Default_Property and
> a DW_TAG_Property_Default?
1) DW_AT_Default_Property
Above "default property".
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.
The latter can (in Pascal) be accessed via Run-Time-Type-Information. It
is e.g. used in streaming of objects.
The property can be omitted from the stream, if it has its default
value. Or when reading a stream, the default value will be assigned, if
no value is present in the stream.
The compiler only generate the RTTI. Streaming can be implemented by the
user, but the RTL provides functionality using the "default" as described.
On 2nd thought: I don't know if (or in which form) such info exists in
other languages. And the amount/kind of such info available may be
subject to change. I included it, as default-value and stored (below) in
Pascal are commonly used. But there is room to discuss them as an
extension (and possible more generic: some form of attributes that can
be associated with any value/type)
> - 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.
> - 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.
In general, this may also be useful for other languages, if they pass
multiple arguments to a getter/setter, and the order of arguments needs
to be clarified.
For the above, it avoids a (probably) Pascal specific
`DW_AT_pascal_property_index_value`.
The proposal has some notes on this in the "function parameters" section.
Example, the default parameters (without the property-index) for
- GetProp is (_this)
- GetOtherProp are (_this, a)
And setters
- SetProp is (_this, NewValue)
- SetOtherProp are (_this, a, NewValue)
The position for the value of 1 or 2 (for the property-index) must be
specified.
Alternatively, it could be hard-specified in the DWARF spec, as a
language specific order...
But then, there would be a need for `DW_AT_pascal_property_index_value`.
And other languages may need their own extra values.
The idea is, that having a property, it can be translated into a
function/method call as follows:
- 'Foo.MyProp' = `Foo.MyPropGetter()`
- global/non-class: 'MyProp' = `MyPropGetter()`
- 'Foo.MyProp[1,2]' = `Foo.MyPropGetter(1,2)`
Any arguments not specified by the user (and not _this) will be given as
a list of: argument-position / argument-value
For the classes above
```
DW_TAG_Structure_type
DW_AT_Name : "TMyClass"
L1:
DW_TAG_subprogram
DW_AT_Name : "GetProp"
DW_AT_Type : <...>
DW_TAG_formal_parameter
DW_AT_Name : "_this"
DW_TAG_formal_parameter
DW_AT_Name : "AIndex"
DW_TAG_Property
DW_AT_Name : "MyProp1"
DW_AT_Type : <...>
DW_TAG_Property_Getter
DW_AT_Property_Forward : reference to L1
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
```
For MyProp2, DW_AT_Property_Argument_Value will be 2.
For `GetOtherProp` the `DW_AT_Property_Argument_Number` would be position 2
```
DW_TAG_Structure_type
DW_AT_Name : "TMyOtherClass"
L1:
DW_TAG_subprogram
DW_AT_Name : "GetProp"
DW_AT_Type : <...>
DW_TAG_formal_parameter
DW_AT_Name : "_this"
DW_TAG_formal_parameter
DW_AT_Name : "a"
DW_TAG_formal_parameter ! argument number 2 (zero based)
DW_AT_Name : "AIndex"
DW_TAG_Property
DW_AT_Name : "MyProp1"
DW_AT_Type : <...>
DW_TAG_Property_Getter
DW_AT_Property_Forward : reference to L1
DW_TAG_Property_Argument_List
DW_AT_Property_Argument_Number : 2
! DW_TAG_formal_parameter at pos 2 "AIndex"
DW_AT_Property_Argument_Value : 1 ! the index value
```
If a setter is called, then the new value is the last argument to the
function. If any language has a different position it can specify
DW_AT_Property_Value_Argument_Number
Which is a direct child of DW_TAG_Property_Setter (not in
DW_TAG_Property_Argument_List)
For the hypothetical / non-Pascal
procedure SetOtherProp(NewVal: integer; a: boolean; AIndex: Integer);
```
DW_TAG_Property_Setter
DW_AT_Property_Forward : reference
DW_AT_Property_Value_Argument_Number : 1 ! pos of "NewVal"
DW_TAG_Property_Argument_List
DW_AT_Property_Argument_Number : 3 ! pos of "AIndex"
DW_AT_Property_Argument_Value : 1 ! the index value
```
The _this argument is passed according to normal function calling rules.
If the _this DW_TAG_formal_parameter (or DW_AT_Property_Argument_Number)
has been used by any DW_AT_Property_Argument_Number, then it needs to be
decided
- don't pass it (assume it has been set already)
- pass it in the next available param?
The arguments for the array-like index will be passed left to right in
any DW_TAG_formal_parameter that has not been used.
E.g. with DW_AT_Property_Value_Argument_Number=1
DW_TAG_formal_parameter(0): _this
DW_TAG_formal_parameter(1): new value
DW_TAG_formal_parameter(2): array-like "a" (leftmost unused param)
DW_TAG_formal_parameter(3): property-index "AIndex"
> - 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.
The proposal allows a choice of either
- DW_AT_Property_Forward
- DW_TAG_Member, DW_TAG_Variable, DW_TAG_subprogram
So, it is possible to have anonymous accessors/storage.
The forward would simple allow the debugger to identify the named member
that provides the value, if any debugger wants to maybe show that.
IMHO, if the field/accessor is on another object then the forward seems
more natural. But that is my personal preference.
If there will be functions on nested objects, the directly specifying
DW_TAG_subprogram may be misleading with regards to the correct _this
parameter (though it will work, as the param can be given by
DW_AT_Property_Object)
> - Why isn't the accessibility attribute
> on the linked DW_TAG_subprogram?
They can have different visibility.
```
TMyClass = class
private
function Getbar: boolean;
public
property bar: boolean read Getbar;
end;
```
// or even
```
TMyClass = class
private
function Getbar: boolean;
protected
property bar: boolean read Getbar;
end;
TMySubClass = class(TMyClass)
public
property bar; // only change visibility
procedure GetBar: boolean; reintroduce;
end;
```
In TMySubClass the property "bar" still calls the inherited GetBar from
the parent.
The GetBar isn't virtual, and so the new GetBar hides the parent GetBar
for any code calling GetBar directly (without the property)
> - Why is DW_AT_property_object needed?
//Example
TPoint = record x,y: integer; end;
TLine = class
private
FStart,FStop: TPoint;
public
property StartX: integer read FStart.X;
end;
In the DWARF description we would need to know if "X" is in FStart or FStop.
The DW_AT_Property_Forward would refer to the field "x" in the
DW_TAG_Structure for TPoint. So it would not indicate if that is FStart
or FStop. (since both will refer the type "TPoint")
At the moment Pascal only supports such redirects for "records" (i.e.
structures without reference, that are inlined into the parents memory).
For such structures the structure could be found from the memory location.
But for a generic approach the DW_AT_Property_Forward would point to
"X" in "TPoint", and "X" would have a DW_AT_member_location. So the
address of FStart would be needed.
Of course if DW_AT_Location pointed to the address of FStart.X then that
provides the final location.
Currently - in Pascal - such redirects only work for fields. In future
this may support functions in nested object (Though there are no current
plans). A function would need a self parameter, therefore need to know
the address of the enclosing object.
Of course the address of the object can be a DW_AT_location.
Its a matter of understanding the purpose of that location (it is not
the value itself).
And also, while I can't think of any other location that could in future
be referred from a DW_TAG_Property_[GS]etter, there may be a chance for
that to happen.
On 08/06/2024 01:12, Adrian Prantl wrote:
Hello Martin,
Thanks for submitting your proposal! In order to prepare it for discussion I
would suggest to first try pick a first choice for all the design options in
the proposal and then once the direction is clear, distill the normative text
changes that would need to be made in the DWARF specification.
Adding a new TAG called DW_TAG_property seems like a good approach. There is
nothing that's overly specific about Pascal in the proposal, so using the
generic name seems like a good choice.
I had a couple of initial questions that came up while reading through the
proposal:
- What does it mean for a property to be default? I couldn't find that defined
in the linked FreePascal documentation.
- Why is there both a DW_AT_Default_Property and a DW_TAG_Property_Default?
- What is the purpose of DW_TAG_Property_Stored? Maybe also add an example for
this.
- DW_TAG_Property_Argument_List would also benefit from an example.
- 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?
- Why isn't the accessibility attribute on the linked DW_TAG_subprogram?
After having read the last example, I think I can answer my question from
above: Pascal allows to specify an access path to a (nested) field as the read
accessor.
- Why is DW_AT_property_object needed? Couldn't the debugger determine the
location from following the DW_AT_Property_Forward link? Related: Does this
need to be a new attribute, or could this be DW_AT_location?
--
Dwarf-discuss mailing list
Dwarf-discuss@lists.dwarfstd.org
https://lists.dwarfstd.org/mailman/listinfo/dwarf-discuss