[fpc-devel] FPC implementation of attributes for language parts.

Maciej Izak hnb.code at gmail.com
Wed Apr 13 09:42:30 CEST 2016


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 <michael at freepascal.org>:

>
>
> On Tue, 12 Apr 2016, Maciej Izak wrote:
>
> 2016-04-12 14:48 GMT+02:00 Michael Van Canneyt <michael at freepascal.org>:
>>
>> 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
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.freepascal.org/pipermail/fpc-devel/attachments/20160413/b138f4df/attachment.html>


More information about the fpc-devel mailing list