www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Showing TypeFunction style

reply Stefan Koch <uplink.coder googlemail.com> writes:
Hi there,

This evening I played with a partial translation of 
implicitConversionTargets help in phobos.

Here is what I have so far.
Note that this is not true transliteration because I wanted to 
show some of the more unknown type function features.
---
alias Bool = bool;
alias Ubyte = ubyte;
alias Byte = byte;
alias Ushort = ushort;
alias Short = short;
alias Uint = uint;
alias Int = int;
alias Ulong = ulong;
alias Long = long;

// for those ty.isFloating is true, which takes a diffrent path 
than all other types ;)
// therefore we can't use it as of now
//alias Double = double;
//alias Float = float;

enum basic_types = makeAliasArray(Bool, Ubyte, Byte, Short, 
Ushort, Uint, Int, Long, Ulong, /*Double, Float*/);

// temporarly needed because parser issues ....
auto makeAliasArray(alias[] types ...)
{
     return types;
}

auto convTargets(alias T)
{
     if (isBasicType(T))
         return basicTypeConvTargets(T);
     return S.init;
}

bool isBasicType(alias T)
{
     foreach(t;basic_types)
     {
         if (is(T == t))
             return true;
     }
     return false;
}

// just showing off that you can store type arrays in structs
struct S
{
     typeof(makeAliasArray()) result;
     size_t n;
     alias type;
}

auto basicTypeConvTargets(alias T)
{
     typeof(makeAliasArray()) targets;
     targets.length = basic_types.length;
     assert(isBasicType(T), "You may not call this function when 
you don't have a basic type ... (given: " ~ T.stringof ~ ")");
     size_t n = 0;
     foreach(t;basic_types)
     {
         if (is(T : t))
         {
             targets[n++] = t;
         }
     }
     return S(targets[0 .. n], n, T);
}

pragma(msg, convTargets(Long));  // S([(long), (ulong)], 2LU, 
(long))
pragma(msg, convTargets(Short)); // S([(short), (ushort), (uint), 
(int), (long), (ulong)], 6LU, (short))

---

I hope that this code will be nice and readable.

As a comparison, here is a piece from the template I translated 
which should be equivalent.

---

     static if (is(T == bool))
         alias ImplicitConversionTargets =
             AliasSeq!(byte, ubyte, short, ushort, int, uint, 
long, ulong, CentTypeList,
                        float, double, real, char, wchar, dchar);
     else static if (is(T == byte))
         alias ImplicitConversionTargets =
             AliasSeq!(short, ushort, int, uint, long, ulong, 
CentTypeList,
                        float, double, real, char, wchar, dchar);
     else static if (is(T == ubyte))
         alias ImplicitConversionTargets =
             AliasSeq!(short, ushort, int, uint, long, ulong, 
CentTypeList,
                        float, double, real, char, wchar, dchar);
     else static if (is(T == short))
         alias ImplicitConversionTargets =
             AliasSeq!(int, uint, long, ulong, CentTypeList, 
float, double, real);
     else static if (is(T == ushort))
         alias ImplicitConversionTargets =
             AliasSeq!(int, uint, long, ulong, CentTypeList, 
float, double, real);
     else static if (is(T == int))
         alias ImplicitConversionTargets =
             AliasSeq!(long, ulong, CentTypeList, float, double, 
real);
     else static if (is(T == uint))
         alias ImplicitConversionTargets =
             AliasSeq!(long, ulong, CentTypeList, float, double, 
real);
     else static if (is(T == long))
         alias ImplicitConversionTargets = AliasSeq!(float, 
double, real);
     else static if (is(T == ulong))
         alias ImplicitConversionTargets = AliasSeq!(float, 
double, real);
---

The behavior is not 100% equivalent as the hand-written target 
list does not include signed conversions in the same size class. 
(I assume this is an omission).


