Sign in Join

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

Mailing lists / fpc-devel / 2013-02

Feature announcement: Type helpers

46 messages · 14 people · –

Reply by email Subscribe to this list Your subscription

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

Sven Barth

Hello Free Pascal community!

I'm pleased to announce the addition of type helpers which extend the existing helper concept with the ability to extend primitive types.

Motivation:

With class and record helpers the possibility was created to extend classes and records with types without subclassing the type (which wouldn't be possible with records anyway). This allows to add e.g. methods to types in units that you can't influence or where you can't influence with type is instantiated (e.g. the TStrings descendant used in TMemo). Now it is logical to extend this also to other types supported by Pascal, but here more driven by the possibility to group methods together and have them appear to belong to the primitive type.

While this does not bring the concepts of boxing of managed languages/environments like Java and .NET to Pascal it does nevertheless look this way.

Syntax:

The declaration of type helpers looks as follows:

TYPENAME = type helper[(BASEHELPER)] for EXTENDEDTYPE DECLARATIONS
end;

Like class and record helpers they support all visibility sections and you can define methods, properties and constructors. Inside methods declared in the helper "Self" will be of the extended type's type and it's value can also be changed.
Similar to record helpers class methods MUST be declared as static.

Usage:

A type helper is active if it is in scope. This means it must either have been declared in the same unit before the code which wants to use the helper or it needs to be declared in a used unit. As with class and type helpers only one helper for a given type can be active and thus you need to keep in mind the scoping rules when using helpers (e.g. the current unit is searched in the order implementation section then interface section (if the code is in the implementation section) and then the used units are searched from right to left and each unit from top to bottom).

In some cases the meaning of a type depends on the compiler settings the helper is compiled with. E.g. the type Integer is either a ShortInt or a LongInt depending on the current mode (fpc/tp vs. objfpc/delphi) and the type String is different depending on the switches {$H+/-} and {$modeswitch unicodestring}. This needs to be kept in mind when working with these "generic" types. Another special case is the type Extended on platforms that don't support that type (and thus it will be defined as Double).
Additionally a type declared as "NewType = type OldType" is considered a completly independant type as it is the case with e.g. operator overloads as well.

If a helper for the type is in scope you can simply invoke it's methods or properties like you'd do on classes or records. Let's suppose we have a helper with method "ToString: String" for the type LongInt in scope then it will look like this:

=== example begin ===

var
   i: LongInt;
begin
    Writeln(i.ToString);
end.

=== example end ===

Additionally to invoking type helpers on variables they can also be used on constants though special care needs to be taken that the correct type is used. E.g. the constant "200" will be handled as a "Byte" whereas "20" will be handled as "SmallInt". Also the type of string constants depends on the current mode switch (especially {$H+/-} and {$modeswitch unicodestring}) and also the content of the string. E.g. in case of "{$mode objfpc}{$H+}" a string containing unicode characters will be handled as a UnicodeString constant and thus only helpers for UnicodeString will apply.

For the following example let's assume the helper from the previous example is in scope again:

=== example begin ===

begin
   Writeln($12345678.ToString);
end.

=== example end ===

Additionally addresses (e.g. "@i") (type: Pointer) and the built in constants "True" (type: Boolean), "False" (type: Boolean) and "Nil" (type: Pointer) are allowed as well. Please note that in the case of typed addresses also the untyped pointer type will be used, because a corresponding typename might not be available to the current unit (and thus the helper could not be found). Constants that can't be used with type helpers are set and array constructors.

Class methods (and properties) can be either used on variables or constants, but also on the type name itself:

=== example begin ===

type
   TLongIntHelper = type helper for LongInt
     class procedure Test; static;
   end;
class procedure TLongIntHelper.Test;
begin
   Writeln('Test');
end;
var
   i: LongInt;
begin
   i.Test;
   $12345678.Test;
   LongInt.Test;
end.

=== example end ===

Supported types:

There is a restrictions on the type which can be extended. Basically every primitive type is allowed besides the following:

* file types (TextFile, file of ...)
* procedural variables

Of course types like records, classes, Objective C classes, C++ classes, objects and interfaces are forbidden as well.

Viewed from the other perspective this means that the following types are allowed:

* ordinal types
* string types (including char types)
* set and enum types
* array types
* boolean types
* Variant
* floating point types
* pointer types

Delphi compatibility:

This feature was introduced by Delphi XE3, but instead of using the more logical "type helper" syntax they added support for primitive types to the "record helper" one. Thus to keep Delphi compatibility this is also the syntax used in mode Delphi. Also in non Delphi modes inheritance for helper types is supported.

Future developments:

Add support for more types, especially interface and object types. They will either be added as class helpers or as "object helper" and "interface helper" (as objects and interfaces support inheritance the scoping rules inside the helper will resemble class helpers more than record/type helpers).

Allow that multiple helpers are active for one type at a single time. This is one of the main restrictions of the current helper implementation. For this corresponding lookup rules need to be defined and the feature will be added as a modeswitch (maybe by default enabled in mode objfpc).

Add support for helpers to the JVM target. The most likely implementation approach is to pass the "Self" value as an additional parameter and treat the methods otherwise as static ones (like is done in .NET for helper methods).

Regards,
Sven

Reply by email

Michael Van Canneyt
to Mattias Gaertner
Mattias Gaertner wrote 14 lines
On Wed, 06 Feb 2013 10:49:36 +0100 Sven Barth wrote: > [...] Hello Free Pascal community! > === example begin === > > var > i: LongInt; > begin > Writeln(i.ToString); > end. And how is toString declared?

Something like

type
   TLongIntHelper = type helper for LongInt
     function toString : AnsiString;
   end;
function TLongIntHelper.toString : AnsiString;
begin
   Result:=IntToStr(Self);
end;

Michael.

Reply by email

Sven Barth
to Michael Van Canneyt
Michael Van Canneyt wrote 10 lines
On Wed, 6 Feb 2013, Sven Barth wrote: > Hello Free Pascal community! > > I'm pleased to announce the addition of type helpers which extend the > existing helper concept with the ability to extend primitive types. Haha, finally after 7 years of waiting we catch up with Morfik...

In how far? I've read about Morfik just now on Wikipedia, but I found nothing referring to something like type helpers, so if you could please elaborate? :)

Thank you very much Sven, excellent work ! :-)

You're welcome. And now I'm going to make Marco happy by further improving generics :)

Regards,
Sven

Reply by email

