Skip to content
This repository was archived by the owner on Oct 12, 2022. It is now read-only.

Commit 9a49c7f

Browse files
committed
Also reuse common implementation fragments for arrays
1 parent f14c296 commit 9a49c7f

File tree

1 file changed

+82
-73
lines changed

1 file changed

+82
-73
lines changed

src/rt/util/typeinfo.d

Lines changed: 82 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -267,21 +267,24 @@ unittest
267267
}();
268268
}
269269

270+
/*
271+
Reduces to `T` if `cond` is `true` or `U` otherwise.
272+
*/
270273
private template Select(bool cond, T, U)
271274
{
272275
static if (cond) alias Select = T;
273276
else alias Select = U;
274277
}
275278

276-
/**
279+
/*
277280
TypeInfo information for built-in types.
278281
279-
Type `T` has the same layout and alignment as type `Base`, but slightly different behavior.
280-
Example: `float` and `ifloat` or `char` and `ubyte`.
281-
We assume the two types hash the same, swap the same, have the same ABI flags, and compare the same for
282-
equality. For ordering comparisons, we detect during compilation whether they have different min and max
283-
values (e.g. signed vs. unsigned) and override appropriately. For initializer, we detect if we need to
284-
override. The overriding initializer should be nonzero.
282+
A `Base` type may be specified, which must be a type with the same layout, alignment, hashing, and
283+
equality comparison as type `T`. This saves on code size because parts of `Base` will be reused. Example:
284+
`float` and `ifloat` or `char` and `ubyte`. The implementation assumes `Base` and `T` hash the same, swap
285+
the same, have the same ABI flags, and compare the same for equality. For ordering comparisons, we detect
286+
during compilation whether they have different signedness and override appropriately. For initializer, we
287+
detect if we need to override. The overriding initializer should be nonzero.
285288
*/
286289
private class TypeInfoGeneric(T, Base = T) : Select!(is(T == Base), TypeInfo, TypeInfoGeneric!Base)
287290
if (T.sizeof == Base.sizeof && T.alignof == Base.alignof)
@@ -408,66 +411,72 @@ unittest
408411
}
409412
}
410413

