What type functions mean on a language level

Stefan Koch uplink.coder at googlemail.com
Sat Jan 2 01:24:50 UTC 2021


On Friday, 1 January 2021 at 23:52:58 UTC, Max Haughton wrote:
>
> [...] specifying exactly what typefunctions can do is probably 
> a good thing.

Let a type tainted value be: - a value of type __type__ or
                      - a value of an aggregate which contains a 
type value as a field (this is transitive) or
                      - a value which is an associative array that 
contains a type value.

examples are:
__type__ x; // x is a type tainted value
__type__[string] y; // y is a type tainted value
struct S { __type__ x; }
S s; // s is a type tainted value
s[string] y2; // y2 is a type tainted value
class C
{
   typeof(y2) f;
}
C c = new C(); // c is a type tainted value


A typefunction is specified as "a function which either returns a 
type tainted value, or takes takes at least one type tainted 
value as argument"
A typefunction may only be evaluated at compile time.
A typefunction may not generate any code in object files.

Other than the 2 typefunction specific rules above it's a regular 
function.

I believe what you want specified are the operations which can be 
performed on type values.

A type value may be created by from types by means of implicit 
conversion (whenever a type value is expected; such as when 
calling a type function, or when performing a comparison via is), 
or a cast to __type__.

examples:

void f(__type__ x);
f(int); // int is implicitly converted to __type__ meaning a the 
type expression `int` is rewritten to the type value expression 
`cast(__type__)int`;

__type__[__type__] arr;
arr = [int:uint, myClass:yourClass]; // here the conversion is 
inserted as follows arr = [cast(__type__)int:cast(__type__)uint, 
cast(__type__)myClass:cast(__type__)yourClass];

or explicit auto x = cast(__type__)double;// although that's not 
needed since the type type is inferred here.

meaning:
auto x = int;
static assert (is(typeof(x) == __type__); // passes

A type value exposes all the properties of a type.
such as `.sizeof`, `.min`, `.max` and so on.
currently the exceptions here are .mangleof and stringof, since 
they can be referring to the variable itself.

examples:

__type__ t = int;
assert(t.sizeof == 4); // yep
t = double;
assert(t.sizeof == 8); // works too
t = ushort;
assert(t.max == ushort.max && t.min == ushort.min); // that's fine

assert(t.stringof == ushort.stringof) // fails: t.stringof is "t"

Furthermore a type value may be used in an is expression and in 
__traits which can take a type; where it behaves as if the it 
were type which it currently represents.

struct V3_64 { double x; double y; double z; }

t = V3_64;
assert(__traits(allMembers, t) == ["x", "y", "z"]); //passes
assert(is(t == V3_64)); // passes
assert(!is(t == double)); // passes
assert(__traits(identifier, t) == "V3_64"); // passes
// note: t.stringof is still "t"

The initialization value __type__.init is defined as the 
primitive type __emptyType also known as the empty Type.

the emptyType exposes default values for it's properties.
sizeof = 0, min = 0, max = 0, __traits(identifier, __type__.init) 
= __emptyType, __traits(allMemebers, __type__.init) = []
the other specialty about the empty type is that the is 
expression does not consider it to be a type.
which means it can be detected via: is(typeof(t) == __type__) && 
!is(t);

And I that's all there is.


More information about the Digitalmars-d mailing list