Re: [fpc-devel] Implicit function specialization precedence

2021-05-16 Thread Sven Barth via fpc-devel

Am 15.05.2021 um 20:08 schrieb Ryan Joseph via fpc-devel:



On May 15, 2021, at 10:49 AM, Ryan Joseph  wrote:

Also it looks like ChangeOwnerAndName isn't making the compiler happy.

Sorry for the noise, I figured out it was because the name had spaces. How 
should I make the name then? I'm doing this for now which is certainly unique 
but it's not standard.

   
newtype:=ctypesym.create(def.fullownerhierarchyname(false)+typName[def.typ]+'$'+def.unique_id_str,def);

It will make names like below which don't upset the assembler.

SOMETESTUNIT.arraydef$5

Anyways, I put up a patch on the bug tracker 
(https://bugs.freepascal.org/view.php?id=35261) for you to review and see if I 
did this right.
I had already wondered why that worked previously. But yes, that 
approach is better.


Regards,
Sven
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] Implicit function specialization precedence

2021-05-16 Thread Sven Barth via fpc-devel

Am 15.05.2021 um 18:27 schrieb Ryan Joseph via fpc-devel:



On May 13, 2021, at 2:38 PM, Sven Barth  wrote:

Ah, you need to use ChangeOwnerAndName then and simply pass in the same name 
you used for the constructor (cause otherwise it tries to use the name that is 
currently stored in the list).

Looking at this again today and I have yet another question to confirm. I 
create one of the types using ctypesym.create but the others were just 
references from the system unit. We only want to change owner of the symbol I 
create, right? Not the system unit ones? If not changing owner maybe we need to 
add some ref count or something? just confirming to make sure.
You only need to change the owner of those you create using 
ctypesym.create. The others are preexisting and you must not touch them 
in any way.


Regards,
Sven
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] Implicit function specialization precedence

2021-05-15 Thread Ryan Joseph via fpc-devel


> On May 15, 2021, at 10:49 AM, Ryan Joseph  wrote:
> 
> Also it looks like ChangeOwnerAndName isn't making the compiler happy.

Sorry for the noise, I figured out it was because the name had spaces. How 
should I make the name then? I'm doing this for now which is certainly unique 
but it's not standard.

  
newtype:=ctypesym.create(def.fullownerhierarchyname(false)+typName[def.typ]+'$'+def.unique_id_str,def);

It will make names like below which don't upset the assembler.

SOMETESTUNIT.arraydef$5

Anyways, I put up a patch on the bug tracker 
(https://bugs.freepascal.org/view.php?id=35261) for you to review and see if I 
did this right.

Regards,
Ryan Joseph

___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] Implicit function specialization precedence

2021-05-15 Thread Ryan Joseph via fpc-devel


> On May 15, 2021, at 10:27 AM, Ryan Joseph  wrote:
> 
> Looking at this again today and I have yet another question to confirm. I 
> create one of the types using ctypesym.create but the others were just 
> references from the system unit. We only want to change owner of the symbol I 
> create, right? Not the system unit ones? If not changing owner maybe we need 
> to add some ref count or something? just confirming to make sure.

Also it looks like ChangeOwnerAndName isn't making the compiler happy.

The dynamic array creates an unnamed typesym like this. (def is the array def 
for [1,2,3])

  newtype:=ctypesym.create(def.typename,def);
  newtype.owner:=def.owner;

And specialized like this:

generic procedure DoThis(p1: T);
begin
end;

begin
  DoThis([1,2,3]);
end;

Then during assembling I get these errors.

Assembling (pipe) 
/Users/ryanjoseph/Developer/Projects/FPC/macro_test/output/timpfuncspez0.s
:40:50: error: unexpected token in directive
.globl  _P$TIMPFUNCSPEZ19_$$_DOTHIS$1$CRCC2373297${Array Of Const/Constant 
Open} Array of ShortInt
  ^
:41:60: error: unexpected token in directive
.private_extern _P$TIMPFUNCSPEZ19_$$_DOTHIS$1$CRCC2373297${Array Of 
Const/Constant Open} Array of ShortInt
  ^
:42:44: error: unknown token in expression
_P$TIMPFUNCSPEZ19_$$_DOTHIS$1$CRCC2373297${Array Of Const/Constant Open} Array 
of ShortInt:
   ^
:117:50: error: invalid register name
call_P$TIMPFUNCSPEZ19_$$_DOTHIS$1$CRCC2373297${Array Of 
Const/Constant Open} Array of ShortInt
   ^
:117:50: error: Expected an op-mask register at this point
call_P$TIMPFUNCSPEZ19_$$_DOTHIS$1$CRCC2373297${Array Of 
Const/Constant Open} Array of ShortInt
   ^
:283:50: error: unexpected token in '.quad' directive
.quad   _P$TIMPFUNCSPEZ19_$$_DOTHIS$1$CRCC2373297${Array Of 
Const/Constant Open} Array of ShortInt
  ^
error: There were 1 errors compiling module, stopping
error: Compilation aborted


Regards,
Ryan Joseph

___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] Implicit function specialization precedence

2021-05-15 Thread Ryan Joseph via fpc-devel


> On May 13, 2021, at 2:38 PM, Sven Barth  wrote:
> 
> Ah, you need to use ChangeOwnerAndName then and simply pass in the same name 
> you used for the constructor (cause otherwise it tries to use the name that 
> is currently stored in the list).

Looking at this again today and I have yet another question to confirm. I 
create one of the types using ctypesym.create but the others were just 
references from the system unit. We only want to change owner of the symbol I 
create, right? Not the system unit ones? If not changing owner maybe we need to 
add some ref count or something? just confirming to make sure.

function create_unamed_typesym(def:tdef): tsym;
var
  newtype: tsym;
begin
  newtype:=nil;
  if is_conststring_array(def) then
begin
  { for constant strings we need to respect various modeswitches }
  if (cs_refcountedstrings in current_settings.localswitches) then
begin
  if m_default_unicodestring in current_settings.modeswitches 
then
newtype:=cunicodestringtype.typesym
  else
newtype:=cansistringtype.typesym;
end
  else
newtype:=cshortstringtype.typesym;
end
  else if def.typ=stringdef then
newtype:=tstringdef(def).get_default_string_type.typesym
  else
begin
  newtype:=ctypesym.create(def.typename,def);
  newtype.owner:=def.owner;
end;
  if newtype=nil then
internalerror(2021020904);
  result:=newtype;
end;

Regards,
Ryan Joseph

___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] Implicit function specialization precedence

2021-05-13 Thread Sven Barth via fpc-devel

Am 12.05.2021 um 17:50 schrieb Ryan Joseph via fpc-devel:



On May 9, 2021, at 1:30 AM, Sven Barth  wrote:

Essentially it will boil down to sym.ChangeOwner(pd.parast)

However you need to keep the Owner (which is different from what you change 
with ChangeOwner) different as otherwise is_specialization of the procdef will 
not work correctly.


I'm saving the storing symbols in tcallcandiates so they can be available when 
maybe_add_pending_specialization is called once the call node chooses the 
specialization, and then I ran into this problem. The symbol I make in 
create_unamed_typesym has FOwner nil so calling TFPHashObject.ChangeOwner 
crashes. Did I not make the symbol correctly or do I need to do something 
before calling ChangeOwner?
Ah, you need to use ChangeOwnerAndName then and simply pass in the same 
name you used for the constructor (cause otherwise it tries to use the 
name that is currently stored in the list).


Regards,
Sven
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] Implicit function specialization precedence

2021-05-12 Thread Ryan Joseph via fpc-devel


