Sign in Join

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

Mailing lists / fpc-pascal / 2022-02

bug or feature?

28 messages · 9 people · –

Reply by email Subscribe to this list Your subscription

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

Mattias Gaertner

Hi,

This can't be right, can it?

type
  TBird = class
    procedure Fly;
  end;
  TEagle = TBird; // alias
procedure TEagle.Fly;
begin
end;

Mattias

Reply by email

Michael Van Canneyt
to Mattias Gaertner
Mattias Gaertner wrote 13 lines
Hi, This can't be right, can it? type TBird = class procedure Fly; end; TEagle = TBird; // alias procedure TEagle.Fly; begin end;

Personally, I would not allow this.
But Delphi compiles and runs it...

Maybe something to check for {$mode objfpc} =-)

Michael.

Reply by email

Sven Barth
to Michael Van Canneyt

Michael Van Canneyt via fpc-pascal
schrieb am Sa., 12. Feb. 2022, 12:14:

Show quoted text 23 lines
On Sat, 12 Feb 2022, Mattias Gaertner via fpc-pascal wrote: > Hi, > > This can't be right, can it? > > type > TBird = class > procedure Fly; > end; > TEagle = TBird; // alias > > procedure TEagle.Fly; > begin > end; Personally, I would not allow this. But Delphi compiles and runs it... Maybe something to check for {$mode objfpc} =-)

The compiler does not have any real tracking for non-type aliases... As far as the compiler is concerned these are interchangeable...

Regards,
Sven

Reply by email

Michael Van Canneyt
to Sven Barth
Sven Barth wrote 29 lines
Michael Van Canneyt via fpc-pascal schrieb am Sa., 12. Feb. 2022, 12:14: > > > On Sat, 12 Feb 2022, Mattias Gaertner via fpc-pascal wrote: > >> Hi, >> >> This can't be right, can it? >> >> type >> TBird = class >> procedure Fly; >> end; >> TEagle = TBird; // alias >> >> procedure TEagle.Fly; >> begin >> end; > > Personally, I would not allow this. > But Delphi compiles and runs it... > > Maybe something to check for {$mode objfpc} =-) > The compiler does not have any real tracking for non-type aliases... As far as the compiler is concerned these are interchangeable...

I think Mattias just got some more gray hairs :-)

So if I understand this correctly, I can do

---
Interface
Type
   TSomeReallyAnnoyingIncrediblyLongClassName = Class
     Procedure DoSomething;
   end;
implementation
Type
   T1 = TSomeReallyAnnoyingUltraLongClassName;
procedure T1.DoSomething;
begin
end;
---

And consequently also

---
Interface
Type
   TSomeReallyAnnoyingIncrediblyLongClassName = Class
   Type
      TSomeReallyAnnoyingSubClass = class
         Procedure DoSomething;
      end;
   end;
implementation
Type
   T1 = TSomeReallyAnnoyingIncrediblyLongClassName.TSomeReallyAnnoyingSubClass;
procedure T1.DoSomething;
begin
end;
---

The lazarus code tools maintainer will have a field day with this one ;-)

Michael.

PS. Just tested, the compiler accepts both... Amazing, I never thought this would be possible. I'd better update the docs :-)

Reply by email

Jonas Maebe
to Michael Van Canneyt
Michael Van Canneyt wrote
PS. Just tested, the compiler accepts both... Amazing, I never thought this would be possible. I'd better update the docs :-)

I wouldn't consider this to be working by design, but rather because of implementation limitations.

Jonas

Reply by email

Michael Van Canneyt
to Jonas Maebe
Jonas Maebe wrote 6 lines
On 12/02/2022 17:36, Michael Van Canneyt via fpc-pascal wrote: > PS. Just tested, the compiler accepts both... Amazing, I never thought this > would be possible. I'd better update the docs :-) I wouldn't consider this to be working by design, but rather because of implementation limitations.

Why do you consider it a limitation ?

Because the compiler currently has no way to distinguish the types when resolving the name "T" (as used in my example)?

Then it is a strange coincidence that Delphi has it too :-)

Michael.

Reply by email

Jonas Maebe
to Michael Van Canneyt
Michael Van Canneyt wrote 15 lines
On Sat, 12 Feb 2022, Jonas Maebe via fpc-pascal wrote: > On 12/02/2022 17:36, Michael Van Canneyt via fpc-pascal wrote: >> PS. Just tested, the compiler accepts both... Amazing, I never >> thought this >> would be possible. I'd better update the docs :-) > > I wouldn't consider this to be working by design, but rather because > of implementation limitations. Why do you consider it a limitation ? Because the compiler currently has no way to distinguish the types when resolving the name "T" (as used in my example)?