Michael Van Canneyt
to Sven Barth
Sven Barth wrote 14 lines
Am 06.02.2013 11:03, schrieb Michael Van Canneyt: > > > On Wed, 6 Feb 2013, Sven Barth wrote: > >> Hello Free Pascal community! >> >> I'm pleased to announce the addition of type helpers which extend the >> existing helper concept with the ability to extend primitive types. > > Haha, finally after 7 years of waiting we catch up with Morfik... In how far? I've read about Morfik just now on Wikipedia, but I found nothing referring to something like type helpers, so if you could please elaborate? :)

It does what type helpers do. Only they implemented it by 'refactoring' the code.

By themselves I think they are pretty useless.

The main advantage is in the codetools of the IDE.

With helpers you can do
   i.<ctrl-space>
and get a list of methods, for example ToString;

Which, for newbies, is easier than guessing IntToStr()

We'll have to make some units with 'standard' helpers.

I assume Delphi XE3 has such a unit, we can use that for inspiration.

> Thank you very much Sven, excellent work ! :-) You're welcome. And now I'm going to make Marco happy by further improving generics :)

You might want to look at the bug reported by Ido Kanner ;-)

Michael.

Reply by email

Marco van de Voort
to Michael Van Canneyt

In our previous episode, Michael Van Canneyt said:

Show quoted text 7 lines
With helpers you can do i.<ctrl-space> and get a list of methods, for example ToString; Which, for newbies, is easier than guessing IntToStr() We'll have to make some units with 'standard' helpers.

Well, newbies are not to strong in knowing what is which unit either :-)

Reply by email

Michael Van Canneyt
to Marco van de Voort
Marco van de Voort wrote 10 lines
In our previous episode, Michael Van Canneyt said: > With helpers you can do > i.<ctrl-space> > and get a list of methods, for example ToString; > > Which, for newbies, is easier than guessing IntToStr() > We'll have to make some units with 'standard' helpers. Well, newbies are not to strong in knowing what is which unit either :-)

If we're talking newbies and IDE:

They don't need to, if the IDE puts the unit in the uses clause to start with...

Michael.

Reply by email

Marco van de Voort
to Michael Van Canneyt

In our previous episode, Michael Van Canneyt said:

Show quoted text 5 lines
> Well, newbies are not to strong in knowing what is which unit either :-) If we're talking newbies and IDE: They don't need to, if the IDE puts the unit in the uses clause to start with...

That's completely new functionality. Afaik most unit adding of IDEs is hardcoded?.

Reply by email

Michael Van Canneyt
to Marco van de Voort
Marco van de Voort wrote 9 lines
In our previous episode, Michael Van Canneyt said: >> Well, newbies are not to strong in knowing what is which unit either :-) > > If we're talking newbies and IDE: > > They don't need to, if the IDE puts the unit in the uses clause to start with... That's completely new functionality. Afaik most unit adding of IDEs is hardcoded?.

I know.
The codetools need to recognize type helpers in the first place.

Then we can start thinking about changing the default unit uses clause. For instance in the package lazarusforeducation or so.

Anyway, I just wanted to point out which advantages I see (or do not see) in type helpers.

By themselves, I think they are worthless.

Michael.

Reply by email

Mattias Gaertner
to Marco van de Voort: In our previous episode, Michael Van Canneyt said: That's completely new functionality.…

Marco van de Voort hat am 6. Februar 2013 um 11:41 geschrieben:

Show quoted text 10 lines
In our previous episode, Michael Van Canneyt said: > > Well, newbies are not to strong in knowing what is which unit either :-) > > If we're talking newbies and IDE: > > They don't need to, if the IDE puts the unit in the uses clause to start > with... That's completely new functionality. Afaik most unit adding of IDEs is hardcoded?.

No.
Code completion and identifier completion add the units it finds. Maybe you mean the hard coded uses sections when creating a new project/unit?

Mattias

Reply by email

Mattias Gaertner
to Michael Van Canneyt: If we're talking newbies and IDE: They don't need to, if the IDE puts the unit in the…

Michael Van Canneyt hat am 6. Februar 2013 um 11:38 geschrieben:

Show quoted text 19 lines
On Wed, 6 Feb 2013, Marco van de Voort wrote: > In our previous episode, Michael Van Canneyt said: >> With helpers you can do >> i.<ctrl-space> >> and get a list of methods, for example ToString; >> >> Which, for newbies, is easier than guessing IntToStr() > >> We'll have to make some units with 'standard' helpers. > > Well, newbies are not to strong in knowing what is which unit either :-) If we're talking newbies and IDE: They don't need to, if the IDE puts the unit in the uses clause to start with...

i.<ctrl-space>

will only show identifiers in scope, that excludes units not in the uses section.

Cody's identifier dictionary can add identifiers and units, that are not in scope. But it currently only supports top level identifiers.

Mattias

Reply by email

Henry Vermaak
to Michael Van Canneyt: I know. The codetools need to recognize type helpers in the first place. Then we can…
Michael Van Canneyt wrote 19 lines
On Wed, 6 Feb 2013, Marco van de Voort wrote: >In our previous episode, Michael Van Canneyt said: >>>Well, newbies are not to strong in knowing what is which unit either :-) >> >>If we're talking newbies and IDE: >> >>They don't need to, if the IDE puts the unit in the uses clause to start with... > >That's completely new functionality. Afaik most unit adding of IDEs is >hardcoded?. I know. The codetools need to recognize type helpers in the first place. Then we can start thinking about changing the default unit uses clause. For instance in the package lazarusforeducation or so. Anyway, I just wanted to point out which advantages I see (or do not see) in type helpers.

Thanks for pointing out the advantages. I can see the point, but can't help to think that I'll be reading code like this soon:

s := '(' + x.ToString + ', ' + y.ToString + ')';

Instead of

s := Format('(%d, %d)', [x, y]);

What I'm trying to say with this (admittedly contrived) example is that when you are forced to read the docs to find out which functions you can use for converting numbers to strings, you'll probably discover functions like Format. At least in my case, the most useful tricks I learn come from reading the documentation for something, then exploring a bit.

I apologise if I come across as overly cynical and I do appreciate Sven's work in the compiler!

Henry

Reply by email

Roberto P.
to Michael Van Canneyt: I know. The codetools need to recognize type helpers in the first place. Then we can…

2013/2/6 Michael Van Canneyt

Show quoted text 9 lines
On Wed, 6 Feb 2013, Marco van de Voort wrote: Anyway, I just wanted to point out which advantages I see (or do not see) in type helpers. By themselves, I think they are worthless.

If used appropriately, they can improve the readability.

R#

Show quoted text 6 lines
Michael. ______________________________**_________________ fpc-devel maillist - http://lists.freepascal.org/**mailman/listinfo/fpc-devel<http://lists.freepascal.org/mailman/listinfo/fpc-devel>

Reply by email