> On May 9, 2021, at 1:30 AM, Sven Barth  wrote:
> 
> Essentially it will boil down to sym.ChangeOwner(pd.parast)
> 
> However you need to keep the Owner (which is different from what you change 
> with ChangeOwner) different as otherwise is_specialization of the procdef 
> will not work correctly. 
> 

I'm saving the storing symbols in tcallcandiates so they can be available when 
maybe_add_pending_specialization is called once the call node chooses the 
specialization, and then I ran into this problem. The symbol I make in 
create_unamed_typesym has FOwner nil so calling TFPHashObject.ChangeOwner 
crashes. Did I not make the symbol correctly or do I need to do something 
before calling ChangeOwner?

Regards,
Ryan Joseph

___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] Implicit function specialization precedence

2021-05-09 Thread Sven Barth via fpc-devel
Ryan Joseph via fpc-devel  schrieb am Sa.,
8. Mai 2021, 22:33:

>
>
> > On May 8, 2021, at 12:04 PM, Sven Barth 
> wrote:
> >
> > You need to use ChangeOwner as well, but as I wrote you need to pay
> attention for which created symbol you do it at what time.
>
> Ok, maybe this is what I got wrong didn't use ChangeOwner. When you say
> "add to" what exactly do you mean? Please post a single line code snippet
> even. Thanks.
>

Essentially it will boil down to sym.ChangeOwner(pd.parast)

However you need to keep the Owner (which is different from what you change
with ChangeOwner) different as otherwise is_specialization of the procdef
will not work correctly.

Regards,
Sven

>
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] Implicit function specialization precedence

2021-05-08 Thread Ryan Joseph via fpc-devel


> On May 8, 2021, at 12:04 PM, Sven Barth  wrote:
> 
> You need to use ChangeOwner as well, but as I wrote you need to pay attention 
> for which created symbol you do it at what time.

Ok, maybe this is what I got wrong didn't use ChangeOwner. When you say "add 
to" what exactly do you mean? Please post a single line code snippet even. 
Thanks.

Regards,
Ryan Joseph

___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] Implicit function specialization precedence

2021-05-08 Thread Sven Barth via fpc-devel

Am 22.04.2021 um 17:52 schrieb Ryan Joseph via fpc-devel:



On Apr 16, 2021, at 11:35 AM, Ryan Joseph  wrote:

Got this all integrated and put up the changes to 
https://bugs.freepascal.org/view.php?id=35261. Now I'm waiting for another 
final review. :)

The next thing to do now is to handle a memory leak. From the bug tracker:


You essentially need to make sure the symbols become part of the specialization 
that is picked in the end (cause you create the symbols in make_param_list only 
once, but you might use them for multiple generic overloads of which at most 
one will be picked).
What you might be able to do is the following (have not looked at it in detail 
yet):
- those symbols you directly add to genericparams you ensure that their owner 
is the specialization right away (after generate_specialization_phase1)
- those symbols you add to callerparams you'll probably have to bubble up to 
htypechk and have that somehow add these syms to the final specialization if it 
is picked and free them otherwise


My response:


I looked at this again and it looks like there is just one place where we can 
leak memory now and that's those lines from create_unamed_typesym.

   newtype:=ctypesym.create(def.typename,def);
   newtype.owner:=def.owner;

I set the owner of the new typesym to the target def but what does that even 
do? I think you're saying I need to set the owner of that symbol to be a 
procdef but I don't see how the helps the memory get freed. I would think when 
the specialization is freed we could check some flag in the generic params and 
if they are not owned then we free them then.

And with that I'm stuck. :) I don't know how the symbols in the compiler are memory 
managed but I don't see setting their owner is helping them get freed. I've tried setting 
their owner to the procdef.owner being specialized but that does't do anything either. I 
guess I don't understand what adding them to "the final specialization" means 
so please clarify.

My naive assumption would be to add them to a list in tspecializationcontext 
and free them when the content is freed because I don't think the symbols are 
used after the implicit specialization is finished and a proc def is produced, 
but I may be wrong about that.


You need to use ChangeOwner as well, but as I wrote you need to pay 
attention for which created symbol you do it at what time.


The ones you create in is_possible_specialization you need to add to the 
specialization you do in the following generate_implicit_specialization 
as those are only created for that specific specialization (though you 
also need to free it if you leave is_possible_specialization with False 
which you currently don't do).


The ones you create in make_param_list you need to pass back to htypechk 
so that they can either be added to the final specialization (if 
selected out of multiple ones) or to be freed if none of the ones 
created by that invocation to try_implicit_specialization is picked. 
That is because they would be shared by all the specializations.


Regards,
Sven
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] Implicit function specialization precedence

2021-05-08 Thread Sven Barth via fpc-devel

Am 06.05.2021 um 17:33 schrieb Ryan Joseph via fpc-devel:

I found something sneaky I'd like to confirm before I decide what to do about 
it.

1) "T" in TAnyClass is specialized as Integer from the first parameter with 
TSomeClass (which is TAnyClass).
2) "U" is getting specialized as String by looking at the parameters in Compare() in 
which "U"(the second generic parameter) is String.

This specializes the procedure correctly but it uses a very sneaky method which is very hard to 
discern. I feel like that if a generic parameter is already used (like T in specialize 
TCallback) then no further attempt should be made to look at the parameters and in 
the example below "U" would not be found and the function would fail to implicitly 
specialize.
There is nothing sneaky if one defines that the parameters are evaluated 
left to right and those that are already found and used later on (like 
T) are simply fixed then thus in the example it uses the already found 
type. But if the picked type wouldn't mach, for example if TCallback<,> 
would be declared as TCallback instead then trying to 
specialize the function would simply fail.


Regards,
Sven
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] Implicit function specialization precedence

2021-05-06 Thread Ryan Joseph via fpc-devel
I found something sneaky I'd like to confirm before I decide what to do about 
it.

1) "T" in TAnyClass is specialized as Integer from the first parameter with 
TSomeClass (which is TAnyClass).
2) "U" is getting specialized as String by looking at the parameters in 
Compare() in which "U"(the second generic parameter) is String.

This specializes the procedure correctly but it uses a very sneaky method which 
is very hard to discern. I feel like that if a generic parameter is already 
used (like T in specialize TCallback) then no further attempt should be 
made to look at the parameters and in the example below "U" would not be found 
and the function would fail to implicitly specialize.

==

type
  generic TAnyClass = class
type TElem = U;
  end;

type
  TSomeClass = specialize TAnyClass;

type
  generic TCallback = function(a: T; b: U): integer;

function Compare(a: TSomeClass.TElem; b: string): integer;
begin
  result := 1;
end;

generic procedure DoThis(aClass: specialize TAnyClass; callback: 
specialize TCallback);
begin
  callback(1, 'string');
end;

begin
  DoThis(TSomeClass.Create, @Compare);
end.

Regards,
Ryan Joseph

___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] Implicit function specialization precedence

2021-04-29 Thread Ryan Joseph via fpc-devel


> On Apr 22, 2021, at 9:52 AM, Ryan Joseph  wrote:
> 
>> Got this all integrated and put up the changes to 
>> https://bugs.freepascal.org/view.php?id=35261. Now I'm waiting for another 
>> final review. :)
> 
> The next thing to do now is to handle a memory leak. From the bug tracker:

I just noticed a week has passed on this.  Sven, do you have a reply to my 
previous message to clarify a little? I could make a guess at what you want but 
I'll probably just waste more time doing the wrong thing. :P

Regards,
Ryan Joseph

___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] Implicit function specialization precedence

2021-04-22 Thread Ryan Joseph via fpc-devel


> On Apr 16, 2021, at 11:35 AM, Ryan Joseph  wrote:
> 
> Got this all integrated and put up the changes to 
> https://bugs.freepascal.org/view.php?id=35261. Now I'm waiting for another 
> final review. :)

