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