What type functions mean on a language level

Stefan Koch uplink.coder at googlemail.com
Sat Jan 2 00:05:12 UTC 2021


On Friday, 1 January 2021 at 23:52:58 UTC, Max Haughton wrote:
> On Friday, 1 January 2021 at 23:26:58 UTC, Stefan Koch wrote:
>> Good Evening and Happy new year to everyone.
>>
>> After a stressful move to the UK in uncertain times, I am now 
>> free and able to enjoy the last day of my holiday.
>>
>> I am currently not working on DMD but on a different hobby 
>> project instead.
>>
>> So with some distance between me and the implementation 
>> details I think it's a good idea to talk about what type 
>> functions mean for the language (regardless of all the 
>> architecture issues  in DMD which make an implementation iffy)
>>
>> Specification wise type functions require two statements to be 
>> added.
>>
>> "Under certain conditions a type may be implicitly converted 
>> to a value of type __type__."
>> and
>> "Under certain conditions a value of type __type__ may be 
>> converted to a type."
>>
>> That's it.
>>
>> Everything else is just working regularly with value and 
>> expressions.
>>
>> let me give you an example.
>>
>> enum TK
>> {
>>   Integral,
>>   Floating,
>>   Other,
>> }
>>
>> string ts(__type__ t)
>> {
>>   switch (t)
>>   {
>>      case ubyte, byte, ushort, short, int, uint, long, ulong:
>>          return TK.Integral;
>>      case double, float, real :
>>          return TK.Floating;
>>      default:
>>          return TK.Other;
>>   }
>> }
>>
>>
>> this looks like it would require a new construct right?
>> infact it does not.
>>
>> since the types are used in a ctfe context where values are 
>> expected they get implicitly converted to values.
>>
>> so what happens is:
>> string ts(__type__ t)
>> {
>>      case cast(__type__)ubyte, cast(__type__)byte, 
>> cast(__type__)ushort, cast(__type__)short, cast(__type__)int, 
>> cast(__type__)uint, cast(__type__)long, cast(__type__)ulong:
>>          return TK.Integral;
>>      case cast(__type__)double, cast(__type__)float, 
>> cast(__type__)real :
>>          return TK.Floating;
>>      default:
>>          return TK.Other;
>>   }
>> }
>>
>> which converts the types into values, the same stuff as 
>> integers :)
>> and since a switch works with integers it works with types as 
>> well.
>>
>> And that is precisely the reason why I was so excited about my 
>> invention/discovery.
>>
>> It just fits in. And requires minimal changes to the spec.
>>
>> You will see that I've punted on the definition of the 
>> circumstances in which the implicit conversion from type to 
>> value and vice versa may occur.
>> That's just to keep the post short and avoid many long and 
>> boring words ;)
>>
>> I do hope you get as excited as me when reading this.
>>
>> Regards,
>> Stefan
>
> I like this idea quite a lot, some questions/points:
>
> 1. How far does this go? Are we just exposing the frontends 
> concept of a type (i.e. the contents of dmd.mtype) or a 
> abstraction over it? Can I (say) make an entirely new type like 
> a struct like I would with a mixin?

I used to think that creating entirely new types was impossible, 
because the new type would not have a mangle.
Now I see that I could just do the same thing as a template would 
do and give it a mangle of all the arguments to the type 
functions; that however has the unpleasant side effect of 
creating potentially giant mangles, which I want to avoid.
Therefore the current implementation disallows creation of new 
types.
Also I am not sure how I want the api to look like.

Perhaps like this?
struct StructField
{
     __type__ type;
     string name
}
__type__ makeStruct (string name, StructField[] fields)
{
     __struct__ sresult = __interal__magic__makeStruct(name);
     foreach(f;fields) { sresult.addField(f.name, f.type); }
     return __internal__magic__registerType(sresult);
}

> 2. I don't think avoiding spec changes is necessarily a good 
> thing - D is already fairly murky in that regard so (wrt 
> previous point) specifying exactly what typefunctions can do is 
> probably a good thing.

The are just regular CTFE-only functions they can do anything a 
pure function can do.


> 3. I think a similar thing wouldn't be all that bad for the AST 
> - read-only I should say (the only that worries me in the 
> abstract about that is that dmd's AST isn't very consistent in 
> its API) - i.e. Being able to access it as a regular (say) 
> class at CTFE rather than adding more and more and more 
> __traits.

See the sketch of a possible API above.

And feel free to suggest your own!



More information about the Digitalmars-d mailing list