The next thing to do now is to handle a memory leak. From the bug tracker:

> You essentially need to make sure the symbols become part of the 
> specialization that is picked in the end (cause you create the symbols in 
> make_param_list only once, but you might use them for multiple generic 
> overloads of which at most one will be picked).
> What you might be able to do is the following (have not looked at it in 
> detail yet):
> - those symbols you directly add to genericparams you ensure that their owner 
> is the specialization right away (after generate_specialization_phase1)
> - those symbols you add to callerparams you'll probably have to bubble up to 
> htypechk and have that somehow add these syms to the final specialization if 
> it is picked and free them otherwise


My response:

> I looked at this again and it looks like there is just one place where we can 
> leak memory now and that's those lines from create_unamed_typesym.
> 
>   newtype:=ctypesym.create(def.typename,def);
>   newtype.owner:=def.owner;
> 
> I set the owner of the new typesym to the target def but what does that even 
> do? I think you're saying I need to set the owner of that symbol to be a 
> procdef but I don't see how the helps the memory get freed. I would think 
> when the specialization is freed we could check some flag in the generic 
> params and if they are not owned then we free them then.

And with that I'm stuck. :) I don't know how the symbols in the compiler are 
memory managed but I don't see setting their owner is helping them get freed. 
I've tried setting their owner to the procdef.owner being specialized but that 
does't do anything either. I guess I don't understand what adding them to "the 
final specialization" means so please clarify.

My naive assumption would be to add them to a list in tspecializationcontext 
and free them when the content is freed because I don't think the symbols are 
used after the implicit specialization is finished and a proc def is produced, 
but I may be wrong about that.


Regards,
Ryan Joseph

___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] Implicit function specialization precedence

2021-04-16 Thread Ryan Joseph via fpc-devel


> On Apr 16, 2021, at 2:44 AM, Sven Barth via fpc-devel 
>  wrote:
> 
> Yes, do that for now. 
> 

Got this all integrated and put up the changes to 
https://bugs.freepascal.org/view.php?id=35261. Now I'm waiting for another 
final review. :)

Regards,
Ryan Joseph

___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] Implicit function specialization precedence

2021-04-16 Thread Sven Barth via fpc-devel
Ryan Joseph via fpc-devel  schrieb am Fr.,
16. Apr. 2021, 00:38:

>
>
> > On Apr 14, 2021, at 3:49 PM, Ryan Joseph  wrote:
> >
> > It works but it thinks this array is array of const also so it's too
> strict I believe.
> >
> > ['aaa', 'bbb'];
>
> About this, shouldn't we just be doing this? Any array constructor that
> has elements which are which are incompatible is "array of const"? from
> tarrayconstructornode.pass_typecheck:
>
>  if eq=te_incompatible then
>diff:=true;


Yes, do that for now.

Regards,
Sven

>
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] Implicit function specialization precedence

2021-04-15 Thread Ryan Joseph via fpc-devel


> On Apr 14, 2021, at 3:49 PM, Ryan Joseph  wrote:
> 
> It works but it thinks this array is array of const also so it's too strict I 
> believe.
> 
> ['aaa', 'bbb'];

About this, shouldn't we just be doing this? Any array constructor that has 
elements which are which are incompatible is "array of const"? from 
tarrayconstructornode.pass_typecheck:

 if eq=te_incompatible then
   diff:=true;

Regards,
Ryan Joseph

___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] Implicit function specialization precedence

2021-04-15 Thread Ryan Joseph via fpc-devel


> On Apr 14, 2021, at 11:39 PM, Sven Barth  wrote:
> 
> Well, then I'll have to improve the check. But for now you can continue, 
> right?

I can continue but if I include the check some tests will fail. Currently I've 
only made some changes in create_unamed_typesym and now this check to reject 
array of const. Everything else is done AKAIK unless we discover more bugs in 
the tests (which I've uploaded on the bug tracker).

Regards,
Ryan Joseph

___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] Implicit function specialization precedence

2021-04-14 Thread Sven Barth via fpc-devel

Am 14.04.2021 um 23:49 schrieb Ryan Joseph via fpc-devel:



On Apr 14, 2021, at 2:33 PM, Sven Barth  wrote:

Had a bit of time to look at this. You can try the attached patch. You can then 
check for both ado_IsConstructor and ado_IsArrayOfConst to detect such a mixed 
array.

It works but it thinks this array is array of const also so it's too strict I 
believe.

['aaa', 'bbb'];
Well, then I'll have to improve the check. But for now you can continue, 
right?


Regards,
Sven
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] Implicit function specialization precedence

2021-04-14 Thread Ryan Joseph via fpc-devel


> On Apr 14, 2021, at 2:33 PM, Sven Barth  wrote:
> 
> Had a bit of time to look at this. You can try the attached patch. You can 
> then check for both ado_IsConstructor and ado_IsArrayOfConst to detect such a 
> mixed array.

It works but it thinks this array is array of const also so it's too strict I 
believe.

['aaa', 'bbb'];


Regards,
Ryan Joseph

___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] Implicit function specialization precedence

2021-04-14 Thread Sven Barth via fpc-devel

Am 11.04.2021 um 23:38 schrieb Ryan Joseph via fpc-devel:



On Apr 11, 2021, at 3:33 PM, Sven Barth  wrote:

Looking at it, it could be that there is a bug in 
tarrayconstructornode.pass_typecheck that hasn't really surfaced yet... I'll 
have to look at that first, but I don't know when I'll have the time for that.

sure I'll just leave it as is for now then. By the time the overloading happens 
it must know the array constructor is array of const but it should ideally be 
known by the time tarrayconstructornode.pass_typecheck is executed.


Had a bit of time to look at this. You can try the attached patch. You 
can then check for both ado_IsConstructor and ado_IsArrayOfConst to 
detect such a mixed array.


Regards,
Sven
diff --git a/compiler/defutil.pas b/compiler/defutil.pas
index 852d2cfa5a..b9c50dfa87 100644
--- a/compiler/defutil.pas
+++ b/compiler/defutil.pas
@@ -821,7 +821,10 @@ implementation
 function is_array_of_const(p : tdef) : boolean;
   begin
  result:=(p.typ=arraydef) and
- (ado_IsArrayOfConst in tarraydef(p).arrayoptions);
+ (ado_IsArrayOfConst in tarraydef(p).arrayoptions) and
+ { consider it an array-of-const in the strict sense only if it
+   isn't an array constructor }
+ not (ado_IsConstructor in tarraydef(p).arrayoptions);
   end;
 
 function is_conststring_array(p: tdef): boolean;
diff --git a/compiler/nld.pas b/compiler/nld.pas
index 7be26db2bc..bdea9cfb0f 100644
--- a/compiler/nld.pas
+++ b/compiler/nld.pas
@@ -1113,6 +1113,7 @@ implementation
 hdef  : tdef;
 hp: tarrayconstructornode;
 len   : longint;
+diff,
 varia : boolean;
 eq: tequaltype;
 hnodetype : tnodetype;
@@ -1136,6 +1137,7 @@ implementation
 hnodetype:=errorn;
 len:=0;
 varia:=false;
+diff:=false;
 if assigned(left) then
  begin
hp:=self;
@@ -1164,6 +1166,8 @@ implementation
end
  else
eq:=compare_defs(hdef,hp.left.resultdef,hp.left.nodetype);
+ if eq___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] Implicit function specialization precedence

2021-04-11 Thread Ryan Joseph via fpc-devel


> On Apr 11, 2021, at 3:33 PM, Sven Barth  wrote:
> 
> Looking at it, it could be that there is a bug in 
> tarrayconstructornode.pass_typecheck that hasn't really surfaced yet... I'll 
> have to look at that first, but I don't know when I'll have the time for that.