Indeed.

Then it is a strange coincidence that Delphi has it too :-)

The simplest way to implement alias types is to just have them refer to the original type...

Jonas

Reply by email

Mattias Gaertner
to Jonas Maebe
[...] >> I wouldn't consider this to be working by design, but rather >> because of implementation limitations.

+1
pas2js complained. That's how I found out. Someone renamed a class, added an alias for compatibility, forgot to rename the implementation, and fpc did not complain.

Show quoted text 12 lines
> Why do you consider it a limitation ? > > Because the compiler currently has no way to distinguish the types > when resolving the > name "T" (as used in my example)? Indeed. > Then it is a strange coincidence that Delphi has it too :-) The simplest way to implement alias types is to just have them refer to the original type...

Actually pas2js did an even simpler approach here: Look up the identifier without resolving the original type ;)

Mattias

Reply by email

Michael Van Canneyt
to Ryan Joseph
Ryan Joseph wrote 7 lines
> On Feb 12, 2022, at 11:40 PM, Jonas Maebe via fpc-pascal wrote: > > I wouldn't consider this to be working by design, but rather because of implementation limitations. I agree and it should be fixed probably.

As I wrote in my initial answer to Mattias, I would also forbid it. (despite the temptation to use it for shortening class names in the implementation, I think it will be more confusing than helpful in the end)

But since Delphi allows it, we must continue to allow it in Delphi mode...

Michael.

Reply by email

Mattias Gaertner
to Michael Van Canneyt: Personally, I would not allow this. But Delphi compiles and runs it... Maybe something to…

On Sat, 12 Feb 2022 12:14:14 +0100 (CET)
Michael Van Canneyt via fpc-pascal

Show quoted text 18 lines
On Sat, 12 Feb 2022, Mattias Gaertner via fpc-pascal wrote: > Hi, > > This can't be right, can it? > > type > TBird = class > procedure Fly; > end; > TEagle = TBird; // alias > > procedure TEagle.Fly; > begin > end; Personally, I would not allow this. But Delphi compiles and runs it...

... and Delphi's class completion no longer works in the unit giving a useless error "expected ';' but '.' found". So it is one of those Delphi "features" compiling but not usable.

Mattias

Reply by email

Michael Van Canneyt
to Mattias Gaertner
Mattias Gaertner wrote 26 lines
On Sat, 12 Feb 2022 12:14:14 +0100 (CET) Michael Van Canneyt via fpc-pascal wrote: > On Sat, 12 Feb 2022, Mattias Gaertner via fpc-pascal wrote: > > > Hi, > > > > This can't be right, can it? > > > > type > > TBird = class > > procedure Fly; > > end; > > TEagle = TBird; // alias > > > > procedure TEagle.Fly; > > begin > > end; > > Personally, I would not allow this. > But Delphi compiles and runs it... ... and Delphi's class completion no longer works in the unit giving a useless error "expected ';' but '.' found". So it is one of those Delphi "features" compiling but not usable.

I'm all for forbidding this in objfpc mode.

Michael.

Reply by email

Sven Barth
to Michael Van Canneyt

Michael Van Canneyt via fpc-pascal
schrieb am So., 13. Feb. 2022, 09:47:

Show quoted text 33 lines
On Sun, 13 Feb 2022, Mattias Gaertner via fpc-pascal wrote: > On Sat, 12 Feb 2022 12:14:14 +0100 (CET) > Michael Van Canneyt via fpc-pascal > wrote: > >> On Sat, 12 Feb 2022, Mattias Gaertner via fpc-pascal wrote: >> >> > Hi, >> > >> > This can't be right, can it? >> > >> > type >> > TBird = class >> > procedure Fly; >> > end; >> > TEagle = TBird; // alias >> > >> > procedure TEagle.Fly; >> > begin >> > end; >> >> Personally, I would not allow this. >> But Delphi compiles and runs it... > > ... and Delphi's class completion no longer works in the unit giving a > useless error "expected ';' but '.' found". So it is one of those > Delphi "features" compiling but not usable. I'm all for forbidding this in objfpc mode.

Then file a bug report for it. Cause it's definitely going to be one of the low priority things cause it's going to be annoying to fix...

Regards,
Sven

Reply by email

