Sign in Join

Live chat for Free Pascal, Lazarus, Delphi and every Pascal programmer.

Mailing lists / fpc-devel / 2016-04

FPC implementation of attributes for language parts.

13 messages · 5 people · –

Reply by email Subscribe to this list Your subscription

Read-only archive. Use j and k to move between messages.

Maciej Izak

Moved from: "Initialize/Finalize management operators and Default intrinsic". I'd like to keep Initialize/Finalize topic more clear ;P

Small introduction:

for selected language elements in Delphi is possible to use attributes. For example in Delphi we have:

  TCustomAttribute = class(TObject)
  end;
  WeakAttribute = class(TCustomAttribute);
  UnsafeAttribute = class(TCustomAttribute);
  RefAttribute = class(TCustomAttribute);
  VolatileAttribute = class(TCustomAttribute);

which is used like this:

procedure Foo([ref] const X: TFoo); // AFAIK FPC equivalent is procedure
Foo(constref X: TFoo);

or like this for TObject field for ref. count for ARC:

[Volatile] FRefCount: Integer;

Michael Van Canneyt really doesn't like them :) :

2016-04-12 15:37 GMT+02:00 Michael Van Canneyt :

Show quoted text 35 lines
On Tue, 12 Apr 2016, Maciej Izak wrote: 2016-04-12 14:48 GMT+02:00 Michael Van Canneyt : > > I really don't think you should delegate such things to attributes. You >> make 2 completely unrelated language constructs suddenly related. A bad >> design decision. >> > > > I think you are wrong. Attributes are not only dedicated to RTTI just look > at other languages: Delphi, C#, Java. Instead of extending language into > infinity you can use simple attribute with parameter. I don't see any > reason why don't use attributes to describe some compiler/RTL behavior? > Any > attribute can be easier placed in many language structures without > breaking > language syntax. That is much harder with new keywords. > > Maybe that is not ideal but works excellent. > Nono. You deviate from an important design principle: orthogonality. By linking 2 concepts, any change in 1 concept risks to influence the other. This is ALWAYS bad. If you implement things orthogonally, a change in 1 concept does not risk influencing the other. So you will really, really have to provide better arguments than 'but works excellent'.

To clarify: I am not a big fan of the attributes syntax. But...

If attribute is used you already know that it has more "flag idea" (by analogy to RTTI attributes, anyway it does not have to be just like a flag), as in our example presented in "Initialize/Finalize management operators and Default intrinsic" topic - is more visible whole context. Introducing many new keyword is the waste and can collide with existing keywords.

I don't want the language with thousands of keywords, some things can be delegated to attributes. *That helps to keep main language more clear*.

Usage of attributes is more readable than mix of many keywords (it depends of context ofc). I think in many areas it is matter of taste. Of course is possible to implement new keywords, but
*the main idea of using attributes for syntax elements is to omit explosion of new keywords*... Just imagine this as attributes for nodes of compiler. Pure theory:

  // open mp - attributes way
  [OmpParallel]
  begin
    [OmpFor]
    for i := 1 to 10 do
      WriteLn(i);
  end;
  // new keywords way ? set of keywords?...
  ompparallelbegin
    ompfor i := 1 to 10 do
      WriteLn(i);
  end;
  // or...
  omp parallel begin
    omp for i := 1 to 10 do
      WriteLn(i);
  end;
// another example
//Throws - like java throws - used to force the caller of the method to
catch exceptions
// JSExport - some special export for JavaScript without deeper sense for
non-existing FPC JS target ;)

[Throws(EConvertError, EClassNotFound, ECrtSocket)] [JSExport('Foo')]
class procedure procedure Foo(); stdcall; overloaded; static;

// new keywords ...
class procedure procedure Foo(); stdcall; overloaded; static; throws EConvertError, EClassNotFound, ECrtSocket; {$IFDEF JS}jsexport 'foo';{$ENDIF}

The line between attribute and keyword is thin. Attribute is always declared "before". You don't need to redesign language to put something new (sometimes it is even impossible or very complicated, so attribute is the only way).

FINAL NOTE: attributes for a language should be introduced with great carefulness.