sure I'll just leave it as is for now then. By the time the overloading happens 
it must know the array constructor is array of const but it should ideally be 
known by the time tarrayconstructornode.pass_typecheck is executed.

Regards,
Ryan Joseph

___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] Implicit function specialization precedence

2021-04-11 Thread Sven Barth via fpc-devel

Am 11.04.2021 um 22:27 schrieb Ryan Joseph via fpc-devel:



On Apr 10, 2021, at 9:47 AM, Ryan Joseph  wrote:

Just checked and pass_typecheck is called before overloading but ado_IsVariant is simply never set 
for that array. In tarraydef.GetTypeName you can see that "array of const" is associated 
with many flags so maybe we need to make a new flag which means "non-uniform elements"? I 
could probably easily build that into pass_typecheck for array constructors.

...
  if (ado_isarrayofconst in arrayoptions) or
 (ado_isConstructor in arrayoptions) then
   begin
 if (ado_isvariant in arrayoptions) or ((highrange=-1) and 
(lowrange=0)) then
   GetTypeName:='Array Of Const'
 else
   GetTypeName:='{Array Of Const/Constant Open} Array of 
'+elementdef.typename;
   end


Any word on what I should do about this? If those flags present are not 
sufficient I'll add another flag but if that's not acceptable I'll simply have 
to allow the user to specialize with these array types, even though they will 
fail later one when the function is selected during overloading. Once I know 
that I'll submit another patch including the other changes that were requested.
Looking at it, it could be that there is a bug in 
tarrayconstructornode.pass_typecheck that hasn't really surfaced yet... 
I'll have to look at that first, but I don't know when I'll have the 
time for that.


Regards,
Sven
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] Implicit function specialization precedence

2021-04-11 Thread Ryan Joseph via fpc-devel


> On Apr 10, 2021, at 9:47 AM, Ryan Joseph  wrote:
> 
> Just checked and pass_typecheck is called before overloading but 
> ado_IsVariant is simply never set for that array. In tarraydef.GetTypeName 
> you can see that "array of const" is associated with many flags so maybe we 
> need to make a new flag which means "non-uniform elements"? I could probably 
> easily build that into pass_typecheck for array constructors.
> 
> ...
>  if (ado_isarrayofconst in arrayoptions) or
> (ado_isConstructor in arrayoptions) then
>   begin
> if (ado_isvariant in arrayoptions) or ((highrange=-1) and 
> (lowrange=0)) then
>   GetTypeName:='Array Of Const'
> else
>   GetTypeName:='{Array Of Const/Constant Open} Array of 
> '+elementdef.typename;
>   end
> 

Any word on what I should do about this? If those flags present are not 
sufficient I'll add another flag but if that's not acceptable I'll simply have 
to allow the user to specialize with these array types, even though they will 
fail later one when the function is selected during overloading. Once I know 
that I'll submit another patch including the other changes that were requested.

Regards,
Ryan Joseph

___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] Implicit function specialization precedence

2021-04-10 Thread Ryan Joseph via fpc-devel


> On Apr 10, 2021, at 9:18 AM, Ryan Joseph  wrote:
> 
> I checked before and here's what I got. Maybe pass_typecheck hasn't been 
> called yet? If not I'll have to reproduce that code and determine how it 
> knows the elements are not uniform. Thanks.

Just checked and pass_typecheck is called before overloading but ado_IsVariant 
is simply never set for that array. In tarraydef.GetTypeName you can see that 
"array of const" is associated with many flags so maybe we need to make a new 
flag which means "non-uniform elements"? I could probably easily build that 
into pass_typecheck for array constructors.

...
  if (ado_isarrayofconst in arrayoptions) or
 (ado_isConstructor in arrayoptions) then
   begin
 if (ado_isvariant in arrayoptions) or ((highrange=-1) and 
(lowrange=0)) then
   GetTypeName:='Array Of Const'
 else
   GetTypeName:='{Array Of Const/Constant Open} Array of 
'+elementdef.typename;
   end


Regards,
Ryan Joseph

___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] Implicit function specialization precedence

2021-04-10 Thread Ryan Joseph via fpc-devel


> On Apr 10, 2021, at 6:54 AM, Sven Barth  wrote:
> 
> As an additional note: if you take a look at 
> tarrayconstructornode.pass_typecheck you can see that the array type always 
> has the ado_IsConstructor set and if it contains of incompatible types the 
> ado_IsVariant is set as well. So if ado_IsVariant is *not* set, then you can 
> rely on the elementdef of the arraydef.

I checked before and here's what I got. Maybe pass_typecheck hasn't been called 
yet? If not I'll have to reproduce that code and determine how it knows the 
elements are not uniform. Thanks.

elecount:4
typesym:{Array Of Const/Constant Open} Array of ShortInt
ado_IsConvertedPointer: FALSE
ado_IsDynamicArray: FALSE
ado_IsVariant: FALSE
ado_IsConstructor: TRUE
ado_IsArrayOfConst: FALSE
ado_IsConstString: FALSE
ado_IsBitPacked: FALSE
ado_IsVector: FALSE
ado_IsGeneric: FALSE

  writeln('elecount:',tarraydef(caller_def).elecount);
  writeln('typesym:',tarraydef(caller_def).typesym.realname);
  writeln('ado_IsConvertedPointer: ',ado_IsConvertedPointer in 
tarraydef(caller_def).arrayoptions);
  writeln('ado_IsDynamicArray: ',ado_IsDynamicArray in 
tarraydef(caller_def).arrayoptions);
  writeln('ado_IsVariant: ',ado_IsVariant in 
tarraydef(caller_def).arrayoptions);
  writeln('ado_IsConstructor: ',ado_IsConstructor in 
tarraydef(caller_def).arrayoptions);
  writeln('ado_IsArrayOfConst: ',ado_IsArrayOfConst in 
tarraydef(caller_def).arrayoptions);
  writeln('ado_IsConstString: ',ado_IsConstString in 
tarraydef(caller_def).arrayoptions);
  writeln('ado_IsBitPacked: ',ado_IsBitPacked in 
tarraydef(caller_def).arrayoptions);
  writeln('ado_IsVector: ',ado_IsVector in 
tarraydef(caller_def).arrayoptions);
  writeln('ado_IsGeneric: ',ado_IsGeneric in 
tarraydef(caller_def).arrayoptions);

Regards,
Ryan Joseph

___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] Implicit function specialization precedence

2021-04-10 Thread Sven Barth via fpc-devel

Am 10.04.2021 um 10:38 schrieb Sven Barth:

Am 10.04.2021 um 00:43 schrieb Ryan Joseph via fpc-devel:


On Apr 9, 2021, at 4:31 PM, Sven Barth via fpc-devel 
 wrote:


You mean what you did for is_array_literal? A pure array constructor 
can be found with is_array_constructor, though it might be better to 
use is_open_array, cause someone might pass an open array parameter 
to a generic function (those will be unnamed as well).
Maybe the email didn't go through? How to identify this "array of 
const constructor" type. I want to reject these for implicit 
specialization but I can't identity them.


  DoThis([
    1,
    'string',
    'c',
    TObject.Create
  ])


You can't really differentiate these from array constructors with just 
one type, because the type is only really determined once the overload 
is chosen as that kind of array could be an array of const, an array 
of Variant or maybe even an array of LongInt if there are suitable 
operator overloads in scope. So, yeah, it's kinda hard to decide what 
type to use...


*Now* your other mail arrived. ;)