Florian Klämpfl
to Sven Barth
Sven Barth wrote 39 lines
Michael Van Canneyt via fpc-pascal < > schrieb am So., 13. Feb. 2022, 09:47: On Sun, 13 Feb 2022, Mattias Gaertner via fpc-pascal wrote: > On Sat, 12 Feb 2022 12:14:14 +0100 (CET) > Michael Van Canneyt via fpc-pascal < > > wrote: > >> On Sat, 12 Feb 2022, Mattias Gaertner via fpc-pascal wrote: >> >> > Hi, >> > >> > This can't be right, can it? >> > >> > type >> >  TBird = class >> >    procedure Fly; >> >  end; >> >  TEagle = TBird; // alias >> > >> > procedure TEagle.Fly; >> > begin >> > end; >> >> Personally, I would not allow this. >> But Delphi compiles and runs it... > > ... and Delphi's class completion no longer works in the unit giving a > useless error "expected ';' but '.' found". So it is one of those > Delphi "features" compiling but not usable. I'm all for forbidding this in objfpc mode. Then file a bug report for it. Cause it's definitely going to be one of the low priority things cause it's going to be annoying to fix...

I thought (famous last words), checking the typesyms of the tobjectdef would be enough but who knows what else will bit :)

Reply by email

Michael Van Canneyt
to Sven Barth: Michael Van Canneyt via fpc-pascal schrieb am So., 13. Feb. 2022, 09:47: Then file a bug…
Sven Barth wrote 12 lines
>>> Personally, I would not allow this. >>> But Delphi compiles and runs it... >> >> ... and Delphi's class completion no longer works in the unit giving a >> useless error "expected ';' but '.' found". So it is one of those >> Delphi "features" compiling but not usable. > > I'm all for forbidding this in objfpc mode. > Then file a bug report for it. Cause it's definitely going to be one of the low priority things cause it's going to be annoying to fix...

Done:

https://gitlab.com/freepascal.org/fpc/source/-/issues/39576

Maybe someone can check whether Florian's solution really is 'famous last words' ;-)

Michael.

Reply by email

Elmar Haneke
to Mattias Gaertner: This can't be right, can it? type TBird = class procedure Fly; end; TEagle = TBird; //…
Show quoted text 11 lines
This can't be right, can it? type TBird = class procedure Fly; end; TEagle = TBird; // alias procedure TEagle.Fly; begin end;

It does depend on what you expect an Type-Alias to be.

If you expect the compiler to generate an compatible class then your example must not be compilable.

If you expect an alias die make the Typenames "TEagle" and "TBird" equivalent it is no problem for the compiler which name you use at what place.

In any case I would judge such code as "bad style" - programmers should avoid doing so.

Elmar

Reply by email

Unknown author
to Florian Klämpfl: I thought (famous last words), checking the typesyms of the tobjectdef would be enough…

@Michael Van Canneyt
I didn't test but I hope this package can parse this _minified_ CSS file? Attached on the forum

https://forum.lazarus.freepascal.org/index.php/topic,58853.msg438550.html#msg438550

It has many tricks. E.g. @media blocks (@media supports nested blocks, not only 1 level), e.g. {} block for N classes, e.g. weird class names.

Alexey

Reply by email

Michael Van Canneyt
to Unknown author
Alexey Torgashin wrote
@Michael Van Canneyt I didn't test but I hope this package can parse this _minified_ CSS file?

Minified or not is normally not relevant for parsing.

Show quoted text 6 lines
Attached on the forum https://forum.lazarus.freepascal.org/index.php/topic,58853.msg438550.html#msg438550 It has many tricks. E.g. @media blocks (@media supports nested blocks, not only 1 level), e.g. {} block for N classes, e.g. weird class names.

Nested blocks are supported.

But weird class names:

extractcssclasses brackets.min.css -o out

Exception at 00000000004C107B: ECSSParser:
Error: line 9, pos 18: Unexpected token: Got ctkIDENTIFIER (as UTF8String: "zoom"), expected: ctkCOLON .

"*zoom", really ? That's not even valid CSS syntax.

I checked 2 EBNF grammars: neither will allow this. I checked the W3 spec: Confirms this is simply not valid syntax.

Browsers are simply very forgiving for all the junk found in CSS files: The CSS syntax is so sloppy, almost impossible to cover all cases. That's why there are a lot of test files.

But patches to make the implementation more forgiving are welcome. I suppose things like *zoom can be easily supported.