411-
private class TypeInfoArrayGeneric(T) : TypeInfo_Array
412-
{
413-
static if (__traits(isFloating, T))
414-
{
415-
static if (is(T == ifloat)) private alias Real = float;
416-
else static if (is(T == idouble)) private alias Real = double;
417-
else static if (is(T == ireal)) private alias Real = real;
418-
else private alias Real = T;
419-
}
414+
/*
415+
TypeInfo information for arrays of built-in types.
420416
421-
override bool opEquals(Object o) { return TypeInfo.opEquals(o); }
417+
A `Base` type may be specified, which must be a type with the same layout, alignment, hashing, and
418+
equality comparison as type `T`. This saves on code size because parts of `Base` will be reused. Example:
419+
`float` and `ifloat` or `char` and `ubyte`. The implementation assumes `Base` and `T` hash the same, swap
420+
the same, have the same ABI flags, and compare the same for equality. For ordering comparisons, we detect
421+
during compilation whether they have different signedness and override appropriately. For initializer, we
422+
detect if we need to override. The overriding initializer should be nonzero.
423+
*/
424+
private class TypeInfoArrayGeneric(T, Base = T) : Select!(is(T == Base), TypeInfo_Array, TypeInfoArrayGeneric!Base)
425+
{
426+
static if (is(T == Base))
427+
override bool opEquals(Object o) { return TypeInfo.opEquals(o); }
422428

423429
override string toString() const { return (T[]).stringof; }
424430

425-
override size_t getHash(scope const void* p) @trusted const
426-
{
427-
static if (__traits(isFloating, T))
428-
return Array!Real.hashOf(*cast(Real[]*)p);
429-
else
430-
return hashOf(*cast(const T[]*) p);
431-
}
432-
433-
override bool equals(in void* p1, in void* p2) const
434-
{
435-
static if (__traits(isFloating, T))
436-
{
437-
return Array!Real.equals(*cast(Real[]*)p1, *cast(Real[]*)p2);
438-
}
439-
else
431+
static if (is(T == Base))
432+
override size_t getHash(scope const void* p) @trusted const
440433
{
441-
import core.stdc.string;
442-
auto s1 = *cast(T[]*)p1;
443-
auto s2 = *cast(T[]*)p2;
444-
return s1.length == s2.length &&
445-
memcmp(s1.ptr, s2.ptr, s1.length) == 0;
434+
static if (__traits(isFloating, T))
435+
return Array!T.hashOf(*cast(T[]*)p);
436+
else
437+
return hashOf(*cast(const T[]*) p);
446438
}
447-
}
448439

449-
override int compare(in void* p1, in void* p2) const
450-
{
451-
static if (__traits(isFloating, T))
440+
static if (is(T == Base))
441+
override bool equals(in void* p1, in void* p2) const
452442
{
453-
return Array!Real.compare(*cast(Real[]*)p1, *cast(Real[]*)p2);
443+
static if (__traits(isFloating, T))
444+
{
445+
return Array!T.equals(*cast(T[]*)p1, *cast(T[]*)p2);
446+
}
447+
else
448+
{
449+
import core.stdc.string;
450+
auto s1 = *cast(T[]*)p1;
451+
auto s2 = *cast(T[]*)p2;
452+
return s1.length == s2.length &&
453+
memcmp(s1.ptr, s2.ptr, s1.length) == 0;
454+
}
454455
}
455-
else
456-
{
457-
auto s1 = *cast(T[]*)p1;
458-
auto s2 = *cast(T[]*)p2;
459-
auto len = s1.length;
460456

461-
if (s2.length < len)
462-
len = s2.length;
463-
for (size_t u = 0; u < len; u++)
457+
static if (is(T == Base) || (__traits(isIntegral, T) && T.max != Base.max))
458+
override int compare(in void* p1, in void* p2) const
459+
{
460+
static if (__traits(isFloating, T))
464461
{
465-
if (int result = (s1[u] > s2[u]) - (s1[u] < s2[u]))
466-
return result;
462+
return Array!T.compare(*cast(T[]*)p1, *cast(T[]*)p2);
463+
}
464+
else
465+
{
466+
auto s1 = *cast(T[]*)p1;
467+
auto s2 = *cast(T[]*)p2;
468+
auto len = s1.length;
469+
470+
if (s2.length < len)
471+
len = s2.length;
472+
for (size_t u = 0; u < len; u++)
473+
{
474+
if (int result = (s1[u] > s2[u]) - (s1[u] < s2[u]))
475+
return result;
476+
}
477+
return (s1.length > s2.length) - (s1.length < s2.length);
467478
}
468-
return (s1.length > s2.length) - (s1.length < s2.length);
469479
}
470-
}
471480

472481
override @property inout(TypeInfo) next() inout
473482
{
@@ -521,18 +530,18 @@ class TypeInfo_v : TypeInfoGeneric!ubyte
521530
}
522531

523532
// All integrals.
533+
class TypeInfo_h : TypeInfoGeneric!ubyte {}
524534
class TypeInfo_b : TypeInfoGeneric!(bool, ubyte) {}
525-
class TypeInfo_g : TypeInfoGeneric!byte {}
526-
class TypeInfo_h : TypeInfoGeneric!(ubyte, byte) {}
535+
class TypeInfo_g : TypeInfoGeneric!(byte, ubyte) {}
527536
class TypeInfo_a : TypeInfoGeneric!(char, ubyte) {}
537+
class TypeInfo_t : TypeInfoGeneric!ushort {}
538+
class TypeInfo_s : TypeInfoGeneric!(short, ushort) {}
528539
class TypeInfo_u : TypeInfoGeneric!(wchar, ushort) {}
529540
class TypeInfo_w : TypeInfoGeneric!(dchar, uint) {}
530-
class TypeInfo_s : TypeInfoGeneric!short {}
531-
class TypeInfo_t : TypeInfoGeneric!(ushort, short) {}
532-
class TypeInfo_i : TypeInfoGeneric!int {}
533-
class TypeInfo_k : TypeInfoGeneric!(uint, int) {}
534-
class TypeInfo_l : TypeInfoGeneric!long {}
535-
class TypeInfo_m : TypeInfoGeneric!(ulong, long) {}
541+
class TypeInfo_k : TypeInfoGeneric!uint {}
542+
class TypeInfo_i : TypeInfoGeneric!(int, uint) {}
543+
class TypeInfo_m : TypeInfoGeneric!ulong {}
544+
class TypeInfo_l : TypeInfoGeneric!(long, ulong) {}
536545
static if (is(cent)) class TypeInfo_zi : TypeInfoGeneric!cent {}
537546
static if (is(ucent)) class TypeInfo_zk : TypeInfoGeneric!ucent {}
538547

@@ -597,24 +606,24 @@ static if (__traits(hasMember, TypeInfo, "argTypes"))
597606
}
598607

599608
// Arrays of all integrals.
600-
class TypeInfo_Ab : TypeInfoArrayGeneric!bool {}
601-
class TypeInfo_Ag : TypeInfoArrayGeneric!byte {}
602609
class TypeInfo_Ah : TypeInfoArrayGeneric!ubyte {}
603-
class TypeInfo_Aa : TypeInfoArrayGeneric!char {}
610+
class TypeInfo_Ab : TypeInfoArrayGeneric!(bool, ubyte) {}
611+
class TypeInfo_Ag : TypeInfoArrayGeneric!(byte, ubyte) {}
612+
class TypeInfo_Aa : TypeInfoArrayGeneric!(char, ubyte) {}
604613
class TypeInfo_Axa : TypeInfoArrayGeneric!(const char) {}
605614
class TypeInfo_Aya : TypeInfoArrayGeneric!(immutable char)
606615
{
607616
// Must override this, otherwise "string" is returned.
608617
override string toString() const { return "immutable(char)[]"; }
609618
}
610-
class TypeInfo_As : TypeInfoArrayGeneric!short {}
611619
class TypeInfo_At : TypeInfoArrayGeneric!ushort {}
612-
class TypeInfo_Au : TypeInfoArrayGeneric!wchar {}
613-
class TypeInfo_Ai : TypeInfoArrayGeneric!int {}
620+
class TypeInfo_As : TypeInfoArrayGeneric!(short, ushort) {}
621+
class TypeInfo_Au : TypeInfoArrayGeneric!(wchar, ushort) {}
614622
class TypeInfo_Ak : TypeInfoArrayGeneric!uint {}
615-
class TypeInfo_Aw : TypeInfoArrayGeneric!dchar {}
616-
class TypeInfo_Al : TypeInfoArrayGeneric!long {}
623+
class TypeInfo_Ai : TypeInfoArrayGeneric!(int, uint) {}
624+
class TypeInfo_Aw : TypeInfoArrayGeneric!(dchar, uint) {}
617625
class TypeInfo_Am : TypeInfoArrayGeneric!ulong {}
626+
class TypeInfo_Al : TypeInfoArrayGeneric!(long, ulong) {}
618627

619628
private extern (C) void[] _adSort(void[] a, TypeInfo ti);
620629

@@ -656,11 +665,11 @@ unittest
656665

657666
// Arrays of all floating point types.
658667
class TypeInfo_Af : TypeInfoArrayGeneric!float {}
659-
class TypeInfo_Ao : TypeInfoArrayGeneric!ifloat {}
668+
class TypeInfo_Ao : TypeInfoArrayGeneric!(ifloat, float) {}
660669
class TypeInfo_Ad : TypeInfoArrayGeneric!double {}
661-
class TypeInfo_Ap : TypeInfoArrayGeneric!idouble {}
670+
class TypeInfo_Ap : TypeInfoArrayGeneric!(idouble, double) {}
662671
class TypeInfo_Ae : TypeInfoArrayGeneric!real {}
663-
class TypeInfo_Aj : TypeInfoArrayGeneric!ireal {}
672+
class TypeInfo_Aj : TypeInfoArrayGeneric!(ireal, real) {}
664673
class TypeInfo_Aq : TypeInfoArrayGeneric!cfloat {}
665674
class TypeInfo_Ar : TypeInfoArrayGeneric!cdouble {}
666675
class TypeInfo_Ac : TypeInfoArrayGeneric!creal {}

0 commit comments

Comments
 (0)