Michael Schnell
to Henry Vermaak: Thanks for pointing out the advantages. I can see the point, but can't help to think…
Henry Vermaak wrote 8 lines
I can see the point, but can't help to think that I'll be reading code like this soon: s := '(' + x.ToString + ', ' + y.ToString + ')'; Instead of s := Format('(%d, %d)', [x, y]);

In fact to me the first expression does look really nice (even though I am 60 Years old and do Pascal since the "Turbo" days and C since ages, ad strongly dislike weakly typed languages).

-Michael

Reply by email

Michael Van Canneyt
to Henry Vermaak: Thanks for pointing out the advantages. I can see the point, but can't help to think…
Henry Vermaak wrote 36 lines
On Wed, Feb 06, 2013 at 11:52:27AM +0100, Michael Van Canneyt wrote: > On Wed, 6 Feb 2013, Marco van de Voort wrote: > >> In our previous episode, Michael Van Canneyt said: >>>> Well, newbies are not to strong in knowing what is which unit either :-) >>> >>> If we're talking newbies and IDE: >>> >>> They don't need to, if the IDE puts the unit in the uses clause to start with... >> >> That's completely new functionality. Afaik most unit adding of IDEs is >> hardcoded?. > > I know. The codetools need to recognize type helpers in the first > place. > > Then we can start thinking about changing the default unit uses clause. > For instance in the package lazarusforeducation or so. > > Anyway, I just wanted to point out which advantages I see (or do not see) in type helpers. Thanks for pointing out the advantages. I can see the point, but can't help to think that I'll be reading code like this soon: s := '(' + x.ToString + ', ' + y.ToString + ')'; Instead of s := Format('(%d, %d)', [x, y]); What I'm trying to say with this (admittedly contrived) example is that when you are forced to read the docs to find out which functions you can use for converting numbers to strings, you'll probably discover functions like Format. At least in my case, the most useful tricks I learn come from reading the documentation for something, then exploring a bit.

True. It gets worse:

One can wonder whether

   s:='(%d, %d)'.format([x, y]);

is more or less clear than

   s := Format('(%d, %d)', [x, y]);

:-)

Michael.

Reply by email

Michael Schnell
to Michael Van Canneyt
Michael Van Canneyt wrote 11 lines
One can wonder whether s:='(%d, %d)'.format([x, y]); is more or less clear than s := Format('(%d, %d)', [x, y]);

but I feel

   point.x := x;
   point.y := y;
   s := point.ToString;

is most clear.

-Michael

Reply by email

Sven Barth
to Mattias Gaertner: On Wed, 06 Feb 2013 10:49:36 +0100 And how is toString declared? Mattias
Mattias Gaertner wrote 12 lines
On Wed, 06 Feb 2013 10:49:36 +0100 Sven Barth wrote: > [...] Hello Free Pascal community! > === example begin === > > var > i: LongInt; > begin > Writeln(i.ToString); > end. And how is toString declared?

I've mentioned it directly above the example in the prosa text. I thought this was clear enough; seems that I was wrong...

Regards,
Sven

Reply by email

Sven Barth
to Michael Van Canneyt: It does what type helpers do. Only they implemented it by 'refactoring' the code. By…
Michael Van Canneyt wrote
We'll have to make some units with 'standard' helpers.

I agree.

I assume Delphi XE3 has such a unit, we can use that for inspiration.

The problem is that Delphi stuffs all helpers into the main units... e.g. TStringHelper and TDateTimeHelper are both located in unit System...

Show quoted text 5 lines
>> Thank you very much Sven, excellent work ! :-) > You're welcome. And now I'm going to make Marco happy by further > improving generics :) You might want to look at the bug reported by Ido Kanner ;-)

He's using TFPSMap, not TFPGMap :)

Nevertheless I had taken a quick look, but I don't know what's really wrong yet...

Regards,
Sven

Reply by email

Sven Barth
to Henry Vermaak: Thanks for pointing out the advantages. I can see the point, but can't help to think…
Henry Vermaak wrote 25 lines
On Wed, Feb 06, 2013 at 11:52:27AM +0100, Michael Van Canneyt wrote: > On Wed, 6 Feb 2013, Marco van de Voort wrote: > >> In our previous episode, Michael Van Canneyt said: >>>> Well, newbies are not to strong in knowing what is which unit either :-) >>> If we're talking newbies and IDE: >>> >>> They don't need to, if the IDE puts the unit in the uses clause to start with... >> That's completely new functionality. Afaik most unit adding of IDEs is >> hardcoded?. > I know. The codetools need to recognize type helpers in the first > place. > > Then we can start thinking about changing the default unit uses clause. > For instance in the package lazarusforeducation or so. > > Anyway, I just wanted to point out which advantages I see (or do not see) in type helpers. Thanks for pointing out the advantages. I can see the point, but can't help to think that I'll be reading code like this soon: s := '(' + x.ToString + ', ' + y.ToString + ')'; Instead of s := Format('(%d, %d)', [x, y]);

I suppose there are quite some people (especially newbies ^^) who write it like this:

s := '(' + IntToStr(x) + ', ' + IntToStr(y) + ')';

And here I would prefer the "ToString" variant (but my personal favorit is the "Format" one :) )

Regards,
Sven

Reply by email

Henry Vermaak
to Sven Barth
Sven Barth wrote 16 lines
Am 06.02.2013 12:13, schrieb Henry Vermaak: >Thanks for pointing out the advantages. I can see the point, but can't >help to think that I'll be reading code like this soon: > >s := '(' + x.ToString + ', ' + y.ToString + ')'; > >Instead of > >s := Format('(%d, %d)', [x, y]); I suppose there are quite some people (especially newbies ^^) who write it like this: s := '(' + IntToStr(x) + ', ' + IntToStr(y) + ')'; And here I would prefer the "ToString" variant (but my personal favorit is the "Format" one :) )

No, you miss my point. Let me put it this way: You're trading one type of discoverability for another.

With type helpers, it becomes easy to discover that I can type x.<Ctrl-Space> and immediately see ToString. But I'll never learn of Format(), Trim(), etc. this way.

With IntToStr, the initial discoverability is hard, since I need to know about IntToStr in the first place. But when I <Ctrl-Click> on IntToStr, I immediately see Format(), Trim(), AdjustLineBreaks(), etc.

Henry

Reply by email

Ludo Brands
to Sven Barth: I suppose there are quite some people (especially newbies ^^) who write it like this: s…
Sven Barth wrote 18 lines
Am 06.02.2013 12:13, schrieb Henry Vermaak: > Thanks for pointing out the advantages. I can see the point, but can't > help to think that I'll be reading code like this soon: > > s := '(' + x.ToString + ', ' + y.ToString + ')'; > > Instead of > > s := Format('(%d, %d)', [x, y]); I suppose there are quite some people (especially newbies ^^) who write it like this: s := '(' + IntToStr(x) + ', ' + IntToStr(y) + ')'; And here I would prefer the "ToString" variant (but my personal favorit is the "Format" one :) )

