Sign in Join

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

Mailing lists / fpc-pascal / 2019-02

Constants in generics tests

15 messages · 4 people · –

Reply by email Subscribe to this list Your subscription

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

Ryan Joseph

Here’s the latest changes which fixed the constant type checking and includes some tests. Are the tests in the correct format? They are named tgenconst*.pp.

https://github.com/genericptr/freepascal/tree/generic_constants

For example:

{%FAIL}
{$mode objfpc}
program tgenconst8;
type
	generic TByte<const U: Byte> = record end;
var
	a: specialize TByte<300>;
begin
end.

This will now give an error because 300 is a SmallInt. That’s everything I can think of for now. Please let me know if this is ready to submit yet.

Regards,
Ryan Joseph

Reply by email

Jeppe Johansen
to Ryan Joseph

Hi,

Do you know why this doesn't work?

type
   TGPIO = class
   public
     class function ReadValue: NativeUInt; virtual; abstract;
     class procedure SetValue(AValue: NativeUInt); virtual; abstract;
     class function GetPin(const AIndex: NativeInt): boolean; virtual;
   end;
   generic TStm32GPIO<const Base: integer> = class(TGPIO)
   public
     class function ReadValue: NativeUInt; override;
     class procedure SetValue(AValue: NativeUInt); override;
   end;
class function TGPIO.GetPin(const AIndex: NativeInt): boolean;
begin
   result:=Odd(ReadValue shr AIndex);
end;
class function TStm32GPIO.ReadValue: NativeUInt;
begin
   result:=PNativeUInt(Base)^;
end;
class procedure TStm32GPIO.SetValue(AValue: NativeUInt);
begin
   PNativeUInt(Base)^:=AValue;
end;
type GPIOA = specialize TStm32GPIO<$12400000>;

Best Regards,
Jeppe

Ryan Joseph wrote 25 lines
Here’s the latest changes which fixed the constant type checking and includes some tests. Are the tests in the correct format? They are named tgenconst*.pp. https://github.com/genericptr/freepascal/tree/generic_constants For example: {%FAIL} {$mode objfpc} program tgenconst8; type generic TByte<const U: Byte> = record end; var a: specialize TByte<300>; begin end. This will now give an error because 300 is a SmallInt. That’s everything I can think of for now. Please let me know if this is ready to submit yet. Regards, Ryan Joseph _______________________________________________ fpc-pascal maillist - http://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-pascal

Reply by email

Ryan Joseph
to Jeppe Johansen

Good catch, I have no idea what broke or how that could have happened.

I got it distilled down to this:

type
  generic TTest<const U> = class
    class procedure DoThis;	// <—— Forward declaration not solved "class DoThis;"
  end;
class procedure TTest.DoThis;
begin
end;
type
	ATest = specialize TTest<100>;

Something with class functions in particular. Very strange it can’t find the declaration. So never mind about submitting, I need to fix this now. :)

Also I just noticed that I’m getting warnings from the “U” constant which is declared in the “strict private” section (Private const "TTest$1.U" never used). That needs to be fixed also. Sven or some other compiler guy, do you know how to silence that warning?

Show quoted text 5 lines
On Feb 15, 2019, at 1:52 PM, Jeppe Johansen wrote: Hi, Do you know why this doesn't work?

Regards,
Ryan Joseph

Reply by email

Ryan Joseph
to Ryan Joseph
On Feb 15, 2019, at 2:11 PM, Ryan Joseph wrote: Also I just noticed that I’m getting warnings from the “U” constant which is declared in the “strict private” section (Private const "TTest$1.U" never used). That needs to be fixed also. Sven or some other compiler guy, do you know how to silence that warning?

Upon further testing this warning is in all generics. Was this warning intentional? Should it stand for constants also?

Regards,
Ryan Joseph

Reply by email

Sven Barth
to Ryan Joseph

Am Fr., 15. Feb. 2019, 20:58 hat Ryan Joseph
geschrieben:

Show quoted text 13 lines
> On Feb 15, 2019, at 2:11 PM, Ryan Joseph wrote: > > Also I just noticed that I’m getting warnings from the “U” constant which is declared in the “strict private” section (Private const "TTest$1.U" never used). That needs to be fixed also. Sven or some other compiler guy, do you know how to silence that warning? Upon further testing this warning is in all generics. Was this warning intentional? Should it stand for constants also?

Yes and yes :)
The type parameters must not be visible in subclasses except the generic deems it so by using a type (or now constant) alias. This is Delphi compatible.

Regards,
Sven

Reply by email

Ryan Joseph
to Ryan Joseph: Good catch, I have no idea what broke or how that could have happened. I got it distilled…
On Feb 15, 2019, at 2:11 PM, Ryan Joseph wrote: Something with class functions in particular. Very strange it can’t find the declaration. So never mind about submitting, I need to fix this now. :)

I just looked over this and indeed I have no idea idea what happened. I suspect there’s some code not being called because the param is a constsym but I have no idea where that may be. It feels like the specialized class name is not matching when constants are in the specialized type.

A question for the compiler team: is there anything you could say about how forward def are resolved with class functions that may be different from normal functions? I would understand if this happened for all functions but it’s strange it only happens with class functions. Anything you could say to point me in the right direction so I don’t have to spend hours in the debugger. :)

Regards,
Ryan Joseph

Reply by email

Sven Barth
to Ryan Joseph