As an additional note: if you take a look at 
tarrayconstructornode.pass_typecheck you can see that the array type 
always has the ado_IsConstructor set and if it contains of incompatible 
types the ado_IsVariant is set as well. So if ado_IsVariant is *not* 
set, then you can rely on the elementdef of the arraydef.


Regards,
Sven
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] Implicit function specialization precedence

2021-04-10 Thread Sven Barth via fpc-devel

Am 10.04.2021 um 00:43 schrieb Ryan Joseph via fpc-devel:



On Apr 9, 2021, at 4:31 PM, Sven Barth via fpc-devel 
 wrote:

You mean what you did for is_array_literal? A pure array constructor can be 
found with is_array_constructor, though it might be better to use 
is_open_array, cause someone might pass an open array parameter to a generic 
function (those will be unnamed as well).

Maybe the email didn't go through? How to identify this "array of const 
constructor" type. I want to reject these for implicit specialization but I can't 
identity them.

  DoThis([
1,
'string',
'c',
TObject.Create
  ])


You can't really differentiate these from array constructors with just 
one type, because the type is only really determined once the overload 
is chosen as that kind of array could be an array of const, an array of 
Variant or maybe even an array of LongInt if there are suitable operator 
overloads in scope. So, yeah, it's kinda hard to decide what type to use...


Regards,
Sven
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] Implicit function specialization precedence

2021-04-09 Thread Ryan Joseph via fpc-devel


> On Apr 9, 2021, at 4:31 PM, Sven Barth via fpc-devel 
>  wrote:
> 
> You mean what you did for is_array_literal? A pure array constructor can be 
> found with is_array_constructor, though it might be better to use 
> is_open_array, cause someone might pass an open array parameter to a generic 
> function (those will be unnamed as well).

Maybe the email didn't go through? How to identify this "array of const 
constructor" type. I want to reject these for implicit specialization but I 
can't identity them.

 DoThis([
   1,
   'string',
   'c',
   TObject.Create
 ])
Regards,
Ryan Joseph

___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] Implicit function specialization precedence

2021-04-09 Thread Sven Barth via fpc-devel

Am 09.04.2021 um 23:52 schrieb Ryan Joseph via fpc-devel:



On Apr 9, 2021, at 3:08 PM, Sven Barth  wrote:

Possibly, yes...

You could provide the various utility functions in a separate patch.

Well I'm going to use them for this patch so they would all be batched together.

Any idea about the "array of const" issue I raised in the other email? Once 
that's done I'll submit another very patch. Getting very close now unless I missed some 
test cases...
You mean what you did for is_array_literal? A pure array constructor can 
be found with is_array_constructor, though it might be better to use 
is_open_array, cause someone might pass an open array parameter to a 
generic function (those will be unnamed as well).


Regards,
Sven
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] Implicit function specialization precedence

2021-04-09 Thread Ryan Joseph via fpc-devel


> On Apr 9, 2021, at 3:08 PM, Sven Barth  wrote:
> 
> Possibly, yes...
> 
> You could provide the various utility functions in a separate patch.

Well I'm going to use them for this patch so they would all be batched together.

Any idea about the "array of const" issue I raised in the other email? Once 
that's done I'll submit another very patch. Getting very close now unless I 
missed some test cases...

Regards,
Ryan Joseph

___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] Implicit function specialization precedence

2021-04-09 Thread Sven Barth via fpc-devel

Am 09.04.2021 um 18:12 schrieb Ryan Joseph via fpc-devel:



On Apr 8, 2021, at 11:37 PM, Sven Barth via fpc-devel 
 wrote:

That is because before the introduction of type helpers such functions weren't 
really needed. Other mechanisms caught such constants, but for both type 
helpers and these implicit specializations it's hard to do it another way.

Ok then I'll add a is_constant_string function for later use.

What about this function I'm using, should it be in defutils.pas also? I need this so I can distinguish 
"unnamed array literals" like ['a','b','c'] from short strings like 'abc'. They may be internally 
identical to arrays but conceptionally they are different. Not sure about the naming so I chose "array 
literal" but "anonymous array" would make sense also.

   function is_array_literal(def:tdef): boolean;
 begin
   result := (def.typ=arraydef) and not is_constant_string(def);
 end;


This will lead to false assumptions, cause it will return True for *any* 
arraydef that's not a constant string.



Btw, this block (from create_unamed_typesym) could be a useful helper function in 
tstringdef, such as "get_default_system_type". I needed something similar to 
get the char type for a string def (and added that method already) so this is another 
logical extension to that.

case tstringdef(def).stringtype of
   st_shortstring:
 newtype:=search_system_type('SHORTSTRING');
   { st_longstring is currently not supported but
 when it is this case will need to be supplied }
   st_longstring:
 internalerror(2021040801);
   st_ansistring:
 newtype:=search_system_type('ANSISTRING');
   st_widestring:
 newtype:=search_system_type('WIDESTRING');
   st_unicodestring:
 newtype:=search_system_type('UNICODESTRING');
 end


Possibly, yes...

You could provide the various utility functions in a separate patch.

Regards,
Sven
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] Implicit function specialization precedence

2021-04-09 Thread Ryan Joseph via fpc-devel
I just realized one more type introspection related issue. This currently will 
specialize as DoThis  because the array constructor element type is 
"shortint" as is derived from the first element 1. This of course is not 
correct so I'd like to reject "array of const constructors" but I don't see how 
to know what when I get this type.

 I thought the tarraydef would have ado_IsArrayOfConst set but it does not, so 
how do I know the array constructor has multiple element types?

generic procedure DoThis(a: array of T);
begin
end;

begin
  DoThis([
1,
'string',
'c',
TObject.Create
  ])
end.

Regards,
Ryan Joseph

___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] Implicit function specialization precedence

2021-04-09 Thread Ryan Joseph via fpc-devel


> On Apr 8, 2021, at 11:37 PM, Sven Barth via fpc-devel 
>  wrote:
> 
> That is because before the introduction of type helpers such functions 
> weren't really needed. Other mechanisms caught such constants, but for both 
> type helpers and these implicit specializations it's hard to do it another 
> way.

Ok then I'll add a is_constant_string function for later use.

What about this function I'm using, should it be in defutils.pas also? I need 
this so I can distinguish "unnamed array literals" like ['a','b','c'] from 
short strings like 'abc'. They may be internally identical to arrays but 
conceptionally they are different. Not sure about the naming so I chose "array 
literal" but "anonymous array" would make sense also.

  function is_array_literal(def:tdef): boolean;
begin
  result := (def.typ=arraydef) and not is_constant_string(def);
end;

Btw, this block (from create_unamed_typesym) could be a useful helper function 
in tstringdef, such as "get_default_system_type". I needed something similar to 
get the char type for a string def (and added that method already) so this is 
another logical extension to that.

case tstringdef(def).stringtype of
  st_shortstring:
newtype:=search_system_type('SHORTSTRING');
  { st_longstring is currently not supported but 
when it is this case will need to be supplied }
  st_longstring:
internalerror(2021040801);
  st_ansistring:
newtype:=search_system_type('ANSISTRING');
  st_widestring:
newtype:=search_system_type('WIDESTRING');
  st_unicodestring:
newtype:=search_system_type('UNICODESTRING');
end


Regards,
Ryan Joseph

___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] Implicit function specialization precedence

2021-04-08 Thread Sven Barth via fpc-devel

Am 09.04.2021 um 04:20 schrieb Ryan Joseph via fpc-devel:



On Apr 8, 2021, at 3:53 PM, Sven Barth  wrote:

1. you should not blindly assume that the def is a stringdef if it's not an 
arraydef; at least use an internalerror to protect against problems here
2. if it's really a stringdef and the return type is st_shortstring you should indeed use 
SHORTSTRING (it's only constant strings which are a bit more, let's say 
"dynamic")
3. do an internalerror for st_longstring as those are currently not implemented
4. due to 2. you can move the case of newtype=nil into the if-clause with the 
arraydef