FINAL COMPROMISE: is good to allow selected attributes for Delphi compatibility (in Delphi mode only) for example to allow usage of [ref]. I'd like to run my Generics.Collections in Delphi too :). No big deal:

procedure Foo([ref] const X: TFoo);

can be interpreted just like:

procedure Foo(constref X: TFoo);

or in the future:

[Volatile] FRefCount: Integer;

can be interpreted like:

FRefCount: Integer; volatile;
Best regards, Maciej Izak

Reply by email

Sven Barth
to Maciej Izak
"Maciej Izak" wrote
Michael Van Canneyt really doesn't like them :) :

I don't like their use for this either. For their intended purpose, namely to decorate types or properties I have no complains (aside the syntax, but that's a different topic).

If attribute is used you already know that it has more "flag idea" (by

analogy to RTTI attributes, anyway it does not have to be just like a flag), as in our example presented in "Initialize/Finalize management operators and Default intrinsic" topic - is more visible whole context. Introducing many new keyword is the waste and can collide with existing keywords.

I don't want the language with thousands of keywords, some things can be

delegated to attributes. *That helps to keep main language more clear*.

Usage of attributes is more readable than mix of many keywords (it

depends of context ofc). I think in many areas it is matter of taste. Of course is possible to implement new keywords, but

*the main idea of using attributes for syntax elements is to omit

explosion of new keywords*... Just imagine this as attributes for nodes of compiler. Pure theory:

Show quoted text 8 lines
// open mp - attributes way [OmpParallel] begin [OmpFor] for i := 1 to 10 do WriteLn(i); end;

And this is something I'm strongly opposed to and which is exacty the orthogonality Michael was talking about. Attributes are supposed to be related to the RTTI, but adding them to blocks or fors does not extend any RTTI, because there is none to begin with! And that is where this whole thing stinks!

FINAL COMPROMISE: is good to allow selected attributes for Delphi

compatibility (in Delphi mode only) for example to allow usage of [ref]. I'd like to run my Generics.Collections in Delphi too :). No big deal:

Show quoted text 6 lines
procedure Foo([ref] const X: TFoo); can be interpreted just like: procedure Foo(constref X: TFoo);

Then just use an ifdef then.

That "[ref] const ..." Is even more an abomination than the attribute syntax itself already is.

Show quoted text 7 lines
or in the future: [Volatile] FRefCount: Integer; can be interpreted like: FRefCount: Integer; volatile;

Variable/field access is always volatile anyways.

Regards,
Sven

Reply by email

Michael Van Canneyt
to Maciej Izak: Moved from: "Initialize/Finalize management operators and Default intrinsic". I'd like to…
Maciej Izak wrote 23 lines
Moved from: "Initialize/Finalize management operators and Default intrinsic". I'd like to keep Initialize/Finalize topic more clear ;P Small introduction: for selected language elements in Delphi is possible to use attributes. For example in Delphi we have: TCustomAttribute = class(TObject) end; WeakAttribute = class(TCustomAttribute); UnsafeAttribute = class(TCustomAttribute); RefAttribute = class(TCustomAttribute); VolatileAttribute = class(TCustomAttribute); which is used like this: procedure Foo([ref] const X: TFoo); // AFAIK FPC equivalent is procedure Foo(constref X: TFoo); or like this for TObject field for ref. count for ARC: [Volatile] FRefCount: Integer;

Sorry. This is simply very bad design.

1. We already have a syntax for this kind of thing, it is called modifiers. No need to introduce a second syntax. You just introduce extra modifiers.

2. You make the COMPILER dependent on USER-DEFINED classes. What kind of nonsense is that ?
It is even worse than the enumerator syntax Borland/Embarcadero invented.

If the compiler needs to know about it and act on it (and it does for ARC), then it must be a keyword or modifier.

Attributes are meant for user-space information.

The compiler has no business with it, from the point of view of the compiler the presence or non-presence of attributes is entirely irrelevant. It is meant to be extracted easily by the user. No more, no less.

Attributes used like this are self-contained. You can use it or not, it makes no difference to the compiler. This is an example of _good_ design.

If you use attributes to start controlling ARC or whatever other _language feature_, this is _bad_ design, because you link one feature to another, which simply is not related to it at all.