Funny to see that all these fans of a strongly typed pascal prefer Format() that is using variants, has an undetermined number of parameters, doesn't give the compiler any opportunity to check the types used and causes runtime errors when a wrong type or a wrong number of parameters is passed ;)

Ludo

Reply by email

Sven Barth
to Ludo Brands
Ludo Brands wrote 23 lines
On 02/06/2013 01:12 PM, Sven Barth wrote: > Am 06.02.2013 12:13, schrieb Henry Vermaak: >> Thanks for pointing out the advantages. I can see the point, but can't >> help to think that I'll be reading code like this soon: >> >> s := '(' + x.ToString + ', ' + y.ToString + ')'; >> >> Instead of >> >> s := Format('(%d, %d)', [x, y]); > I suppose there are quite some people (especially newbies ^^) who write > it like this: > > s := '(' + IntToStr(x) + ', ' + IntToStr(y) + ')'; > > And here I would prefer the "ToString" variant (but my personal favorit > is the "Format" one :) ) > Funny to see that all these fans of a strongly typed pascal prefer Format() that is using variants, has an undetermined number of parameters, doesn't give the compiler any opportunity to check the types used and causes runtime errors when a wrong type or a wrong number of parameters is passed ;)

But you seperate the view (the format string) from the model (the data which is passed in), which is good :)

Regards,
Sven

Reply by email

Sven Barth
to Henry Vermaak: No, you miss my point. Let me put it this way: You're trading one type of…
Henry Vermaak wrote 27 lines
On Wed, Feb 06, 2013 at 01:12:59PM +0100, Sven Barth wrote: > Am 06.02.2013 12:13, schrieb Henry Vermaak: >> Thanks for pointing out the advantages. I can see the point, but can't >> help to think that I'll be reading code like this soon: >> >> s := '(' + x.ToString + ', ' + y.ToString + ')'; >> >> Instead of >> >> s := Format('(%d, %d)', [x, y]); > I suppose there are quite some people (especially newbies ^^) who > write it like this: > > s := '(' + IntToStr(x) + ', ' + IntToStr(y) + ')'; > > And here I would prefer the "ToString" variant (but my personal > favorit is the "Format" one :) ) No, you miss my point. Let me put it this way: You're trading one type of discoverability for another. With type helpers, it becomes easy to discover that I can type x.<Ctrl-Space> and immediately see ToString. But I'll never learn of Format(), Trim(), etc. this way. With IntToStr, the initial discoverability is hard, since I need to know about IntToStr in the first place. But when I <Ctrl-Click> on IntToStr, I immediately see Format(), Trim(), AdjustLineBreaks(), etc.

But he might or might not scroll far enough to see these methods... and even then it is not known whether he'll immediately relate "Format" to "I can get a string from e.g. Integers".

Note: As I've wrote, I personally prefer Format, so I'm not necesserily defending the use of type helpers...

Regards,
Sven

Reply by email

Sven Barth
to Paul Ishenin: 06.02.13, 19:29, Michael Schnell пишет: This is what you can already do in FPC 2.6.0…
Paul Ishenin wrote 13 lines
06.02.13, 19:29, Michael Schnell пишет: > but I feel > > point.x := x; > point.y := y; > s := point.ToString; > > is most clear. This is what you can already do in FPC 2.6.0 with advanced records feature active.

Or by using record helpers if one can not modify the used record type (e.g. because it's part of the RTL or FCL).

Regards,
Sven

Reply by email

Mark Morgan Lloyd
to Ludo Brands: Funny to see that all these fans of a strongly typed pascal prefer Format() that is using…
Ludo Brands wrote 5 lines
Funny to see that all these fans of a strongly typed pascal prefer Format() that is using variants, has an undetermined number of parameters, doesn't give the compiler any opportunity to check the types used and causes runtime errors when a wrong type or a wrong number of parameters is passed ;)

Format has two parameters. OK, so the second one is a bit weird... :-)

Perhaps somebody would like to correct me, but I think that in the case of output messages Format() has the big advantage that the order of the placeholders in the string can be changed easily when messages are translated from one language to another.

Mark Morgan Lloyd markMLl .AT. telemetry.co .DOT. uk [Opinions above are the author's, not those of his employers or colleagues]

Reply by email

Alexander Klenin
to Michael Schnell: or s := (x,y).ToString; Has there not recently been a discussion on Tupels ?!?!?! :-)…
Michael Schnell wrote 9 lines
> point.x := x; > point.y := y; > s := point.ToString; > or s := (x,y).ToString; Has there not recently been a discussion on Tupels ?!?!?! :-)

At least according to my proposal, tuples will not be a type, so you'll have to force a type by constructor:

   s := TPoint(x,y).ToString;

or, as it is currently, by a special function:

   s := Point(x,y).ToString;
Alexander S. Klenin

Reply by email

Paul Ishenin
to Alexander Klenin

06.02.13, 21:51, Alexander Klenin пишет:

Show quoted text 16 lines
On Wed, Feb 6, 2013 at 10:31 PM, Michael Schnell wrote: >> point.x := x; >> point.y := y; >> s := point.ToString; >> > or > s := (x,y).ToString; > > Has there not recently been a discussion on Tupels ?!?!?! :-) > At least according to my proposal, tuples will not be a type, so you'll have to force a type by constructor: s := TPoint(x,y).ToString; or, as it is currently, by a special function: s := Point(x,y).ToString;
or with a record constructor:
   TPoint.Create(X, Y).ToString;

Best regards,
Paul Ishenin

Reply by email

Thaddy
to Henry Vermaak: Thanks for pointing out the advantages. I can see the point, but can't help to think…
Henry Vermaak wrote 7 lines
What I'm trying to say with this (admittedly contrived) example is that when you are forced to read the docs to find out which functions you can use for converting numbers to strings, you'll probably discover functions like Format. At least in my case, the most useful tricks I learn come from reading the documentation for something, then exploring a bit. I apologise if I come across as overly cynical and I do appreciate Sven's work in the compiler! Henry

First of all, a huge tnx to Sven.
And Henri: do you also oppose macro support? With that you can make Freepascal code look like anything.
And RT(X)M has never harmed anyone.. cynism intended ;) .

Reply by email

Gerhard Scholz
to Sven Barth: Hello Free Pascal community! I'm pleased to announce the addition of type helpers which…

Hello,

I tried to compile the example:

type
   TLongIntHelper = type helper for LongInt
     class procedure Test; static;
   end;
class procedure TLongIntHelper.Test;
begin
   Writeln('Test');