Otherwise, yes, the check for the string type is correct.

I didn't know how constant strings we identified until just now so I can correct that. 
Can we make "(def.typ=arraydef) and (ado_isconststring in 
tarraydef(def).arrayoptions)" into a function in defutils.pas and call it 
is_constant_string? That  would have been easily visible to me and lead me in the right 
direction from the start. I also had problems with array literals like [1,2,3] which 
there is no clear utility function for and prompted me to make is_array_literal() which 
is private right now (and probably not very correct in design). Moving that to a public 
space would be sensible also I think.


That is because before the introduction of type helpers such functions 
weren't really needed. Other mechanisms caught such constants, but for 
both type helpers and these implicit specializations it's hard to do it 
another way.


Regards,
Sven
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] Implicit function specialization precedence

2021-04-08 Thread Ryan Joseph via fpc-devel


> On Apr 8, 2021, at 3:53 PM, Sven Barth  wrote:
> 
> 1. you should not blindly assume that the def is a stringdef if it's not an 
> arraydef; at least use an internalerror to protect against problems here
> 2. if it's really a stringdef and the return type is st_shortstring you 
> should indeed use SHORTSTRING (it's only constant strings which are a bit 
> more, let's say "dynamic")
> 3. do an internalerror for st_longstring as those are currently not 
> implemented
> 4. due to 2. you can move the case of newtype=nil into the if-clause with the 
> arraydef
> 
> Otherwise, yes, the check for the string type is correct.

I didn't know how constant strings we identified until just now so I can 
correct that. Can we make "(def.typ=arraydef) and (ado_isconststring in 
tarraydef(def).arrayoptions)" into a function in defutils.pas and call it 
is_constant_string? That  would have been easily visible to me and lead me in 
the right direction from the start. I also had problems with array literals 
like [1,2,3] which there is no clear utility function for and prompted me to 
make is_array_literal() which is private right now (and probably not very 
correct in design). Moving that to a public space would be sensible also I 
think.

Regards,
Ryan Joseph

___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] Implicit function specialization precedence

2021-04-08 Thread Sven Barth via fpc-devel

Am 08.04.2021 um 19:28 schrieb Ryan Joseph via fpc-devel:



On Apr 7, 2021, at 1:56 PM, Ryan Joseph  wrote:

Ok, so with $H+ constant strings will be specialized as AnsiStrings. And there 
is another unicode string mode I should do a similar thing with? Also if you 
happen to know where I can get the state of $H+ that would be helpful otherwise 
I need to track it down in the debugger. :)

I think I got this part figured out (see function below). I'm going to upload 
another patch and a bunch of unit tests on the bug tracker but I'm leaving my 
latest ambiguous function call as-is until further notice. it's sneaky like it 
is but it follows rules which you can manipulate using casting.


==

function create_unamed_typesym(def:tdef): tsym;
 var
   newtype: tsym;
 begin
   newtype:=nil;
   if is_stringlike(def) then
 begin
   if (def.typ=arraydef) and (ado_isconststring in 
tarraydef(def).arrayoptions) then
 newtype:=nil
   else
 case tstringdef(def).stringtype of
   st_shortstring:
 newtype:=nil;
   st_longstring,
   st_ansistring:
 newtype:=search_system_type('ANSISTRING');
   st_widestring:
 newtype:=search_system_type('WIDESTRING');
   st_unicodestring:
 newtype:=search_system_type('UNICODESTRING');
 end;
   { not better string type was found so chose the default string 
type }
   if newtype=nil then
 begin
   if (cs_refcountedstrings in current_settings.localswitches) 
then
 begin
   if m_default_unicodestring in 
current_settings.modeswitches then
 newtype:=search_system_type('UNICODESTRING')
   else
 newtype:=search_system_type('ANSISTRING');
 end
   else
 newtype:=search_system_type('SHORTSTRING');
 end;
 end
   else
 begin
   newtype:=ctypesym.create(def.typename,def);
   newtype.owner:=def.owner;
 end;
   if newtype=nil then
 internalerror(2021020904);
   result:=newtype;
 end;


1. you should not blindly assume that the def is a stringdef if it's not 
an arraydef; at least use an internalerror to protect against problems here
2. if it's really a stringdef and the return type is st_shortstring you 
should indeed use SHORTSTRING (it's only constant strings which are a 
bit more, let's say "dynamic")
3. do an internalerror for st_longstring as those are currently not 
implemented
4. due to 2. you can move the case of newtype=nil into the if-clause 
with the arraydef


Otherwise, yes, the check for the string type is correct.

Regards,
Sven
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] Implicit function specialization precedence

2021-04-08 Thread Sven Barth via fpc-devel

Am 07.04.2021 um 23:21 schrieb Ryan Joseph via fpc-devel:

With the requested changes I believe some precedence rules have changed. These both should be "Can't 
determine which overloaded function to call" errors or the non-generic should take precedence because the 
functions are ambiguous (by appearance at least). Currently the compiler thinks DoThis is better than 
the non-generic and this may be because it was specialized as DoThis because the parameter of 
"1" is a ShortInt.

What should the rule be here?

=

procedure DoThis(a: word; b: word);
begin
end;

generic procedure DoThis(a:T; b: word);
begin
end;

begin
   DoThis(1,1); // DoThis
end.


In Delphi this takes the non-generic. But I think this comes into a 
region where things are not clearly documented, thus it's hard to get 
things "right". In theory one could move the generic check in front of 
the ordinal check and it should work, but it could get wonky again if 
you pass e.g. a LongInt into this (Delphi keeps insisting on using the 
non-generic with a LongInt constant parameter even though if you have 
two non-generic overloads it will complain that it violates the range of 
Word and ShortInt... go figure... - with a LongInt variable it will use 
the generic)


Let it be as it is now... this will only result in headaches either way.


=

generic procedure DoThis(a:T; b: word);
begin
end;

generic procedure DoThis(a: word; b: T);
begin
end;

begin
   DoThis(1,1); // Can't determine which overloaded function to call
end.

=


This is correct. Delphi behaves the same here (and it would be the same 
in the non-generic case with T being replaced by ShortInt).


Regards,
Sven
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] Implicit function specialization precedence

2021-04-08 Thread Ryan Joseph via fpc-devel


> On Apr 7, 2021, at 1:56 PM, Ryan Joseph  wrote:
> 
> Ok, so with $H+ constant strings will be specialized as AnsiStrings. And 
> there is another unicode string mode I should do a similar thing with? Also 
> if you happen to know where I can get the state of $H+ that would be helpful 
> otherwise I need to track it down in the debugger. :)

I think I got this part figured out (see function below). I'm going to upload 
another patch and a bunch of unit tests on the bug tracker but I'm leaving my 
latest ambiguous function call as-is until further notice. it's sneaky like it 
is but it follows rules which you can manipulate using casting.


==

function create_unamed_typesym(def:tdef): tsym;
var
  newtype: tsym;
begin
  newtype:=nil;
  if is_stringlike(def) then
begin
  if (def.typ=arraydef) and (ado_isconststring in 
tarraydef(def).arrayoptions) then
newtype:=nil
  else
case tstringdef(def).stringtype of
  st_shortstring:
newtype:=nil;
  st_longstring,
  st_ansistring:
newtype:=search_system_type('ANSISTRING');
  st_widestring:
newtype:=search_system_type('WIDESTRING');
  st_unicodestring:
newtype:=search_system_type('UNICODESTRING');
end;
  { not better string type was found so chose the default string 
type }
  if newtype=nil then
