Mercurial > projects > dstep
view dstep/internal/Reflection.d @ 26:6825fcc47e39
Added dstep.internal.Reflection
author | Jacob Carlborg <doob@me.com> |
---|---|
date | Tue, 06 Apr 2010 11:38:08 +0200 |
parents | |
children |
line wrap: on
line source
/** * Copyright: Copyright (c) 2010 Jacob Carlborg. * Authors: Jacob Carlborg * Version: Initial created: Mar 8, 2010 * License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0) */ module dstep.internal.Reflection; import dstep.objc.bridge.Bridge; import dstep.internal.String; /** * Returns the name of the given function * * Params: * func = the function alias to get the name of * * Returns: the name of the function */ template functionNameOf (alias func) { version(LDC) const functionNameOf = (&func).stringof[1 .. $]; else const functionNameOf = (&func).stringof[2 .. $]; } /** * Returns the parameter names of the given function * * Params: * func = the function alias to get the parameter names of * * Returns: an array of strings containing the parameter names */ template parameterNamesOf (alias func) { const parameterNamesOf = parameterNamesOfImpl!(func); } private string[] parameterNamesOfImpl (alias func) () { string funcStr = typeof(&func).stringof; auto start = funcStr.indexOf('('); auto end = funcStr.indexOf(')'); const firstPattern = ' '; const secondPattern = ','; funcStr = funcStr[start + 1 .. end]; if (funcStr == "") return null; funcStr ~= secondPattern; string token; string[] arr; foreach (c ; funcStr) { if (c != firstPattern && c != secondPattern) token ~= c; else { if (token) arr ~= token; token = null; } } if (arr.length == 1) return arr; string[] result; bool skip = false; foreach (str ; arr) { skip = !skip; if (skip) continue; result ~= str; } return result; } /** * Compile-time function to get the index of the give element. * * Performs a linear scan, returning the index of the first occurrence * of the specified element in the array, or U.max if the array does * not contain the element. * * Params: * arr = the array to get the index of the element from * element = the element to find * * Returns: the index of the element or size_t.max if the element was not found. */ private size_t indexOf (T) (T[] arr, T element) { foreach (i, e ; arr) if (e == element) return i; return size_t.max; } //FIXME fix this when http://d.puremagic.com/issues/show_bug.cgi?id=3512 is fixed version (none) { /** * Compile-time function to get the index of the give element. * * Performs a linear scan, returning the index of the first occurrence * of the specified element in the array, or U.max if the array does * not contain the element. * * Params: * arr = the array to get the index of the element from * element = the element to find * * Returns: the index of the element or size_t.max if the element was not found. */ private size_t indexOf (T) (T[] arr, dchar element) { static assert(is(T == char) || is(T == wchar) || is(T == dchar), `dstep.internal.Traits.indexOf: The given type "` ~ T.stringof ~ `" is not valid, it has to be char, wchar or dchar`); foreach (i, dchar e ; arr) if (e == element) return i; return size_t.max; } } /** * Evaluates to true if $(D_PARAM T) has a instance method with the given name * * Params: * T = the type of the class/struct * method = the name of the method */ template hasInstanceMethod (T, string method) { const hasInstanceMethod = is(typeof({ T t; mixin("auto f = &t." ~ method ~ ";"); })); } /** * Evaluates to true if $(D_PARAM T) has a class method with the given name * * Params: * T = the type of the class/struct * method = the name of the method */ template hasClassMethod (T, string method) { const hasClassMethod = is(typeof({ mixin("auto f = &T." ~ method ~ ";"); })); } /** * Evaluates to true if $(D_PARAM T) has a either a class method or a instance method * with the given name. * * Params: * T = the type of the class/struct * method = the name of the method */ template hasMethod (T, string method) { const hasMethod = hasClassMethod!(T, method) || hasInstanceMethod!(T, method); } /** * Evaluates to true if T has a field with the given name * * Params: * T = the type of the class/struct * field = the name of the field */ template hasField (T, string field) { const hasField = hasFieldImpl!(T, field, 0); } private template hasFieldImpl (T, string field, size_t i) { static if (T.tupleof.length == i) const hasFieldImpl = false; else static if (T.tupleof[i].stringof[1 + T.stringof.length + 2 .. $] == field) const hasFieldImpl = true; else const hasFieldImpl = hasFieldImpl!(T, field, i + 1); } /// Evaluates to true if $(D_PARAM T) has binded methods template hasBindedMethods (T) { const bool hasBindedMethods = hasField!(T, Bridge.objcClassMethodDeclarationVar) || hasField!(T, Bridge.objcMethodDeclarationVar); } /** * Sets the given value to the filed with the given name * * Params: * t = an instance of the type that has the field * value = the value to set */ void setValueOfField (string field, T, U) (ref T t, U value) in { static assert(hasField!(T, field), "The given field \"" ~ field ~ "\" doesn't exist in the type \"" ~ T.stringof ~ "\""); } body { const len = T.stringof.length; foreach (i, dummy ; typeof(T.tupleof)) { const f = T.tupleof[i].stringof[1 + len + 2 .. $]; static if (f == field) { t.tupleof[i] = value; break; } } } /** * Evaluates to the type of the field with the given name * * Params: * T = the type of the class/struct * field = the name of the field */ template TypeOfField (T, string field) { static assert(hasField!(T, field), "The given field \"" ~ field ~ "\" doesn't exist in the type \"" ~ T.stringof ~ "\""); alias TypeOfFieldImpl!(T, field, 0) TypeOfField; } private template TypeOfFieldImpl (T, string field, size_t i) { static if (T.tupleof[i].stringof[1 + T.stringof.length + 2 .. $] == field) alias typeof(T.tupleof[i]) TypeOfFieldImpl; else alias TypeOfFieldImpl!(T, field, i + 1) TypeOfFieldImpl; } /** * Creates a new instance of class with the given name * * Params: * name = the fully qualified name of the class * args = the arguments to the constructor * * Returns: the newly created instance or null */ T factory (T : Object, ARGS...) (string name, ARGS args) { auto classInfo = ClassInfo.find(name); if (!classInfo) return null; auto object = newInstance(classInfo); if (classInfo.flags & 8 && classInfo.defaultConstructor is null) { auto o = cast(T) object; static if (is(typeof(o._ctor(args)))) return o._ctor(args); else return null; } else { if (classInfo.flags & 8 && classInfo.defaultConstructor !is null) { Object delegate () ctor; ctor.ptr = cast(void*) object; ctor.funcptr = cast(Object function()) classInfo.defaultConstructor; return cast(T) ctor(); } else return cast(T) object; } } private { version (LDC) extern (C) Object _d_allocclass(ClassInfo); else extern (C) Object _d_newclass(ClassInfo); } /** * Creates a new instance of the given ClassInfo * * Params: * classInfo = the class to create a new instance of * * Returns: the new instance */ Object newInstance (ClassInfo classInfo) { version (LDC) { Object object = _d_allocclass(classInfo); (cast(byte*) object)[0 .. classInfo.init.length] = classInfo.init[]; return object; } else return _d_newclass(classInfo); }