end;
var
   i: LongInt;
begin
   i.Test;
   $12345678.Test;
   LongInt.Test;
end.

Result:

0:25:46,51
G:\ob\syncdirs>ppc386 -vv -al -CioOrt -Cs6000000 -gclt -Mobjfpc -O1 -OpPENTIUM -Fuu:\ -FuM:\u -FuC:\c\-u -FiC:\c\-u -Fuz:\-u -Fiz:\-u -FuP:\gs\tp55\includes -Fuf:\-u -Fiu:\ -FiM:\u -FiP:\gs\tp55\includes -Fif:\-u -FE. thelper
thelper.pas(2,33) Error: Identifier not found "helper" thelper.pas(2,33) Error: Error in type definition
thelper.pas(2,33) Error: Can't create unique type from this type thelper.pas(2,33) Fatal: Syntax error, ";" expected but "FOR" found Fatal: Compilation aborted

The compiler is freshly generated from the SVN

Does the compiler expect special options to invoke the record helper feature?

Gerhard

Earlier message 189 lines
----- Original Message ----- From: "Sven Barth" To: Cc: ; "FPC developers' list" Sent: Wednesday, February 06, 2013 10:49 AM Subject: [fpc-announce] Feature announcement: Type helpers > Hello Free Pascal community! > > I'm pleased to announce the addition of type helpers which extend the > existing helper concept with the ability to extend primitive types. > > Motivation: > > With class and record helpers the possibility was created to extend > classes and records with types without subclassing the type (which > wouldn't be possible with records anyway). This allows to add e.g. methods > to types in units that you can't influence or where you can't influence > with type is instantiated (e.g. the TStrings descendant used in TMemo). > Now it is logical to extend this also to other types supported by Pascal, > but here more driven by the possibility to group methods together and have > them appear to belong to the primitive type. > > While this does not bring the concepts of boxing of managed > languages/environments like Java and .NET to Pascal it does nevertheless > look this way. > > Syntax: > > The declaration of type helpers looks as follows: > > TYPENAME = type helper[(BASEHELPER)] for EXTENDEDTYPE > DECLARATIONS > end; > > Like class and record helpers they support all visibility sections and you > can define methods, properties and constructors. Inside methods declared > in the helper "Self" will be of the extended type's type and it's value > can also be changed. > Similar to record helpers class methods MUST be declared as static. > > Usage: > > A type helper is active if it is in scope. This means it must either have > been declared in the same unit before the code which wants to use the > helper or it needs to be declared in a used unit. As with class and type > helpers only one helper for a given type can be active and thus you need > to keep in mind the scoping rules when using helpers (e.g. the current > unit is searched in the order implementation section then interface > section (if the code is in the implementation section) and then the used > units are searched from right to left and each unit from top to bottom). > > In some cases the meaning of a type depends on the compiler settings the > helper is compiled with. E.g. the type Integer is either a ShortInt or a > LongInt depending on the current mode (fpc/tp vs. objfpc/delphi) and the > type String is different depending on the switches {$H+/-} and > {$modeswitch unicodestring}. This needs to be kept in mind when working > with these "generic" types. Another special case is the type Extended on > platforms that don't support that type (and thus it will be defined as > Double). > Additionally a type declared as "NewType = type OldType" is considered a > completly independant type as it is the case with e.g. operator overloads > as well. > > If a helper for the type is in scope you can simply invoke it's methods or > properties like you'd do on classes or records. Let's suppose we have a > helper with method "ToString: String" for the type LongInt in scope then > it will look like this: > > === example begin === > > var > i: LongInt; > begin > Writeln(i.ToString); > end. > > === example end === > > Additionally to invoking type helpers on variables they can also be used > on constants though special care needs to be taken that the correct type > is used. E.g. the constant "200" will be handled as a "Byte" whereas "20" > will be handled as "SmallInt". Also the type of string constants depends > on the current mode switch (especially {$H+/-} and {$modeswitch > unicodestring}) and also the content of the string. E.g. in case of > "{$mode objfpc}{$H+}" a string containing unicode characters will be > handled as a UnicodeString constant and thus only helpers for > UnicodeString will apply. > > For the following example let's assume the helper from the previous > example is in scope again: > > === example begin === > > begin > Writeln($12345678.ToString); > end. > > === example end === > > Additionally addresses (e.g. "@i") (type: Pointer) and the built in > constants "True" (type: Boolean), "False" (type: Boolean) and "Nil" (type: > Pointer) are allowed as well. Please note that in the case of typed > addresses also the untyped pointer type will be used, because a > corresponding typename might not be available to the current unit (and > thus the helper could not be found). Constants that can't be used with > type helpers are set and array constructors. > > Class methods (and properties) can be either used on variables or > constants, but also on the type name itself: > > === example begin === > > type > TLongIntHelper = type helper for LongInt > class procedure Test; static; > end; > > class procedure TLongIntHelper.Test; > begin > Writeln('Test'); > end; > > var > i: LongInt; > begin > i.Test; > $12345678.Test; > LongInt.Test; > end. > > === example end === > > Supported types: > > There is a restrictions on the type which can be extended. Basically every > primitive type is allowed besides the following: > > * file types (TextFile, file of ...) > * procedural variables > > Of course types like records, classes, Objective C classes, C++ classes, > objects and interfaces are forbidden as well. > > Viewed from the other perspective this means that the following types are > allowed: > > * ordinal types > * string types (including char types) > * set and enum types > * array types > * boolean types > * Variant > * floating point types > * pointer types > > Delphi compatibility: > > This feature was introduced by Delphi XE3, but instead of using the more > logical "type helper" syntax they added support for primitive types to the > "record helper" one. Thus to keep Delphi compatibility this is also the > syntax used in mode Delphi. Also in non Delphi modes inheritance for > helper types is supported. > > Future developments: > > Add support for more types, especially interface and object types. They > will either be added as class helpers or as "object helper" and "interface > helper" (as objects and interfaces support inheritance the scoping rules > inside the helper will resemble class helpers more than record/type > helpers). > > Allow that multiple helpers are active for one type at a single time. This > is one of the main restrictions of the current helper implementation. For > this corresponding lookup rules need to be defined and the feature will be > added as a modeswitch (maybe by default enabled in mode objfpc). > > Add support for helpers to the JVM target. The most likely implementation > approach is to pass the "Self" value as an additional parameter and treat > the methods otherwise as static ones (like is done in .NET for helper > methods). > > Regards, > Sven > _______________________________________________ > fpc-announce maillist - > http://lists.freepascal.org/mailman/listinfo/fpc-announce

Reply by email

Paul Ishenin
to Gerhard Scholz

08.02.2013 7:30, Gerhard Scholz пишет:

Show quoted text 15 lines
0:25:46,51 G:\ob\syncdirs>ppc386 -vv -al -CioOrt -Cs6000000 -gclt -Mobjfpc -O1 -OpPENTIUM -Fuu:\ -FuM:\u -FuC:\c\-u -FiC:\c\-u -Fuz:\-u -Fiz:\-u -FuP:\gs\tp55\includes -Fuf:\-u -Fiu:\ -FiM:\u -FiP:\gs\tp55\includes -Fif:\-u -FE. thelper thelper.pas(2,33) Error: Identifier not found "helper" thelper.pas(2,33) Error: Error in type definition thelper.pas(2,33) Error: Can't create unique type from this type thelper.pas(2,33) Fatal: Syntax error, ";" expected but "FOR" found Fatal: Compilation aborted The compiler is freshly generated from the SVN Does the compiler expect special options to invoke the record helper feature?

Nothing. On objFPC mode which you use they are enabled by default. It is something with your compiler. Mine compiles your code.

Best regards,
Paul Ishenin

Reply by email

Sven Barth
to Gerhard Scholz: I tried to compile the example: type TLongIntHelper = type helper for LongInt class…
"Gerhard Scholz" wrote 27 lines
Hello, I tried to compile the example: type TLongIntHelper = type helper for LongInt class procedure Test; static; end; class procedure TLongIntHelper.Test; begin Writeln('Test'); end; var i: LongInt; begin i.Test; $12345678.Test; LongInt.Test; end. Result: 0:25:46,51 G:\ob\syncdirs>ppc386 -vv -al -CioOrt -Cs6000000 -gclt

-Mobjfpc -O1 -OpPENTIUM -Fuu:\ -FuM:\u -FuC:\c\-u -FiC:\c\-u -Fuz:\-u -Fiz:\-u -FuP:\gs\tp55\includes -Fuf:\-u -Fiu:\ -FiM:\u -FiP:\gs\tp55\includes -Fif:\-u -FE. thelper

Show quoted text 9 lines
thelper.pas(2,33) Error: Identifier not found "helper" thelper.pas(2,33) Error: Error in type definition thelper.pas(2,33) Error: Can't create unique type from this type thelper.pas(2,33) Fatal: Syntax error, ";" expected but "FOR" found Fatal: Compilation aborted The compiler is freshly generated from the SVN Does the compiler expect special options to invoke the record helper

feature?

Did you add "{$mode objfpc}" to your program?

Regards
Sven

Reply by email

Paul Ishenin
to Sven Barth

08.02.2013 14:03, Sven Barth пишет:

Show quoted text 16 lines
> 0:25:46,51 G:\ob\syncdirs>ppc386 -vv -al -CioOrt -Cs6000000 -gclt -Mobjfpc -O1 -OpPENTIUM -Fuu:\ -FuM:\u -FuC:\c\-u -FiC:\c\-u -Fuz:\-u -Fiz:\-u -FuP:\gs\tp55\includes -Fuf:\-u -Fiu:\ -FiM:\u -FiP:\gs\tp55\includes -Fif:\-u -FE. thelper > thelper.pas(2,33) Error: Identifier not found "helper" > thelper.pas(2,33) Error: Error in type definition > thelper.pas(2,33) Error: Can't create unique type from this type > thelper.pas(2,33) Fatal: Syntax error, ";" expected but "FOR" found > Fatal: Compilation aborted > > The compiler is freshly generated from the SVN > > Does the compiler expect special options to invoke the record helper feature? Did you add "{$mode objfpc}" to your program?

Look at the compile string argument: -Mobjfpc

Best regards,
Paul Ishenin

Reply by email

Sven Barth
to Paul Ishenin
"Paul Ishenin" wrote 22 lines
08.02.2013 14:03, Sven Barth пишет: > > 0:25:46,51 G:\ob\syncdirs>ppc386 -vv -al -CioOrt -Cs6000000 -gclt > -Mobjfpc -O1 -OpPENTIUM -Fuu:\ -FuM:\u -FuC:\c\-u -FiC:\c\-u -Fuz:\-u > -Fiz:\-u -FuP:\gs\tp55\includes -Fuf:\-u -Fiu:\ -FiM:\u > -FiP:\gs\tp55\includes -Fif:\-u -FE. thelper > > thelper.pas(2,33) Error: Identifier not found "helper" > > thelper.pas(2,33) Error: Error in type definition > > thelper.pas(2,33) Error: Can't create unique type from this type > > thelper.pas(2,33) Fatal: Syntax error, ";" expected but "FOR" found > > Fatal: Compilation aborted > > > > The compiler is freshly generated from the SVN > > > > Does the compiler expect special options to invoke the record helper > feature? > > Did you add "{$mode objfpc}" to your program? Look at the compile string argument: -Mobjfpc

It's too early in the morning to look at command lines :)

@Gerhard: could you please check that the compiler is indeed from a current SVN checkout?

Regards,
Sven

Reply by email

Carsten Bager
to Sven Barth: -Mobjfpc -O1 -OpPENTIUM -Fuu:\ -FuM:\u -FuC:\c\-u -FiC:\c\-u -Fuz:\-u -Fiz:\-u…

I have made some small modifications to the serial unit for Win32 created by Luis R. Hilario. It now, can be used in Delphi (5, 7), FPC for Win32 and FPC for WinCE. I am using it with all compilers.
I think it could be useful for some people who are moving between Windows/WinCE and Linux.
It is not in the FPC project today, where can I (if possible) put it, so it maybe could be included in the FPC in the future.

Carsten

Reply by email

Mark Morgan Lloyd
to Carsten Bager: I have made some small modifications to the serial unit for Win32 created by Luis R.…
Carsten Bager wrote 7 lines
I have made some small modifications to the serial unit for Win32 created by Luis R. Hilario. It now, can be used in Delphi (5, 7), FPC for Win32 and FPC for WinCE. I am using it with all compilers. I think it could be useful for some people who are moving between Windows/WinCE and Linux. It is not in the FPC project today, where can I (if possible) put it, so it maybe could be included in the FPC in the future.

I did quite a lot of work on serial.pp for unix a year or so ago, and added/changed a number of functions since they'd been implemented in a way that didn't work. At the same time I contributed a Windows implementation, although I've not tested that as heavily as the unix one which I use regularly.

I'd suggest comparing your code with what's in
http://bugs.freepascal.org/view.php?id=18946 so that if it's ever accepted all of the functions are consistent.