Please leave comments and suggestions.
Oct 02 2020
parent reply Jacob Carlborg <doob me.com> writes:
On 2020-10-03 00:24, Stefan Koch wrote:

 // temporarly needed because parser issues ....
 auto makeAliasArray(alias[] types ...)
 {
      return types;
 }
Not sure if other cares, but your examples will look more appealing if you fix the parser. -- /Jacob Carlborg
Oct 03 2020
next sibling parent reply Stefan Koch <uplink.coder googlemail.com> writes:
On Saturday, 3 October 2020 at 07:36:17 UTC, Jacob Carlborg wrote:
 On 2020-10-03 00:24, Stefan Koch wrote:

 // temporarly needed because parser issues ....
 auto makeAliasArray(alias[] types ...)
 {
      return types;
 }
Not sure if other cares, but your examples will look more appealing if you fix the parser.
Yeah ... I know. It's one of these things I keep putting off. You could remove all the aliases from my example if I did fix the parser.
Oct 03 2020
parent reply Basile B. <b2.temp gmx.com> writes:
On Saturday, 3 October 2020 at 08:44:53 UTC, Stefan Koch wrote:
 On Saturday, 3 October 2020 at 07:36:17 UTC, Jacob Carlborg 
 wrote:
 On 2020-10-03 00:24, Stefan Koch wrote:

 // temporarly needed because parser issues ....
 auto makeAliasArray(alias[] types ...)
 {
      return types;
 }
Not sure if other cares, but your examples will look more appealing if you fix the parser.
Yeah ... I know. It's one of these things I keep putting off. You could remove all the aliases from my example if I did fix the parser.
a DIP for TypeFunction requires the parser change. There are two possibilities 1. a new keyword 2. use a symbol, e.g like template instanciation with a bang The first soltion is absolutly aweful. It leads to deprecate an identifier, which will delay the feature. The second is more likely what should be adopted. At first glance I'd propose a double bang. string templateStuff = instance!stuff(); string typefuncstuff = callAtCompileTime!!stuff() so after the double bang, the parser can parse a TypeFuntionCallExpr call instead of a CallExpr.
Oct 03 2020
parent reply Stefan Koch <uplink.coder googlemail.com> writes:
On Saturday, 3 October 2020 at 10:05:23 UTC, Basile B. wrote:
 On Saturday, 3 October 2020 at 08:44:53 UTC, Stefan Koch wrote:
 On Saturday, 3 October 2020 at 07:36:17 UTC, Jacob Carlborg 
 wrote:
 On 2020-10-03 00:24, Stefan Koch wrote:

 // temporarly needed because parser issues ....
 auto makeAliasArray(alias[] types ...)
 {
      return types;
 }
Not sure if other cares, but your examples will look more appealing if you fix the parser.
Yeah ... I know. It's one of these things I keep putting off. You could remove all the aliases from my example if I did fix the parser.
a DIP for TypeFunction requires the parser change. There are two possibilities 1. a new keyword 2. use a symbol, e.g like template instanciation with a bang The first soltion is absolutly aweful. It leads to deprecate an identifier, which will delay the feature. The second is more likely what should be adopted. At first glance I'd propose a double bang. string templateStuff = instance!stuff(); string typefuncstuff = callAtCompileTime!!stuff() so after the double bang, the parser can parse a TypeFuntionCallExpr call instead of a CallExpr.
Actually, no. You can just have a rule which goes like this. Function calls may accept types. It doesn't change much, since just builtin types are rejected by the parser. Anything else is an unresolved Identifier as far as the parser is concerned.
Oct 03 2020
parent reply Basile B. <b2.temp gmx.com> writes:
On Saturday, 3 October 2020 at 10:47:47 UTC, Stefan Koch wrote:
 On Saturday, 3 October 2020 at 10:05:23 UTC, Basile B. wrote:
 On Saturday, 3 October 2020 at 08:44:53 UTC, Stefan Koch wrote:
 On Saturday, 3 October 2020 at 07:36:17 UTC, Jacob Carlborg 
 wrote:
 On 2020-10-03 00:24, Stefan Koch wrote:

 // temporarly needed because parser issues ....
 auto makeAliasArray(alias[] types ...)
 {
      return types;
 }