Show quoted text 9 lines
To clarify: I am not a big fan of the attributes syntax. But... If attribute is used you already know that it has more "flag idea" (by analogy to RTTI attributes, anyway it does not have to be just like a flag), as in our example presented in "Initialize/Finalize management operators and Default intrinsic" topic - is more visible whole context. Introducing many new keyword is the waste and can collide with existing keywords.

Clearly, you are missing something very important: Modifiers are _not_ keywords. You can add as much modifiers as you want. They will never interfere with the syntax. That is the whole point of modifiers ?!

Michael.

Reply by email

Maciej Izak
to Sven Barth: I don't like their use for this either. For their intended purpose, namely to decorate…

I understand all this, and for the most part I agree, but...

2016-04-13 11:19 GMT+02:00 Sven Barth :

Show quoted text 5 lines
Then just use an ifdef then. That "[ref] const ..." Is even more an abomination than the attribute syntax itself already is.

That requires too many IFDEFs. :\, even [ref] syntax is more readable than tons of IFDEFs. Just look at Generics.* code... I'd like to see only one exception for [ref] as alternate syntax for constref to get more clear code and easier to maintenance.

Best regards, Maciej Izak

Reply by email

Maciej Izak
to Michael Van Canneyt: Sorry. This is simply very bad design. 1. We already have a syntax for this kind of…

2016-04-13 13:03 GMT+02:00 Michael Van Canneyt :

Sorry. This is simply very bad design.

I agree with many points. Frankly, I was surprised that they did something like using attributes in that way. I try to understand and find something positive.

I only like to see [ref] const as alternate syntax for constref, only for Delphi mode. It is really problematic.

Best regards, Maciej Izak

Reply by email

Michael Van Canneyt
to Maciej Izak
Maciej Izak wrote 8 lines
2016-04-13 13:03 GMT+02:00 Michael Van Canneyt : > Sorry. This is simply very bad design. > I agree with many points. Frankly, I was surprised that they did something like using attributes in that way. I try to understand and find something positive.

Sometimes, there is nothing positive to be found, even with the biggest microscope.... :-)

IMHO they are randomly copying recipes from C# and Java. Which is IMHO nonsense, since those languages are based on virtual machines, where runtime and compile-time are blurred concepts...

A losing strategy on all accounts, you should always start from your own strength and build on that.

I only like to see [ref] const as alternate syntax for constref, only for Delphi mode. It is really problematic.

I suppose that in Delphi mode, we'll need to support it anyway :/

Michael.

Reply by email

Sven Barth
to Michael Van Canneyt: Sorry. This is simply very bad design. 1. We already have a syntax for this kind of…
"Michael Van Canneyt" wrote 11 lines
On Wed, 13 Apr 2016, Maciej Izak wrote: > Moved from: "Initialize/Finalize management operators and Default > intrinsic". I'd like to keep Initialize/Finalize topic more clear ;P > > Small introduction: > > for selected language elements in Delphi is possible to use attributes.

For

Show quoted text 22 lines
> example in Delphi we have: > > TCustomAttribute = class(TObject) > end; > WeakAttribute = class(TCustomAttribute); > UnsafeAttribute = class(TCustomAttribute); > RefAttribute = class(TCustomAttribute); > VolatileAttribute = class(TCustomAttribute); > > which is used like this: > > procedure Foo([ref] const X: TFoo); // AFAIK FPC equivalent is procedure > Foo(constref X: TFoo); > > or like this for TObject field for ref. count for ARC: > > [Volatile] FRefCount: Integer; Sorry. This is simply very bad design. 1. We already have a syntax for this kind of thing, it is called

modifiers.

No need to introduce a second syntax. You just introduce extra

modifiers.

2. You make the COMPILER dependent on USER-DEFINED classes. What kind of nonsense is that ? It is even worse than the enumerator syntax Borland/Embarcadero

invented.

If the compiler needs to know about it and act on it (and it does for

ARC), then it must be a keyword or modifier.

Attributes are meant for user-space information. The compiler has no business with it, from the point of view of the

compiler