Do you have the unminified file ? So I can see how to interpret the '*zoom': treat as '* zoom' or as identifier '*zoom'

Michael.

Reply by email

Alexey Torgashin
to Michael Van Canneyt
"*zoom", really ? That's not even valid CSS syntax. I checked 2 EBNF grammars: neither will allow this. I checked the W3 spec: Confirms this is simply not valid syntax.

But "*.nnn" is valid one.
https://css-tricks.com/almanac/selectors/u/universal/

So if the "*" has meaning in one context, it is not the id-char, it is special construct.

Do you have the unminified file ?

nope.

> treat as '* zoom' or as identifier '*zoom'

as "* zoom".

Alexey

Reply by email

Michael Van Canneyt
to Alexey Torgashin
Alexey Torgashin wrote 10 lines
> "*zoom", really ? That's not even valid CSS syntax. > > I checked 2 EBNF grammars: neither will allow this. I checked the W3 > spec: Confirms this is simply not valid syntax. But "*.nnn" is valid one. https://css-tricks.com/almanac/selectors/u/universal/ So if the "*" has meaning in one context, it is not the id-char, it is special construct.

The problem is that spaces are meaningful.
so * zoom and *zoom are not the same.

Show quoted text 9 lines
> Do you have the unminified file ? nope. >> treat as '* zoom' or as identifier '*zoom' as "* zoom".

Thanks, I wil check...

Michael.

Reply by email

Michael Van Canneyt
to Michael Van Canneyt
Michael Van Canneyt wrote 11 lines
On Sun, 27 Mar 2022, Alexey Torgashin via fpc-pascal wrote: >> "*zoom", really ? That's not even valid CSS syntax. >> >> I checked 2 EBNF grammars: neither will allow this. I checked the W3 >> spec: Confirms this is simply not valid syntax. > > But "*.nnn" is valid one. > https://css-tricks.com/almanac/selectors/u/universal/

I did some more checking. As a selector * can be used in some cases: the universal selector. but it can not be used as a property name.

in your file:

.clearfix{*zoom:1}

*zoom is a property name, not a selector. and properties must be identifiers. According to the spec, identifiers do not start with a *.

I will add some options to interpret "*zoom" as a property name, but they will off by default.

Michael.

Reply by email

Alexey Torgashin
to Michael Van Canneyt
I will add some options to interpret "*zoom" as a property name, but they will off by default.

OK thanks.
Can you try now with CSS (usual or minified) from
https://getbootstrap.com/ ?
See 'download' which gives file bootstrap-5.1.3-dist.zip .

Complex places:
====

.link-dark:hover, .link-dark:focus {
   color: #1a1e21;
}
//Here they have :suffixes.
-----------
   --bs-purple: #6f42c1;
   --bs-pink: #d63384;
//Here they have color varialbles.
-----------