Not sure if other cares, but your examples will look more appealing if you fix the parser.
Yeah ... I know. It's one of these things I keep putting off. You could remove all the aliases from my example if I did fix the parser.
a DIP for TypeFunction requires the parser change. There are two possibilities 1. a new keyword 2. use a symbol, e.g like template instanciation with a bang The first soltion is absolutly aweful. It leads to deprecate an identifier, which will delay the feature. The second is more likely what should be adopted. At first glance I'd propose a double bang. string templateStuff = instance!stuff(); string typefuncstuff = callAtCompileTime!!stuff() so after the double bang, the parser can parse a TypeFuntionCallExpr call instead of a CallExpr.
Actually, no. You can just have a rule which goes like this. Function calls may accept types. It doesn't change much, since just builtin types are rejected by the parser. Anything else is an unresolved Identifier as far as the parser is concerned.
calls to type functions have to accept basic types, i.e keywords. Even if you've made the biggest part of semantic, you still need to specify this.
Oct 03 2020
parent reply Basile B. <b2.temp gmx.com> writes:
On Saturday, 3 October 2020 at 12:28:47 UTC, Basile B. wrote:
 On Saturday, 3 October 2020 at 10:47:47 UTC, Stefan Koch wrote:
 On Saturday, 3 October 2020 at 10:05:23 UTC, Basile B. wrote:
 On Saturday, 3 October 2020 at 08:44:53 UTC, Stefan Koch 
 wrote:
 On Saturday, 3 October 2020 at 07:36:17 UTC, Jacob Carlborg 
 wrote:
 On 2020-10-03 00:24, Stefan Koch wrote:

 // temporarly needed because parser issues ....
 auto makeAliasArray(alias[] types ...)
 {
      return types;
 }
Not sure if other cares, but your examples will look more appealing if you fix the parser.
Yeah ... I know. It's one of these things I keep putting off. You could remove all the aliases from my example if I did fix the parser.
a DIP for TypeFunction requires the parser change. There are two possibilities 1. a new keyword 2. use a symbol, e.g like template instanciation with a bang The first soltion is absolutly aweful. It leads to deprecate an identifier, which will delay the feature. The second is more likely what should be adopted. At first glance I'd propose a double bang. string templateStuff = instance!stuff(); string typefuncstuff = callAtCompileTime!!stuff() so after the double bang, the parser can parse a TypeFuntionCallExpr call instead of a CallExpr.
Actually, no. You can just have a rule which goes like this. Function calls may accept types. It doesn't change much, since just builtin types are rejected by the parser. Anything else is an unresolved Identifier as far as the parser is concerned.
calls to type functions have to accept basic types, i.e keywords. Even if you've made the biggest part of semantic, you still need to specify this.
not to have a special syntax will make the compiler slower. The expression semantic for a call is already complex, it's better to have a dedicated call with a dedicated syntax for type functions.
Oct 03 2020
parent reply Stefan Koch <uplink.coder googlemail.com> writes:
On Saturday, 3 October 2020 at 14:16:09 UTC, Basile B. wrote:
 On Saturday, 3 October 2020 at 12:28:47 UTC, Basile B. wrote:
 calls to type functions have to accept basic types, i.e 
 keywords.
 Even if you've made the biggest part of semantic, you still 
 need to specify this.
not to have a special syntax will make the compiler slower. The expression semantic for a call is already complex, it's better to have a dedicated call with a dedicated syntax for type functions.
type functions are supposed to support UFCS. How would I do that with the calling syntax you propose?
Oct 03 2020
parent reply Basile B. <b2.temp gmx.com> writes:
On Saturday, 3 October 2020 at 21:36:20 UTC, Stefan Koch wrote:
 On Saturday, 3 October 2020 at 14:16:09 UTC, Basile B. wrote:
 On Saturday, 3 October 2020 at 12:28:47 UTC, Basile B. wrote:
 calls to type functions have to accept basic types, i.e 
 keywords.
 Even if you've made the biggest part of semantic, you still 
 need to specify this.