Show quoted text 7 lines
the presence or non-presence of attributes is entirely irrelevant. It is meant to be extracted easily by the user. No more, no less. Attributes used like this are self-contained. You can use it or not, it makes no difference to the compiler. This is an example of _good_ design. If you use attributes to start controlling ARC or whatever other

_language feature_, this is _bad_ design, because you link one feature to another, which simply is not related to are nice and well, but only for the area they had been designed for.

Regards,
Sven

Reply by email

Sven Barth
to Maciej Izak: I understand all this, and for the most part I agree, but... 2016-04-13 11:19 GMT+02:00…
"Maciej Izak" wrote 8 lines
I understand all this, and for the most part I agree, but... 2016-04-13 11:19 GMT+02:00 Sven Barth : > > Then just use an ifdef then. > > That "[ref] const ..." Is even more an abomination than the attribute

syntax itself already is.

That requires too many IFDEFs. :\, even [ref] syntax is more readable

than tons of IFDEFs. Just look at Generics.* code... I'd like to see only one exception for [ref] as alternate syntax for constref to get more clear code and easier to maintenance.

*I* won't add it.

Regards,
Sven

Reply by email

Maciej Izak
to Sven Barth

2016-04-13 14:36 GMT+02:00 Sven Barth :

*I* won't add it.

I can do it after merging Joost's class attributes branch. No one really won't this but it is the must. IFDEF hell is much more visible for "constref/[ref] const" than in any other place... :(

Best regards, Maciej Izak

Reply by email

Michael Van Canneyt
to Maciej Izak
Maciej Izak wrote 7 lines
2016-04-13 14:36 GMT+02:00 Sven Barth : > *I* won't add it. > I can do it after merging Joost's class attributes branch. No one really won't this but it is the must. IFDEF hell is much more visible for "constref/[ref] const" than in any other place... :(

But please, only in Delphi mode.

Michael.

Reply by email

Kazantsev Alexey
to silvioprog
silvioprog wrote 7 lines
> No one really won't this but it is the must. IFDEF hell is much more > visible for "constref/[ref] const" than in any other place... :( > I need this feature too, but for Delphi compatibility. It could avoid a lot of IFDEFs in Delphi mode.
You can use: procedure test({$I constref.inc} AIID : TGUID);
Kazantsev Alexey

Reply by email

Maciej Izak
to Michael Van Canneyt: Sometimes, there is nothing positive to be found, even with the biggest microscope.... :-)

2016-04-13 13:46 GMT+02:00 Michael Van Canneyt :

Show quoted text 14 lines
On Wed, 13 Apr 2016, Maciej Izak wrote: 2016-04-13 13:03 GMT+02:00 Michael Van Canneyt : > > Sorry. This is simply very bad design. >> >> > I agree with many points. Frankly, I was surprised that they did something > like using attributes in that way. I try to understand and find something > positive. > Sometimes, there is nothing positive to be found, even with the biggest microscope.... :-)

I think is worth to cite people from "Delphi core".

*Don't beat me for this, this is just quotation* (not my personal opinion).

Source:
http://blog.marcocantu.com/blog/2016-april-weak-unsafe-interface-references.html

by Marco Cantu:

=== quote begin ===
Odd getting two comments about the attributes syntax. First, that syntax is in the product since Delphi 2010, so not exactly new. Second this is the syntax that has been used a few years now for mobile...

As any other attribute, these attributes are applied to the following symbol. They can also be equally applied to different types of symbols (types, methods, declarations, parameters, return values). The syntax you are suggesting is hard to apply in this different cases. Also using the attribute syntax for predefined and user- defined attributes is very consistent. Other languages do it... because it is nice, expressive, and flexible.

I was in fact chatting earlier with a developer who is experimenting with the [Result: Unsafe] modifier. Hard to express with a "traditional" syntax.

BTW: there is also the new [volatile] attribute in 10.1 Berlin. === quote end ===

by Rudy Velthuis ...

=== quote begin ===
For all those who don't like the attribute syntax, it looks indeed ugly if you write

[Result: unsafe] function Bla...

but not if you format it slightly differently
(actually, the usual way):

[Result: unsafe]
function Bla...

That looks perfectly acceptable to me.
=== quote end ===

oh my... [Result: unsafe] is a monster ;d

Best regards, Maciej Izak

Reply by email