Am Fr., 15. Feb. 2019, 21:54 hat Ryan Joseph
geschrieben:

Show quoted text 20 lines
> On Feb 15, 2019, at 2:11 PM, Ryan Joseph wrote: > > Something with class functions in particular. Very strange it can’t find the declaration. So never mind about submitting, I need to fix this now. :) I just looked over this and indeed I have no idea idea what happened. I suspect there’s some code not being called because the param is a constsym but I have no idea where that may be. It feels like the specialized class name is not matching when constants are in the specialized type. A question for the compiler team: is there anything you could say about how forward def are resolved with class functions that may be different from normal functions? I would understand if this happened for all functions but it’s strange it only happens with class functions. Anything you could say to point me in the right direction so I don’t have to spend hours in the debugger. :)

It could be that the method body is not generated. Look for generate_specialization_procs in pgenutil as that is what generates the bodies at the end of a unit (simplified).

Regards,
Sven

Reply by email

Ryan Joseph
to Sven Barth
On Feb 15, 2019, at 4:19 PM, Sven Barth via fpc-pascal wrote: It could be that the method body is not generated. Look for generate_specialization_procs in pgenutil as that is what generates the bodies at the end of a unit (simplified).

Really good catch Sven. tstoreddef.is_specialization is not returning true for generics with const params so the procedure body is not getting created. Not sure how to resolve it yet but at least I know where it is. Thanks.

Regards,
Ryan Joseph

Reply by email

Sven Barth
to Ryan Joseph
Ryan Joseph wrote 6 lines
> On Feb 15, 2019, at 4:19 PM, Sven Barth via fpc-pascal wrote: > > It could be that the method body is not generated. Look for generate_specialization_procs in pgenutil as that is what generates the bodies at the end of a unit (simplified). > Really good catch Sven. tstoreddef.is_specialization is not returning true for generics with const params so the procedure body is not getting created. Not sure how to resolve it yet but at least I know where it is. Thanks.

Disclaimer: I have not yet looked at your most recent changes, nor do I fully remember what you had changed previously.
Maybe tstoreddef.genericparas does not contain the constant symbols? (they should be added in pgenutil.insert_generic_parameter_types) While you're at it, you should probably also ensure that internal error 2014050904 does not trigger ;)

Regards,
Sven

Reply by email

Ryan Joseph
to Sven Barth
On Feb 16, 2019, at 3:33 AM, Sven Barth via fpc-pascal wrote: While you're at it, you should probably also ensure that internal error 2014050904 does not trigger ;)

That’s what got my in the first place. I saw the internal error and made it not trigger but didn’t bother to check if the rest of the method was operational (hint, it’s not!). sym.owner.defownerself is not true for constants so I need to figure out why.

Btw, how does FPC generate internal errors numbers? I needed to add some errors myself and I didn’t know how to increment the counter.

Regards,
Ryan Joseph

Reply by email

Jonas Maebe
to Ryan Joseph
Ryan Joseph wrote
Btw, how does FPC generate internal errors numbers? I needed to add some errors myself and I didn’t know how to increment the counter.

YearMonthDay00, YearMonthDay01, ...

Jonas

Reply by email

Sven Barth
to Ryan Joseph: That’s what got my in the first place. I saw the internal error and made it not trigger…

Am Sa., 16. Feb. 2019, 15:34 hat Ryan Joseph
geschrieben:

Show quoted text 13 lines
> On Feb 16, 2019, at 3:33 AM, Sven Barth via fpc-pascal < > wrote: > > While you're at it, you should probably also ensure that internal error 2014050904 does not trigger ;) That’s what got my in the first place. I saw the internal error and made it not trigger but didn’t bother to check if the rest of the method was operational (hint, it’s not!). sym.owner.defownerself is not true for constants so I need to figure out why.

When you create the constant symbols for the specialization you need to make sure that they belong to the surrounding symtable, not the specialized generic.

Regards,
Sven

Reply by email

Ryan Joseph
to Sven Barth
On Feb 16, 2019, at 9:42 AM, Sven Barth via fpc-pascal wrote: When you create the constant symbols for the specialization you need to make sure that they belong to the surrounding symtable, not the specialized generic.

I probably didn’t get that right then. The constants are significantly different because they are generated during specialization unlike normal types which are already defined and have ownerships.

Btw I just saw this (in types_dec from pdecl.pas) and not sure it applies to constants. The symbol in question here was created in parse_generic_parameters and tconstsym doesn’t have a typedef method so I don’t know what casting to ttypesym did. Maybe tconstsym.constdef needs to be registered but I have no idea.

 { we are not freeing the type parameters, so register them }
               for i:=0 to generictypelist.count-1 do
                 begin
                    ttypesym(generictypelist[i]).register_sym;
                    tstoreddef(ttypesym(generictypelist[i]).typedef).register_def;
                 end;

Regards,
Ryan Joseph

Reply by email

Ryan Joseph
to Jeppe Johansen: Do you know why this doesn't work? type   TGPIO = class   public     class function…
Show quoted text 5 lines
On Feb 15, 2019, at 1:52 PM, Jeppe Johansen wrote: Hi, Do you know why this doesn't work?

Jeppe I got this fixed now so if you update and rebuild from git it should work now. Really stupid one liner mistake that took my all morning to find.

I included this into the tests which all run now but I’m not sure if I did them correctly. Anyone please let me know if those are correct/complete.

Regards,
Ryan Joseph

Reply by email