Configurable syntax
bearophile
bearophileHUGS at lycos.com
Fri May 22 08:51:29 PDT 2009
bearophile:
>To write some templates as compile-time functions you may need to add a new type to D, named "type":<
To see if the idea of compile-time functions that process compile-time variables of type "type" isn't fully crazy I have translated some of the D1 templates of my dlibs into such compile-time functions.
The following code shows a template and its possible translation. The code is of course untested and there can be many mistakes of mine.
// -------------------------------
private template AA_impl(KeyType, ValueType) {
ValueType[KeyType] result;
const ValueType[KeyType] res = result;
}
template AA(KeyType, ValueType) {
const ValueType[KeyType] AA = AA_impl!(KeyType, ValueType).res;
}
TyVal[TyKey] newaa(type TyKey, type TyVal) {
TyVal[TyKey] aa;
return aa;
}
// -------------------------------
template AAKeyType(T) {
alias typeof(T.keys[0]) AAKeyType;
}
template AAValType(T) {
alias typeof(T.values[0]) AAValType;
}
type aaKeyType(TV, TK)(TV[TK] aa) {
return TK;
}
type aaValType(TV, TK)(TV[TK] aa) {
return TV;
}
type aaKeyType(TV, TK)(type TV[TK]) {
return TK;
}
type aaValType(TV, TK)(type TV[TK]) {
return TV;
}
// -------------------------------
template ALL(alias Predicate, Types...) {
static if (Types.length == 0)
const bool ALL = true;
else
const bool ALL = Predicate!(Types[0]) && ALL!(Predicate, Types[1 .. $]);
}
bool All(alias pred, type[] types...) {
static foreach (T; types)
static if (!pred(T))
return false;
return true;
}
ANY/Any are similar.
// -------------------------------
template BaseTypedef(T) {
static if( is( T BaseType1 == typedef ) )
alias BaseTypedef!(BaseType1) BaseTypedef;
else
alias T BaseTypedef;
}
type baseTypedef(type T) {
// the syntax of is() may be improved in many ways
static while ( is( T BaseType1 == typedef ) )
T = BaseType1;
return T;
}
A problem of the "static foreach" (that Walter will face) is that templates are functional, so their values are immutable. And Scheme shows that in a language with no mutability it's not much useful to have for/foreach loops.
In that "static while" loop the variable T of type type, is a mutable.
// -------------------------------
template CastableTypes(Types...) {
static if (Types.length <= 1)
const CastableTypes = true;
else
const CastableTypes = is(typeof(Types[0] == Types[1])) && CastableTypes!(Types[1 .. $]);
}
bool areCastableTypes(type[] Types)(type... types) {
static foreach (T; types[1 .. $])
static if (!is(typeof(Types[0] == Types[1])))
return false;
return true;
}
// -------------------------------
template DeconstArrayType(T) {
static if (IsStaticArray!(T))
alias typeof(T[0])[] DeconstArrayType;
else
alias T DeconstArrayType;
}
(DeconstArrayType works if T isn't a static array, this is very useful in my code)
type deconstArrayType(type T) {
static if (isStaticArray!(T))
return typeof(T[0])[];
//return (T[0]).typeof[];
else
return T;
}
// -------------------------------
template IsType(T, Types...) {
// Original idea by Burton Radons, modified
static if (Types.length == 0)
const bool IsType = false;
else
const bool IsType = is(T == Types[0]) || IsType!(T, Types[1 .. $]);
}
bool isType(T, type[] types...) {
static foreach (TX; types)
// now == works among run-time variables of type "type".
static if (T == TX)
return true;
return false;
}
Or even simpler, if the compiler understands that isType is a compile-time-function-only:
bool isType(T, type[] types...) {
foreach (TX; types)
if (T == TX)
return true;
return false;
}
With Any() and a compile-time lambda you can write:
bool isType(T, type[] types...) {
return Any((type TX){ return T == TX; }, types);
}
:-)
// -------------------------------
Bye,
bearophile
More information about the Digitalmars-d
mailing list