begin
  if (cs_refcountedstrings in current_settings.localswitches) 
then
begin
  if m_default_unicodestring in 
current_settings.modeswitches then
newtype:=search_system_type('UNICODESTRING')
  else
newtype:=search_system_type('ANSISTRING');
end
  else
newtype:=search_system_type('SHORTSTRING');
end;
end
  else
begin
  newtype:=ctypesym.create(def.typename,def);
  newtype.owner:=def.owner;
end;
  if newtype=nil then
internalerror(2021020904);
  result:=newtype;
end;

Regards,
Ryan Joseph

___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] Implicit function specialization precedence

2021-04-07 Thread Ryan Joseph via fpc-devel
With the requested changes I believe some precedence rules have changed. These 
both should be "Can't determine which overloaded function to call" errors or 
the non-generic should take precedence because the functions are ambiguous (by 
appearance at least). Currently the compiler thinks DoThis is better than 
the non-generic and this may be because it was specialized as DoThis 
because the parameter of "1" is a ShortInt.

What should the rule be here?

=

procedure DoThis(a: word; b: word);
begin
end;

generic procedure DoThis(a:T; b: word);
begin
end;

begin
  DoThis(1,1); // DoThis
end.

=

generic procedure DoThis(a:T; b: word);
begin
end;

generic procedure DoThis(a: word; b: T);
begin
end;

begin
  DoThis(1,1); // Can't determine which overloaded function to call
end.

=


Regards,
Ryan Joseph

___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] Implicit function specialization precedence

2021-04-07 Thread Ryan Joseph via fpc-devel


> On Apr 7, 2021, at 1:42 PM, Sven Barth via fpc-devel 
>  wrote:
> 
> Yes, we want to change that for two reasons:
> - the constant string might be larger than 255 characters
> - ShortString is worse for passing as a by-value parameter (which will be the 
> default after all) than AnsiString or UnicodeString as ShortString is 
> completely copied while Ansi-/UnicodeString are only references with 
> reference count adjustments

Ok, so with $H+ constant strings will be specialized as AnsiStrings. And there 
is another unicode string mode I should do a similar thing with? Also if you 
happen to know where I can get the state of $H+ that would be helpful otherwise 
I need to track it down in the debugger. :)

Regards,
Ryan Joseph

___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] Implicit function specialization precedence

2021-04-07 Thread Sven Barth via fpc-devel

Am 07.04.2021 um 18:16 schrieb Ryan Joseph via fpc-devel:



On Apr 6, 2021, at 11:34 PM, Sven Barth  wrote:

In the second case the compiler will have the non-generic Test(String) due to the 
implicit operator as well as Test(LongInt) due to the implicit 
specialization. Here it will pick the generic one, because a call without a type 
conversion is considered better.

I finally get what you're saying and get the correct results now after moving 
my check inside the if/then block. I didn't realize that the operator overload 
was causing a type conversion that the overloading system knew about. So the 
non-generic still wins unless the type conversion happened due to the operator 
overload and then the generic wins.

Writeln(Test('Hello World'));   // Test(String)
Writeln(Test(42));  // Test
Writeln(Test(String(42)));  // Test(String)


Good. :)


As for $H+ do we really want string literals likes 'ABC' to change? I wouldn't 
think so. Here's my string literal type symbol conversion in 
create_unamed_typesym I'm using now:

   case tstringdef(def).stringtype of
 st_shortstring:
   newtype:=search_system_type('SHORTSTRING');
 st_longstring,
 st_ansistring:
   newtype:=search_system_type('ANSISTRING');
 st_widestring:
   newtype:=search_system_type('WIDESTRING');
 st_unicodestring:
   newtype:=search_system_type('UNICODESTRING');
   end;

'Hello World' is parsed as st_shortstring so we use System.ShortString for 
specialization. Given that I don't think I need to do anything with $H+.


Yes, we want to change that for two reasons:
- the constant string might be larger than 255 characters
- ShortString is worse for passing as a by-value parameter (which will 
be the default after all) than AnsiString or UnicodeString as 
ShortString is completely copied while Ansi-/UnicodeString are only 
references with reference count adjustments


Also your check is wrong as the def that returns True for is_stringlike 
might not be a stringdef. In the case of a constant string it's an 
arraydef with ado_ConstantString in arrayoptions (and that's how you can 
detect constant strings which *need* this treatment).


Regards,
Sven
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] Implicit function specialization precedence

2021-04-07 Thread Ryan Joseph via fpc-devel


> On Apr 6, 2021, at 11:34 PM, Sven Barth  wrote:
> 
> In the second case the compiler will have the non-generic Test(String) due to 
> the implicit operator as well as Test(LongInt) due to the implicit 
> specialization. Here it will pick the generic one, because a call without a 
> type conversion is considered better.

I finally get what you're saying and get the correct results now after moving 
my check inside the if/then block. I didn't realize that the operator overload 
was causing a type conversion that the overloading system knew about. So the 
non-generic still wins unless the type conversion happened due to the operator 
overload and then the generic wins.

Writeln(Test('Hello World'));   // Test(String)
Writeln(Test(42));  // Test
Writeln(Test(String(42)));  // Test(String)

As for $H+ do we really want string literals likes 'ABC' to change? I wouldn't 
think so. Here's my string literal type symbol conversion in 
create_unamed_typesym I'm using now:

  case tstringdef(def).stringtype of
st_shortstring:
  newtype:=search_system_type('SHORTSTRING');
st_longstring,
st_ansistring:
  newtype:=search_system_type('ANSISTRING');
st_widestring:
  newtype:=search_system_type('WIDESTRING');
st_unicodestring:
  newtype:=search_system_type('UNICODESTRING');
  end;

'Hello World' is parsed as st_shortstring so we use System.ShortString for 
specialization. Given that I don't think I need to do anything with $H+.

Regards,
Ryan Joseph

___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] Implicit function specialization precedence

2021-04-06 Thread Sven Barth via fpc-devel

Am 06.04.2021 um 23:11 schrieb Ryan Joseph via fpc-devel:



On Apr 6, 2021, at 12:57 PM, Sven Barth  wrote:

In the example you posted below, I agree with you, but that is not what I said. 
Look at my example again:

Also could you please verify that $H+ isn't causing problems? The string literal 'Hello 
World' is a short string but "String" is an AnsiString so that may influence 
the results you're expecting.  However  even without the operator I don't know how to 
delineate between the explicit cast vs the non-explicit cast.

Writeln(Test('Hello World'));
Writeln(Test(String('Hello World')));

These both appear to be equal as far as is_better_candidate is concerned.


First of *you* need to make sure that the type you pick for the generic 
parameter for a string constant is the correct one matching the $H+ 
directive as well as the UnicodeString modeswitch (and if the string 
constant contains WideChar elements it needs to be a UnicodeString 
anyway). That's where you currently search for the SHORTSTRING type.


Then you only need to make sure that the check for generic vs. 
non-generic is in place as I said in the other mail and the compiler 
will do the rest for you. You don't need to do *anything*. Your task is 
merely to provide the compiler with the suitable overload candidates and 
a way to check their order and it will already do all the rest.


Regards,
Sven
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] Implicit function specialization precedence

2021-04-06 Thread Sven Barth via fpc-devel

Am 06.04.2021 um 22:47 schrieb Ryan Joseph via fpc-devel:



On Apr 6, 2021, at 12:57 PM, Sven Barth  wrote:

In this specific case the two functions also are *not* ambigous, because for the 
non-generic Test the parameter requires an implicit conversion, but the implicit 
specialization does not. For example if there would be a "Test(aArg: LongInt)" 
instead of the generic the compiler would pick that instead of the string one. So if you 
move the check for generic vs. non-generic to the end of is_better_candidate all the 
other rules to determine this will take precedence.