not to have a special syntax will make the compiler slower. The expression semantic for a call is already complex, it's better to have a dedicated call with a dedicated syntax for type functions.
type functions are supposed to support UFCS. How would I do that with the calling syntax you propose?
UFCS style still works: size_t SizeOf(alias T){ return T.sizeof; } static assert (SizeOf!!(ubyte) == 1); static assert (ubyte!!SizeOf() == 1); static assert (ubyte!!SizeOf == 1); although you clearly loose the feel that it's like a builtin property.
Oct 03 2020
parent reply Timon Gehr <timon.gehr gmx.ch> writes:
On 04.10.20 07:04, Basile B. wrote:
 On Saturday, 3 October 2020 at 21:36:20 UTC, Stefan Koch wrote:
 On Saturday, 3 October 2020 at 14:16:09 UTC, Basile B. wrote:
 On Saturday, 3 October 2020 at 12:28:47 UTC, Basile B. wrote:
 calls to type functions have to accept basic types, i.e keywords.
 Even if you've made the biggest part of semantic, you still need to 
 specify this.
not to have a special syntax will make the compiler slower. The expression semantic for a call is already complex, it's better to have a dedicated call with a dedicated syntax for type functions.
type functions are supposed to support UFCS. How would I do that with the calling syntax you propose?
UFCS style still works:   size_t SizeOf(alias T){ return T.sizeof; }   static assert (SizeOf!!(ubyte) == 1);   static assert (ubyte!!SizeOf() == 1);   static assert (ubyte!!SizeOf == 1); although you clearly loose the feel that it's like a builtin property.
IMO this is ugly and unnecessary. The distinction between types and expressions in the parser is pointless anyway.
Oct 03 2020
parent Stefan Koch <uplink.coder googlemail.com> writes:
On Sunday, 4 October 2020 at 05:14:02 UTC, Timon Gehr wrote:
 On 04.10.20 07:04, Basile B. wrote:
 On Saturday, 3 October 2020 at 21:36:20 UTC, Stefan Koch wrote:
 On Saturday, 3 October 2020 at 14:16:09 UTC, Basile B. wrote:
 [...]
type functions are supposed to support UFCS. How would I do that with the calling syntax you propose?
UFCS style still works:   size_t SizeOf(alias T){ return T.sizeof; }   static assert (SizeOf!!(ubyte) == 1);   static assert (ubyte!!SizeOf() == 1);   static assert (ubyte!!SizeOf == 1); although you clearly loose the feel that it's like a builtin property.
IMO this is ugly and unnecessary. The distinction between types and expressions in the parser is pointless anyway.
Yes that's what I meant to say.
Oct 04 2020
prev sibling parent Stefan Koch <uplink.coder googlemail.com> writes:
On Saturday, 3 October 2020 at 07:36:17 UTC, Jacob Carlborg wrote:
 On 2020-10-03 00:24, Stefan Koch wrote:

 // temporarly needed because parser issues ....
 auto makeAliasArray(alias[] types ...)
 {
      return types;
 }
Not sure if other cares, but your examples will look more appealing if you fix the parser.
Done now: --- alias alias_t = alias; // this is needed because if a declaration starts with alias it is thought to be the old style of alias declaration. //Which is ambiguous ... sigh. alias_t[] makeAliasArray(alias[] array ...) { return array; } pragma(msg, makeAliasArray(int, ulong, void)); // outputs [(int), (ulong), (void)] --- For anyone interested the parser change was actually much more trivial than I would have thought. --- } + // if the type is not followed by a dot then the type is a type expression + if (token.value != TOK.dot) + { + e = new AST.TypeExp(loc, t); + break; + } check(TOK.dot, t.toChars()); ---
Oct 04 2020