Mark Morgan Lloyd markMLl .AT. telemetry.co .DOT. uk [Opinions above are the author's, not those of his employers or colleagues]

Reply by email

Gerhard Scholz
to Sven Barth: It's too early in the morning to look at command lines :) @Gerhard: could you please…

@Sven:

the problem is gone...

I made a new SVN run, and made a totally fresh compiler out of it. Now the program compiles.

Maybe I didn't understand the syntax correctly: I didn't see how to get the value inside the method?

example:

type
   TLongIntHelper = type helper for LongInt
     class procedure ShowValue; static;
   end;
class procedure TLongIntHelper.Test;
begin
   Writeln('Value=',self);
end;
var i : longint ;
begin
i:= 3 ;
.showvalue ;
end.
Earlier message 39 lines
----- Original Message ----- From: Sven Barth To: FPC developers' list Sent: Friday, February 08, 2013 7:49 AM Subject: Re: [fpc-devel] Re: [fpc-announce] Feature announcement: Type helpers Am 08.02.2013 07:22 schrieb "Paul Ishenin" : > > 08.02.2013 14:03, Sven Barth пишет: > >> > 0:25:46,51 G:\ob\syncdirs>ppc386 -vv -al -CioOrt -Cs6000000 -gclt >> -Mobjfpc -O1 -OpPENTIUM -Fuu:\ -FuM:\u -FuC:\c\-u -FiC:\c\-u -Fuz:\-u >> -Fiz:\-u -FuP:\gs\tp55\includes -Fuf:\-u -Fiu:\ -FiM:\u >> -FiP:\gs\tp55\includes -Fif:\-u -FE. thelper >> > thelper.pas(2,33) Error: Identifier not found "helper" >> > thelper.pas(2,33) Error: Error in type definition >> > thelper.pas(2,33) Error: Can't create unique type from this type >> > thelper.pas(2,33) Fatal: Syntax error, ";" expected but "FOR" found >> > Fatal: Compilation aborted >> > >> > The compiler is freshly generated from the SVN >> > >> > Does the compiler expect special options to invoke the record helper >> feature? >> >> Did you add "{$mode objfpc}" to your program? > > > Look at the compile string argument: -Mobjfpc It's too early in the morning to look at command lines :) @Gerhard: could you please check that the compiler is indeed from a current SVN checkout? Regards, Sven

Reply by email

Paul Ishenin
to Gerhard Scholz
Gerhard Scholz wrote
Maybe I didn't understand the syntax correctly: I didn't see how to get the value inside the method?

By accessing Self

Show quoted text 11 lines
example: type TLongIntHelper = type helper for LongInt class procedure ShowValue; static; end; class procedure TLongIntHelper.Test; begin Writeln('Value=',self); end;

Replace your static class procedure with regular method:

procecure TLongIntHelper.Test;
begin
   WriteLn(Self);
end;

Class static method is only needed if you are going to call it for the type declaration itself like: LongInt.PrintSize:

class procedure TLongIntHelper.PrintSize;
begin
   WriteLn(SizeOf(LongInt));
end;

static methods don't have a magic Self variable.

In any case I suggest to look for test which had been commited together with Sven patch.

Best regards,
Paul Ishenin

Reply by email

Sven Barth
to Paul Ishenin
Paul Ishenin wrote
In any case I suggest to look for test which had been commited together with Sven patch.

Just in case: they are located in $fpcdir/tests/test and are named tthlpX.pp (where X is a number)

Regards,
Sven

Reply by email

Gerhard Scholz
to Paul Ishenin: By accessing Self Replace your static class procedure with regular method: procecure…

Thanks for the help, I understood it now; I also found the test progs.

As far I see, it could already be substituted by the following constructs:

program RHelper1v ;
  type
    poLongint = ^ oLongint ;
    oLongint = object
                 li : longint ;
                 procedure ShowValue ;
                 procedure put ( j : longint ) ;
                 Function inc : poLongint ;
                end ;
  procedure oLongInt.showvalue ;
    begin
      Writeln ( 'Value=', li ) ;
     end ;
  procedure oLongInt.put ( j : longint ) ;
    begin
      li := j ;
     end ;
  function oLongInt.inc : polongint ;
    begin
      system.inc ( li ) ;
      result := @self ;
     end ;
  function v ( i : longint ) : polongint ;
    begin
      result := addr(i) ;
     end ;
  var
    i : LongInt ;
begin
  i := 3 ;
  olongint(i).showvalue ;
  olongint(i).put ( 4711 ) ;
  olongint(i).showvalue ;
  olongint(i).inc ;
  olongint(i).showvalue ;
  olongint(v(12345678)^).put ( 4711 ) ;  // senseless, but possible
  olongint(v(12345678)^).inc ;                // senseless, but possible
  olongint(v(12345678)^).showvalue ;     // 4712?
end.

And it produces the same assembler code as the construct TYPE HELPER FOR LONGINT
(which is definitely better readable).

The same program with type helper:

program RHelper1f ;
  type
    pLongInt = ^ longint ;
    tLongIntHelper = type helper for LongInt
                       procedure ShowValue ;
                       procedure put ( j : longint ) ;
                       Function inc : pLongint ;
                      end ;
  procedure TLongIntHelper.showvalue ;
    begin
      Writeln ( 'Value=', self ) ;
     end ;
  procedure TLongIntHelper.put ( j : longint ) ;
    begin
      self := j ;
     end ;
  function tLongInthelper.inc : plongint ;
    begin
      system.inc ( self ) ;
      result := @self ;
     end ;
  var
    i : LongInt ;
begin
  i := 3 ;
  i.showvalue ;
  i.put ( 4711 ) ;
  i.showvalue ;
  i.inc ;
  i.showvalue ;
  12345678.put ( 4711 ) ;  // senseless, but possible
  12345678.inc ;                 // senseless, but possible
  12345678.showvalue ;     // 4712?
end.

The last 3 lines show that the type helpers allow useless code. I assume such useless code is not catchable by the compiler.

Gerhard

Earlier message 52 lines
----- Original Message ----- From: "Paul Ishenin" To: "FPC developers' list" Sent: Friday, February 08, 2013 3:21 PM Subject: Re: [fpc-devel] Re: [fpc-announce] Feature announcement: Type helpers > 08.02.13, 21:52, Gerhard Scholz wrote: > >> Maybe I didn't understand the syntax correctly: I didn't see how to get >> the value inside the method? > > By accessing Self > >> example: >> >> type >> TLongIntHelper = type helper for LongInt >> class procedure ShowValue; static; >> end; >> >> class procedure TLongIntHelper.Test; >> begin >> Writeln('Value=',self); >> end; > > Replace your static class procedure with regular method: > > procecure TLongIntHelper.Test; > begin > WriteLn(Self); > end; > > Class static method is only needed if you are going to call it for the > type declaration itself like: LongInt.PrintSize: > > class procedure TLongIntHelper.PrintSize; > begin > WriteLn(SizeOf(LongInt)); > end; > > static methods don't have a magic Self variable. > > In any case I suggest to look for test which had been commited together > with Sven patch. > > Best regards, > Paul Ishenin > _______________________________________________ > fpc-devel maillist - > http://lists.freepascal.org/mailman/listinfo/fpc-devel

Reply by email

Sven Barth
to Gerhard Scholz
"Gerhard Scholz" wrote 58 lines
Thanks for the help, I understood it now; I also found the test progs. As far I see, it could already be substituted by the following constructs: program RHelper1v ; type poLongint = ^ oLongint ; oLongint = object li : longint ; procedure ShowValue ; procedure put ( j : longint ) ; Function inc : poLongint ; end ; procedure oLongInt.showvalue ; begin Writeln ( 'Value=', li ) ; end ; procedure oLongInt.put ( j : longint ) ; begin li := j ; end ; function oLongInt.inc : polongint ; begin system.inc ( li ) ; result := @self ; end ; function v ( i : longint ) : polongint ; begin result := addr(i) ; end ; var i : LongInt ; begin i := 3 ; olongint(i).showvalue ; olongint(i).put ( 4711 ) ; olongint(i).showvalue ; olongint(i).inc ; olongint(i).showvalue ; olongint(v(12345678)^).put ( 4711 ) ; // senseless, but possible olongint(v(12345678)^).inc ; // senseless, but possible olongint(v(12345678)^).showvalue ; // 4712? end. And it produces the same assembler code as the construct TYPE HELPER FOR

LONGINT

(which is definitely better readable).

Impressive O.o I would have never thought to use objects like that. The main advantage of helpers compared to your example is that the compiler will do the type checking.

Show quoted text 49 lines
The same program with type helper: program RHelper1f ; type pLongInt = ^ longint ; tLongIntHelper = type helper for LongInt procedure ShowValue ; procedure put ( j : longint ) ; Function inc : pLongint ; end ; procedure TLongIntHelper.showvalue ; begin Writeln ( 'Value=', self ) ; end ; procedure TLongIntHelper.put ( j : longint ) ; begin self := j ; end ; function tLongInthelper.inc : plongint ; begin system.inc ( self ) ; result := @self ; end ; var i : LongInt ; begin i := 3 ; i.showvalue ; i.put ( 4711 ) ; i.showvalue ; i.inc ; i.showvalue ; 12345678.put ( 4711 ) ; // senseless, but possible 12345678.inc ; // senseless, but possible 12345678.showvalue ; // 4712? end. The last 3 lines show that the type helpers allow useless code. I assume

such useless code is not catchable by the compiler.

If we could keep track of writes to Self and then mark the methods accordingly we could at least provide a warning or a hint.

And the last line should show 12345678 hopefully :)