So the root of the problem is that we have no way to choose the generic 
function via explicit casting? That makes sense and presumably I can use the 
final result of is_better_candidate to determine this?


You simply need to put your check for generic vs. not-generic after the 
check for ordinal_distance inside is_better_candidate instead of at the 
start of the function.



  In your example:

Writeln(Test('Hello World'));   // is_better_candidate res = -1
Writeln(Test(42));  // is_better_candidate 
res = 1
Writeln(Test(String(42)));  // is_better_candidate res = -1

I'm struggling to see how the operator influenced the result. Res is -1 in both 
cases so how do we know which Test we want to call?


The compiler is free to use implicit operator overloads when determining 
the overload to pick.


When the compiler sees the first call to Test it will have the 
non-generic Test(String) in its candidate list as well as 
Test(String) due to the implicit specialization. Here it will 
use the non-generic one.


In the second case the compiler will have the non-generic Test(String) 
due to the implicit operator as well as Test(LongInt) due to 
the implicit specialization. Here it will pick the generic one, because 
a call without a type conversion is considered better.


In the third case the will will contain Test(String) as well as 
Test(String) due to the parameter being explicitely casted to 
String with the compiler again picking the non-generic one.


Without the explicit cast by the user the compiler would have picked the 
Test, but using a cast to the type of non-generic function one 
is able to enforce the non-generic function (for example to avoid an 
error during specialization if the Test<> function would not be able to 
handle the LongInt type).


Regards,
Sven
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] Implicit function specialization precedence

2021-04-06 Thread Ryan Joseph via fpc-devel


> On Apr 6, 2021, at 12:57 PM, Sven Barth  wrote:
> 
> In the example you posted below, I agree with you, but that is not what I 
> said. Look at my example again:

Also could you please verify that $H+ isn't causing problems? The string 
literal 'Hello World' is a short string but "String" is an AnsiString so that 
may influence the results you're expecting.  However  even without the operator 
I don't know how to delineate between the explicit cast vs the non-explicit 
cast.

Writeln(Test('Hello World'));
Writeln(Test(String('Hello World')));

These both appear to be equal as far as is_better_candidate is concerned.

Regards,
Ryan Joseph

___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] Implicit function specialization precedence

2021-04-06 Thread Ryan Joseph via fpc-devel


> On Apr 6, 2021, at 12:57 PM, Sven Barth  wrote:
> 
> In this specific case the two functions also are *not* ambigous, because for 
> the non-generic Test the parameter requires an implicit conversion, but the 
> implicit specialization does not. For example if there would be a "Test(aArg: 
> LongInt)" instead of the generic the compiler would pick that instead of the 
> string one. So if you move the check for generic vs. non-generic to the end 
> of is_better_candidate all the other rules to determine this will take 
> precedence.

So the root of the problem is that we have no way to choose the generic 
function via explicit casting? That makes sense and presumably I can use the 
final result of is_better_candidate to determine this? In your example:

Writeln(Test('Hello World'));   // is_better_candidate res = -1
Writeln(Test(42));  // is_better_candidate 
res = 1
Writeln(Test(String(42)));  // is_better_candidate res = -1

I'm struggling to see how the operator influenced the result. Res is -1 in both 
cases so how do we know which Test we want to call?

Regards,
Ryan Joseph

___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel


Re: [fpc-devel] Implicit function specialization precedence

2021-04-06 Thread Sven Barth via fpc-devel

Am 06.04.2021 um 17:45 schrieb Ryan Joseph via fpc-devel:

Finally some movement is happening on implicit function specialization and I'm 
almost finished now except some questions about precedence have been raised 
again. Initially I thought we decided on non-generic functions taking 
precedence in the case of *any* name collisions (the original thread 
https://lists.freepascal.org/pipermail/fpc-pascal/2018-December/055225.html) 
but Sven is saying now that this isn't the case (see the remarks on the bug 
report https://bugs.freepascal.org/view.php?id=35261). I'm asking this here not 
to go over Svens head but in hopes to get some answers quicker (it can take us 
weeks sometimes to round trip even simple questions).

Currently what I implemented is that in the case below non-generic Test() will take 
precedence even though Test could be specialized and indeed even comes 
after.  My questions:

1) What is required for Delphi compatibility? I never used Delphi and I thought 
we decided this initially for Delphi compatibility. Of course we can make a 
Delphi mode only option if we need to.

2) Svens final remarks on the bug tracker are "Right now your code will pick the existing String 
overload even if specializing the generic might be the better choice. If the user really wants the String 
one (or if the specializing the generic does not work) the user can still force the String overload by 
casting the parameter to a String.". I'm confused about this because Test(String) and 
Test are both identical and thus I don't see what is the "better choice".

Personally I feel like we should fallback to the non-generic function as a way to 
resolve ambiguity but I can also see why Test should take precedence simply 
because it comes after Test().


In the example you posted below, I agree with you, but that is not what 
I said. Look at my example again:


=== code begin ===

program timplicitspez;

{$mode objfpc}{$H+}
{$modeswitch IMPLICITFUNCTIONSPECIALIZATION}

function Test(const aStr: String): LongInt;
begin
  Result := 1;
end;

generic function Test(aT: T): LongInt;
begin
  Result := 2;
end;

operator := (aArg: LongInt): String;
begin
  { potentially expensive conversion }
  Result := '';
end;

begin
  Writeln(Test('Hello World'));
  Writeln(Test(42));
end.

=== code end ===

The important part here is the operator overload. If the generic 
function would not exist then the compiler would simply call the 
operator overload to convert the 42 to a String and call the function 
with the string overload. While in this example the conversion is 
essential a no-op in reality it might be more complex and expensive thus 
it might be better to use the implicit specialization of the 42 as is 
(in this case it would be a LongInt I think). Right now there is no 
possibility to enforce the use of the implicit specialization.


In this specific case the two functions also are *not* ambigous, because 
for the non-generic Test the parameter requires an implicit conversion, 
but the implicit specialization does not. For example if there would be 
a "Test(aArg: LongInt)" instead of the generic the compiler would pick 
that instead of the string one. So if you move the check for generic vs. 
non-generic to the end of is_better_candidate all the other rules to 
determine this will take precedence.


And to pick the non-generic one can do this in the above example: 
Test(String(42)), because here the type your implicit specialization 
code will receive will be String already and thus the generic vs. 
non-generic check will catch it and prefer the non-generic one.


Also Delphi agrees with me:

=== code begin ===

program timplspez;

{$APPTYPE CONSOLE}

uses
  SysUtils;

type
  TFoo = record
    f: LongInt;
    class operator Implicit(aArg: LongInt): TFoo;
  end;

  TTest = record
    class function Test(aArg: TFoo): LongInt; overload; static;
    class function Test(aArg: T): LongInt; overload; static;
  end;

class operator TFoo.Implicit(aArg: LongInt): TFoo;
begin
  Result.f := aArg;
end;

class function TTest.Test(aArg: TFoo): LongInt;
begin
  Result := 1;
end;

class function TTest.Test(aArg: T): LongInt;
begin
  Result := 2;
end;

var
  f: TFoo;
begin
  f := 21;
  Writeln(TTest.Test(f));
  Writeln(TTest.Test(42));
  Writeln(TTest.Test(TFoo(42)));
  Readln;
end.

=== code end ===

=== output begin ===

1
2
1

=== output end ===

This should answer both your points, cause they're related.

Regards,
Sven
___
fpc-devel maillist  -  fpc-devel@lists.freepascal.org
https://lists.freepascal.org/cgi-bin/mailman/listinfo/fpc-devel