.visually-hidden-focusable:not(:focus):not(:focus-within) {

a:not([href]):not([class]), a:not([href]):not([class]):hover {

button:not(:disabled),
[type=button]:not(:disabled),
[type=reset]:not(:disabled),
[type=submit]:not(:disabled) {

   cursor: pointer;

}

//Here they have weird boolean things.
-----------

*,
*::before,
*::after {

   box-sizing: border-box;

}
//Here they have star-chars.
-----------

   --bs-gradient: linear-gradient(180deg, rgba(255, 255, 255, 0.15),
rgba(255, 255, 255, 0));
//They have complex func calls.
-----------

::-webkit-datetime-edit-year-field {

   padding: 0;

}
//More suffixes
-----------

From bootstrap-4.0.0-dist.zip I got also--
-----------

abbr[title]::after {

     content: " (" attr(title) ")";
   }

//strange value with 2 strings
-----------

.text-hide {

   font: 0/0 a;
   }

//strange value
-----------

Alexey

Reply by email

Michael Van Canneyt
to Alexey Torgashin
Alexey Torgashin wrote 8 lines
> I will add some options to interpret "*zoom" as a property name, but they > will > off by default. OK thanks. Can you try now with CSS (usual or minified) from https://getbootstrap.com/ ? See 'download' which gives file bootstrap-5.1.3-dist.zip .

Good idea, I will check this file.
I use bootstrap a lot, although I prefer Bulma these days.

From your samples, most if not all things should work.

By the way, it is easy to test. Just compile the extractcssclasses demo and run

extractcssclasses yourfile

But if you prefer a GUI program, the actual code is really simple:

uses fpcssutils;
Var
   L : TStringList;
   Util : TCSSUtils;
begin
   Util:=Nil;
   L:=TStringList.Create;
   try
     Util:=TCSSUtils.Create(Self);
     Util.ExtractClassNames(aFileName,L);
     // Do something with L
   finally
     Util.Free;
     L.Free;
   end;
end;

Michael.

Show quoted text 67 lines
Complex places: ==== .link-dark:hover, .link-dark:focus { color: #1a1e21; } //Here they have :suffixes. ----------- --bs-purple: #6f42c1; --bs-pink: #d63384; //Here they have color varialbles. ----------- .visually-hidden-focusable:not(:focus):not(:focus-within) { a:not([href]):not([class]), a:not([href]):not([class]):hover { button:not(:disabled), [type=button]:not(:disabled), [type=reset]:not(:disabled), [type=submit]:not(:disabled) { cursor: pointer; } //Here they have weird boolean things. ----------- *, *::before, *::after { box-sizing: border-box; } //Here they have star-chars. ----------- --bs-gradient: linear-gradient(180deg, rgba(255, 255, 255, 0.15), rgba(255, 255, 255, 0)); //They have complex func calls. ----------- ::-webkit-datetime-edit-year-field { padding: 0; } //More suffixes ----------- From bootstrap-4.0.0-dist.zip I got also-- ----------- abbr[title]::after { content: " (" attr(title) ")"; } //strange value with 2 strings ----------- .text-hide { font: 0/0 a; } //strange value ----------- Alexey _______________________________________________ fpc-pascal maillist - https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal

Reply by email

Alexey Torgashin
to Michael Van Canneyt

Currently if I run "extractcssclasses" with Bootstrap 4 (or 5) CSS file (not minified) I get it work for more than 30 seconds, then I stopped it, too long.
Output file (parameter "--output=4.txt") not created.

CPU Core i3. Linux x64.
AT

Reply by email

Michael Van Canneyt
to Michael Van Canneyt: Good idea, I will check this file. I use bootstrap a lot, although I prefer Bulma these…
Michael Van Canneyt wrote 14 lines
On Mon, 28 Mar 2022, Alexey Torgashin via fpc-pascal wrote: >> I will add some options to interpret "*zoom" as a property name, but they >> will >> off by default. > > OK thanks. > Can you try now with CSS (usual or minified) from > https://getbootstrap.com/ ? > See 'download' which gives file bootstrap-5.1.3-dist.zip . Good idea, I will check this file. I use bootstrap a lot, although I prefer Bulma these days.

I had to do 2 small fixes, but the bootstrap file now parses 100%

Michael.

Reply by email

Alexey Torgashin
to Mattias Gaertner: On Sat, 12 Feb 2022 12:14:14 +0100 (CET) Michael Van Canneyt via fpc-pascal ... and…

(I posted to the forum, but it's better to post here.) TStringList.Text setter does this

<pre>
     Procedure TStrings.DoSetTextStr(const Value: string; DoClear :
Boolean);
...
         if FLineBreak=sLineBreak then
           begin
           While GetNextLine (Value,S,P) do
             Add(S)
           end
         else
           While GetNextLineBreak (Value,S,P) do
             Add(S);
       finally
         EndUpdate;
       end;
     end;
</pre>

here it calls GetNextLine which does SPECIAL handling of #10 and #13 and #13#10 line breaks. If it does special handling of #10 and #13 and #13#10 line breaks, why don't we check

if (FLineBreak=#10) or (FLineBreak=#13) or (FLineBreak=#13#10)

but we do simple

if FLineBreak=sLineBreak

Alexey

Reply by email

Michael Van Canneyt
to Alexey Torgashin
Alexey Torgashin wrote 25 lines
(I posted to the forum, but it's better to post here.) TStringList.Text setter does this <pre> Procedure TStrings.DoSetTextStr(const Value: string; DoClear : Boolean); ... if FLineBreak=sLineBreak then begin While GetNextLine (Value,S,P) do Add(S) end else While GetNextLineBreak (Value,S,P) do Add(S); finally EndUpdate; end; end; </pre> here it calls GetNextLine which does SPECIAL handling of #10 and #13 and #13#10 line breaks. If it does special handling of #10 and #13 and #13#10 line breaks, why don't we check if (FLineBreak=#10) or (FLineBreak=#13) or (FLineBreak=#13#10)

This would change the behaviour.

Now the special treatment is only done when FLinebreak exactly matches sLineBreak.

Michael.

Reply by email