Regards,
Sven

Reply by email

Gerhard Scholz
to Sven Barth

I know that the examples are stupid and most of them senseless.

Sometimes I used similar workarounds (more senseful), so I just wanted to know if the type helper construct produces more efficient code.
It doesn't.

The main advantage of helpers compared to your example is that the

compiler will do the type checking.

That's an advantage.

> 12345678.showvalue ; // 4712? And the last line should show 12345678 hopefully :)

Yes. it does.

Greetings

Gerhard

Earlier message 130 lines
----- Original Message ----- From: Sven Barth To: FPC developers' list Sent: Friday, February 08, 2013 8:24 PM Subject: Re: [fpc-devel] Re: [fpc-announce] Feature announcement: Type helpers Am 08.02.2013 19:52 schrieb "Gerhard Scholz" : > > Thanks for the help, I understood it now; I also found the test progs. > > As far I see, it could already be substituted by the following constructs: > > program RHelper1v ; > > type > poLongint = ^ oLongint ; > oLongint = object > li : longint ; > procedure ShowValue ; > procedure put ( j : longint ) ; > Function inc : poLongint ; > end ; > > procedure oLongInt.showvalue ; > > begin > Writeln ( 'Value=', li ) ; > end ; > > procedure oLongInt.put ( j : longint ) ; > > begin > li := j ; > end ; > > function oLongInt.inc : polongint ; > > begin > system.inc ( li ) ; > result := @self ; > end ; > > function v ( i : longint ) : polongint ; > > begin > result := addr(i) ; > > end ; > > var > i : LongInt ; > > begin > i := 3 ; > olongint(i).showvalue ; > olongint(i).put ( 4711 ) ; > olongint(i).showvalue ; > olongint(i).inc ; > olongint(i).showvalue ; > olongint(v(12345678)^).put ( 4711 ) ; // senseless, but possible > olongint(v(12345678)^).inc ; // senseless, but possible > olongint(v(12345678)^).showvalue ; // 4712? > end. > > And it produces the same assembler code as the construct TYPE HELPER FOR LONGINT > (which is definitely better readable). Impressive O.o I would have never thought to use objects like that. The main advantage of helpers compared to your example is that the compiler will do the type checking. > The same program with type helper: > > program RHelper1f ; > > type > pLongInt = ^ longint ; > > tLongIntHelper = type helper for LongInt > procedure ShowValue ; > procedure put ( j : longint ) ; > Function inc : pLongint ; > end ; > > procedure TLongIntHelper.showvalue ; > > begin > Writeln ( 'Value=', self ) ; > end ; > > procedure TLongIntHelper.put ( j : longint ) ; > > begin > self := j ; > end ; > > function tLongInthelper.inc : plongint ; > > begin > system.inc ( self ) ; > result := @self ; > > end ; > > var > i : LongInt ; > > begin > i := 3 ; > i.showvalue ; > i.put ( 4711 ) ; > i.showvalue ; > i.inc ; > i.showvalue ; > 12345678.put ( 4711 ) ; // senseless, but possible > 12345678.inc ; // senseless, but possible > 12345678.showvalue ; // 4712? > end. > > The last 3 lines show that the type helpers allow useless code. I assume such useless code is not catchable by the compiler. If we could keep track of writes to Self and then mark the methods accordingly we could at least provide a warning or a hint. And the last line should show 12345678 hopefully :) Regards, Sven

Reply by email

Sven Barth
to Sven Barth: Hello Free Pascal community! I'm pleased to announce the addition of type helpers which…

Hello together!

A little follow up of the feature announcement: After an internal discussion regarding language clarity last October it was decided that type helpers should not be enabled by default. Thus a new modeswitch "typehelpers" was added in revision 26796 that switches on "type helper for PrimitiveType" (non-Delphi modes) and "record helper for PrimitiveType" (Delphi modes).

Consequentially the same should be done for class and record helpers, but since they already had one mayor release cycle that's not that easy anymore (technically it is easy of course ^^).

Regards,
Sven

Reply by email