# Proposal to implement "properties" (based on Pascal)
## Background
Pascal has a property construct, that allows a "variable like"
identifier, which can either point to a field (member variable) or a
getter/setter function.
```
TFoo = class
FField: integer;
function GetProp: integer;
procedure SetProp(AVal: Integer);
property MyProp: integer read GetProp write SetProp;
property MyOtherProp: integer read FField;
end;
```
* Properties can exist in a structure, interface, or on a global level.
* Properties can be read/write, read only, write only.
* Properties can have one or more array like indexes (of any type).
```
function GetProp(AIdx:word; AIdx2: boolean): integer;
procedure SetProp(AIdx:word; AIdx2: boolean; AVal: Integer);
property MyProp[AIdx:word; AIdx2: boolean]: integer read GetProp
write SetProp;
```
* Properties can share a method, and provide an index (constant) to
identify which property called the method.
```
function GetProp(AIndex: Integer): integer;
procedure SetProp(AIndex: Integer; AValue: integer);
property MyProp1: integer index 1 read GetProp write SetProp;
property MyProp2: integer index 2 read GetProp write SetProp;
```
* Properties can have a "default" flag, indicating that the array []
access can omit the property name. I.e. accessing "Object[n]" is a
shortcut for the default property. (default for non-array properties is
being considered for future addition)
* Properties can have "default" and "stored" values for streaming
(constant or via function).
* Properties can be elevated to a higher visibility (private/public) in
inherited classes.
There may be partial overlaps with properties in Objective-C and C#
## Proposed Changes
### `DW_TAG_Property` or `DW_TAG_Property_Pascal`
This tag can occur anywhere where `DW_TAG_MEMBER` can occur. It can also
occur on a `global scope`.
It supports (at least) the following existing attributes:
* DW_AT_Name
* DW_AT_Type
* DW_AT_Accessibility
* DW_AT_external
* DW_AT_virtuality
* DW_AT_start_scope
* DW_AT_decl_column, DW_AT_decl_file and DW_AT_decl_line.
* ... others from the var/member tags, except for actual value or
location of value
It will support the following new attributes
* DW_AT_Default_Property flag
Specify this is a default property
* DW_TAG_Property_Setter
* DW_TAG_Property_Reader
* DW_TAG_Property_Default
* DW_TAG_Property_Stored
### `DW_TAG_Property_[Setter|Getter|...]`
Specifies how the property is accessed for read/write and other access.
#### Reference to a field/var/function.
* DW_AT_Property_Forward reference/constant
A reference to an existing the field or function.
* This could be a constant for the reader/default/stored accessors.
* This could be a string to support the current
`AT_APPLE_property_setter` extension
* DW_AT_Property_Object reference/expression/constant
The object on which the value is stored (value for
`DW_OP_push_object_address`). This can be omitted for inherited classes,
if it computes to the same address as the current class.
* DW_TAG_Member, DW_TAG_Variable, DW_TAG_subprogram.
For inlining the accessor. E.g. subprogram for C#
The referenced element must have the same `DW_AT_Type` as the property.
Except for "stored" which should be boolean.
#### function parameters
* A getter should
* take one parameter, which is the _this value of the object. For
global properties no parameters are given
* A setter should
* take _this as the first parameter (except for global properties)
* the `value` as the 2nd parameter.
For shared/indexed properties the order of parameters should default to
* _this
* indexes from array-like access
* the `value` (setter only)
For the **shared getter/setter index** the value of the argument must be
specified. For this the list of arguments to a getter/setter can be
specified.
* DW_TAG_Property_Argument_List
* containing a list of DW_TAG_Property_Argument
* each having the following attributes.
* DW_AT_Property_Argument_Number
zero-based number of the function parameter for which a value is given
* DW_AT_Property_Argument_Value reference or constant or expression
(returning value)
The value that should be passed
For the position of the `value` in the parameter list
* DW_AT_Property_Value_Argument_Number const/expression
The values for _this, array-index and value (if not specified) are
passed to the function remaining parameters.
#### Other attributes for getter/setter/default/stored
The following attributes should be allowed in
DW_TAG_Property_[Setter|Getter|...] to overwrite value given in the
DW_TAG_Property
* DW_AT_Accessibility
* DW_AT_external
* DW_AT_virtuality
* DW_AT_start_scope
### Other usage forms of DW_TAG_Property
To change accessibility (private/public) of a property in an inherited
class, DW_TAG_Property will be specified with just a name and accessibility.
```
DW_TAG_PROPERTY
DW_AT_NAME
DW_AT_ACCESSIBILITY
```
In more generic terms, a property that has no getter or setter, and is
not "abstract" is modifying an inherited property. Either accessibility,
or addifng "default" or "stored". (This could alternatively be done by
specifing a new attribute DW_AT_Property_Inherhit)
### Possible compatibility to existing AT_APPLE_property extension
If a property getter/setter (but not stored/default) only needs
DW_AT_Property_Forward then instead of having each of them in a
`DW_TAG_Property_[Setter|Getter]` there could be attributes in
`DW_TAG_Property`: `DW_AT_Property_Forward_Setter` and
`DW_AT_Property_Forward_Getter`
## References
FreePascal property doc
https://www.freepascal.org/docs-html/ref/refse27.html
Oxygene https://docs.elementscompiler.com/Oxygene/Members/Properties/
APPLE extension for Objective-C
https://github.com/llvm/llvm-project/blob/main/llvm/docs/SourceLevelDebugging.rst#debugging-information-format-1
--
Dwarf-discuss mailing list
Dwarf-discuss@lists.dwarfstd.org
https://lists.dwarfstd.org/mailman/listinfo/dwarf-discuss