[fpc-pascal] Constants in generics

Ryan Joseph ryan at thealchemistguild.com
Mon Nov 26 12:13:36 CET 2018



> On Nov 26, 2018, at 5:16 PM, Sven Barth via fpc-pascal <fpc-pascal at lists.freepascal.org> wrote:
> 
> Am Mo., 26. Nov. 2018, 10:46 hat Ryan Joseph <ryan at thealchemistguild.com> geschrieben:
> 
> 
> > On Nov 26, 2018, at 12:09 AM, Sven Barth via fpc-pascal <fpc-pascal at lists.freepascal.org> wrote:
> > 
> > - your pretty name is wrong; the pretty name for a specialization with constants should be "TSomeGeneric<TSomeType, 42>", not "TSomeGeneric<SomeUnit.TSomeType, System.LongInt#42>" as it would be now
> 
> I’ll change the # prefix for const params but the unit prefix was not added by me. See the line:
> 
> prettynamepart:=typeparam.resultdef.fullownerhierarchyname(true);
> 
> in pgenutil.pas.
> 
> Yes, but that is only because the code currently only handles types. For constants the addition of the type is not required, only the constant value. 

Then is it ok if type params have the unit prefix? Right now I’m doing TGeneric<Unit.Type,40> because the first param is a type so it uses the original code.

> Like you mention below if the const type was restricted in the definition then it would make sense to change these to tconstsym. I guess I need to try and see how much code this change blows up.
> 
> Those assumptions will "simply" have to be checked/fixed. In the end we'll have cleaner code and thus it will be worth it. And with the help of the testsuite you can avoid regressions. :) 

Ok, I’ll make it happen if it’s important.

> 
> 
> > - get rid of tscannerfile.parsing_generic_type; it's not only at the wrong location (the name "parsing_generic_type" should already tell you that it has no place inside the *scanner*), but it's also used to solve something in a completely wrong way: you must *not* use current_structdef for the generic parameters as the only valid parameter list inside parse_generic_specialization_types_internal *is* paradeflist and genericdef.genericparas. If there is still a problem then you need to handle that differently (Note: also don't Exit from parse_generic_specialization_type_internal, because the idea is that all incompatibilities are shown at once, so use Continue to check the next parameter)
> 
> Yes, that was a hack to access current_structdef safely but I guess that’s not what I should be doing. Let me see if I can get that same information from the 2 params you mentioned.
> 
> Maybe you can show a test case that is failing? 

This is why I wanted to access current_structdef. When "specialize IMyInterface<T, U>” was being parsed I need a way to refer back to the generic so I know what “U” is.

type
	generic TMyClass<T, const U> = class (specialize IMyInterface<T, U>)
		type
			THelperType = specialize THelper<T, U>;
		public
			helper: THelperType;
			procedure DoThis (value: T);
	end;
	TListClass = specialize TMyClass<integer,10>;


> 
> 
> > - remove the check for m_objfpc; yes it won't work with inline specializations in mode Delphi for now, but it can still be used for specializations in type or var sections; also one idea for an improvement I have for parsing inline specializations in mode Delphi would be if the compiler knows that the symbol left of the "<" can only be a generic (cause let's be honest: in most code types aren't overloaded with variables/constants and more often than not types begin with "T", so they shouldn't conflict with the names of more local variables/constants/fields either)
> 
> I got a crash in Delphi mode but I can change that to an error.
> 
> For now we should reject an inline specialization (aka block_type = bt_general) in mode Delphi if the found generic contains any constant parameter (declarations of such generics should be allowed). Later on we can lift that restriction once I've implemented the checks I mentioned. 

Ok, I can give an error is this one instance where it fails and allow all the others.

Regards,
	Ryan Joseph




More information about the fpc-pascal mailing list