Note: This website is archived. For up-to-date information about D projects and development, please visit wiki.dlang.org.

Changeset 1540

Show
Ignore:
Timestamp:
05/23/10 00:35:48 (15 years ago)
Author:
rsinfu
Message:

Added BlackHole? and WhiteHole?.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • trunk/phobos/std/traits.d

    r1531 r1540  
    1111 * License:   <a href="http://www.boost.org/LICENSE_1_0.txt">Boost License 1.0</a>. 
    1212 * Authors:   $(WEB digitalmars.com, Walter Bright), 
    1313 *            Tomasz Stachowiak ($(D isExpressionTuple)), 
    1414 *            $(WEB erdani.org, Andrei Alexandrescu), 
    1515 *            Shin Fujishiro 
    1616 * 
    1717 *          Copyright Digital Mars 2005 - 2009. 
    1818 * Distributed under the Boost Software License, Version 1.0. 
    1919 *    (See accompanying file LICENSE_1_0.txt or copy at 
    2020 *          http://www.boost.org/LICENSE_1_0.txt) 
    21  * 
    22  * Macros: 
    23  *   EM = <em>$0</em> 
    2421 */ 
    2522module std.traits; 
    2623import std.typetuple; 
    2724 
    2825 
    2926//:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::// 
    3027// Functions 
    3128//:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::// 
    3229 
    3330// Petit demangler 
     
    493490$(D FunctionTypeOf) is able to obtain function types of properties. 
    494491-------------------- 
    495492class C { 
    496493    int value() @property; 
    497494} 
    498495static assert(is( typeof(C.value) == int )); 
    499496static assert(is( FunctionTypeOf!(C.value) == function )); 
    500497-------------------- 
    501498 
    502499Note: 
    503 Do not confuse function types with function $(EM pointer) types; function types 
    504 are usually used for compile-time reflection purposes. 
     500Do not confuse function types with function pointer types; function types are 
     501usually used for compile-time reflection purposes. 
    505502 */ 
    506503template FunctionTypeOf(func...) 
    507504    if (func.length == 1 && isCallable!(func)) 
    508505{ 
    509506    static if (is(typeof(& func[0]) Fsym : Fsym*) && is(Fsym == function)) 
    510507    { 
    511508        alias Fsym FunctionTypeOf; // HIT: function symbol 
    512509    } 
    513510    else static if (is(typeof(& func[0].opCall) Fobj == delegate)) 
    514511    { 
     
    20532050    static assert(isSomeFunction!(real function(ref int))); 
    20542051    static assert(isSomeFunction!(real delegate(ref int))); 
    20552052 
    20562053    static assert(! isSomeFunction!(int)); 
    20572054    static assert(! isSomeFunction!(val)); 
    20582055    static assert(! isSomeFunction!(isSomeFunction)); 
    20592056} 
    20602057 
    20612058 
    20622059/** 
    2063 Detect whether $(D T) is a callable object, which can be $(EM called) with the 
     2060Detect whether $(D T) is a callable object, which can be called with the 
    20642061function call operator $(D $(LPAREN)...$(RPAREN)). 
    20652062 */ 
    20662063template isCallable(T...) 
    20672064    if (T.length == 1) 
    20682065{ 
    20692066    static if (is(typeof(& T[0].opCall) == delegate)) 
    20702067        // T is a object which has a member function opCall(). 
    20712068        enum bool isCallable = true; 
    20722069    else static if (is(typeof(& T[0].opCall) V : V*) && is(V == function)) 
    20732070        // T is a type which has a static member function opCall(). 
     
    22942291 
    22952292 
    22962293//::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::// 
    22972294// Misc. 
    22982295//::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::// 
    22992296 
    23002297/** 
    23012298Returns the mangled name of symbol or type $(D sth). 
    23022299 
    23032300$(D mangledName) is the same as builtin $(D .mangleof) property, except that 
    2304 the $(EM correct) names of property functions are obtained. 
     2301the correct names of property functions are obtained. 
    23052302-------------------- 
    23062303module test; 
    23072304import std.traits : mangledName; 
    23082305 
    23092306class C { 
    23102307    int value() @property; 
    23112308} 
    23122309pragma(msg, C.value.mangleof);      // prints "i" 
    23132310pragma(msg, mangledName!(C.value)); // prints "_D4test1C5valueMFNdZi" 
    23142311-------------------- 
     
    23642361            m_upb *= 10; 
    23652362        } 
    23662363    } 
    23672364 
    23682365    return s; 
    23692366} 
    23702367 
    23712368unittest 
    23722369{ 
    23732370    typedef int MyInt; 
     2371    MyInt test() { return 0; } 
    23742372    class C { int value() @property { return 0; } } 
    23752373    static assert(mangledName!(int) == int.mangleof); 
    23762374    static assert(mangledName!(C) == C.mangleof); 
    23772375    static assert(mangledName!(MyInt)[$ - 7 .. $] == "T5MyInt"); 
     2376    //static assert(mangledName!(test)[$ - 7 .. $] == "T5MyInt"); 
     2377        // seems bug in dmd: the preceding T is omitted 
    23782378    static assert(mangledName!(C.value)[$ - 12 .. $] == "5valueMFNdZi"); 
    23792379    static assert(mangledName!(mangledName) == "3std6traits11mangledName"); 
    23802380    static assert(mangledName!(removeDummyEnvelope) == 
    23812381            "_D3std6traits19removeDummyEnvelopeFAyaZAya"); 
    23822382} 
    23832383 
    23842384 
    23852385/* 
    23862386workaround for [BUG 2234] "allMembers does not return interface members" 
    23872387 */ 
  • trunk/phobos/std/typecons.d

    r1531 r1540  
    11// Written in the D programming language. 
    22 
    33/** 
    44This module implements a variety of type constructors, i.e., templates 
    55that allow construction of new, useful general-purpose types. 
    66 
    77Macros: 
    88 
    99WIKI = Phobos/StdVariant 
    10 EM   = <em>$0</em> 
    1110  
    1211Synopsis: 
    1312 
    1413---- 
    1514// value tuples 
    1615alias Tuple!(float, "x", float, "y", float, "z") Coord; 
    1716Coord c; 
    1817c.field[1] = 1;   // access by index 
    1918c.z = 1;          // access by given name 
    2019alias Tuple!(string, string) DicEntry; // names can be omitted 
     
    13791378    assert(a == 5); 
    13801379    a = 42; 
    13811380    assert(!a.isNull); 
    13821381    assert(a == 42); 
    13831382} 
    13841383 
    13851384+/ 
    13861385 
    13871386 
    13881387/** 
    1389 $(D AutoImplement), by default, automatically implements all abstract member 
    1390 functions in the class or interface $(D Base) as do-nothing functions. 
    1391  
     1388$(D BlackHole!Base) is a subclass of $(D Base) which automatically implements 
     1389all abstract member functions in $(D Base) as do-nothing functions.  Each 
     1390auto-implemented function just returns the default value of the return type 
     1391without doing anything. 
     1392 
     1393Example: 
    13921394-------------------- 
    1393 abstract class Base 
     1395abstract class C 
    13941396{ 
    13951397    int m_value; 
    13961398    this(int v) { m_value = v; } 
    13971399    int value() @property { return m_value; } 
    13981400 
    13991401    abstract real realValue() @property; 
    14001402    abstract void doSomething(); 
    14011403} 
    14021404 
    14031405void main() 
    14041406{ 
    1405     auto obj = new AutoImplement!Base(42); 
    1406     writeln(obj.value);     // prints "42" 
     1407    auto c = new BlackHole!C(42); 
     1408    writeln(c.value);     // prints "42" 
    14071409 
    14081410    // Abstract functions are implemented as do-nothing: 
    1409     writeln(obj.realValue); // prints "NaN" 
    1410     obj.doSomething();      // does nothing 
     1411    writeln(c.realValue); // prints "NaN" 
     1412    c.doSomething();      // does nothing 
    14111413} 
    14121414-------------------- 
    14131415 
    1414 The behavior can be customized with the parameters. 
     1416See_Also: 
     1417  AutoImplement, generateEmptyFunction 
     1418 */ 
     1419template BlackHole(Base) 
     1420
     1421    alias AutoImplement!(Base, generateEmptyFunction, isAbstractFunction) 
     1422            BlackHole; 
     1423
     1424 
     1425unittest 
     1426
     1427    // return default 
     1428    { 
     1429        interface I_1 { real test(); } 
     1430        auto o = new BlackHole!I_1; 
     1431        assert(o.test() !<>= 0); // NaN 
     1432    } 
     1433    // doc example 
     1434    { 
     1435        static class C 
     1436        { 
     1437            int m_value; 
     1438            this(int v) { m_value = v; } 
     1439            int value() @property { return m_value; } 
     1440 
     1441            abstract real realValue() @property; 
     1442            abstract void doSomething(); 
     1443        } 
     1444 
     1445        auto c = new BlackHole!C(42); 
     1446        assert(c.value == 42); 
     1447 
     1448        assert(c.realValue !<>= 0); // NaN 
     1449        c.doSomething(); 
     1450    } 
     1451
     1452 
     1453 
     1454/** 
     1455$(D WhiteHole!Base) is a subclass of $(D Base) which automatically implements 
     1456all abstract member functions as throw-always functions.  Each auto-implemented 
     1457function fails with $(D AsertError) and does never return.  Useful for trapping 
     1458use of not-yet-implemented functions. 
     1459 
     1460Example: 
     1461-------------------- 
     1462class C 
     1463
     1464    abstract void notYetImplemented(); 
     1465
     1466 
     1467void main() 
     1468
     1469    auto c = new WhiteHole!C; 
     1470    c.notYetImplemented(); // throws AssertError 
     1471
     1472-------------------- 
     1473 
     1474See_Also: 
     1475  AutoImplement, generateAssertTrap 
     1476 */ 
     1477template WhiteHole(Base) 
     1478
     1479    alias AutoImplement!(Base, generateAssertTrap, isAbstractFunction) 
     1480            WhiteHole; 
     1481
     1482 
     1483unittest 
     1484
     1485    // doc example 
     1486    { 
     1487        static class C 
     1488        { 
     1489            abstract void notYetImplemented(); 
     1490        } 
     1491 
     1492        auto c = new WhiteHole!C; 
     1493        try 
     1494        { 
     1495            c.notYetImplemented(); 
     1496            assert(0); 
     1497        } 
     1498        catch (Error e) {} 
     1499    } 
     1500
     1501 
     1502 
     1503/** 
     1504$(D AutoImplement) automatically implements (by default) all abstract member 
     1505functions in the class or interface $(D Base) in specified way. 
    14151506 
    14161507Params: 
    1417   how  = A template which determines _how functions will be 
    1418          implemented/overridden. 
     1508  how  = template which specifies _how functions will be implemented/overridden. 
    14191509 
    14201510         Two arguments are passed to $(D how): the first one is the $(D Base), 
    14211511         and the second one is an alias to a function to be implemented.  Then 
    14221512         $(D how) must return a implemented function body as a string. 
    14231513 
    14241514         The generated function body can use these keywords: 
    14251515         $(UL 
    14261516            $(LI $(D a0), $(D a1), &hellip;: arguments passed to the function;) 
    14271517            $(LI $(D args): a tuple of the arguments;) 
    14281518            $(LI $(D self): an alias to the function itself;) 
     
    14481538            stmt ~= q{ 
    14491539                auto r = parent(args); 
    14501540                Importer.writeln("--> ", r); 
    14511541                return r; 
    14521542            }; 
    14531543    } 
    14541544    return stmt; 
    14551545} 
    14561546-------------------- 
    14571547 
    1458   what = A template which determines _what functions should be 
     1548  what = template which determines _what functions should be 
    14591549         implemented/overridden. 
    14601550 
    14611551         An argument is passed to $(D what): an alias to a non-final member 
    14621552         function in $(D Base).  Then $(D what) must return a boolean value. 
    14631553         Return $(D true) to indicate that the passed function should be 
    14641554         implemented/overridden. 
    14651555 
    14661556-------------------- 
    14671557// Sees if fun returns something. 
    14681558template hasValue(alias fun) 
     
    14831573 
    14841574BUGS: 
    14851575 
    14861576$(UL 
    14871577 $(LI Variadic arguments to constructors are not forwarded to super.) 
    14881578 $(LI Deep interface inheritance causes compile error with messages like 
    14891579      "Error: function std.typecons._AutoImplement!(Foo)._AutoImplement.bar 
    14901580      does not override any function".  [$(BUGZILLA 2525), $(BUGZILLA 3525)] ) 
    14911581 $(LI The $(D parent) keyword is actually a delegate to the super class' 
    14921582      corresponding member function.  [$(BUGZILLA 2540)] ) 
    1493  $(LI Using $(D alias) template parameter in $(D how) and/or $(D what) may 
    1494       cause strange compile error.  Use template tuple parameter instead to 
    1495       workaround this problem.  [$(BUGZILLA 4217)] ) 
     1583 $(LI Using alias template parameter in $(D how) and/or $(D what) may cause 
     1584     strange compile error.  Use template tuple parameter instead to workaround 
     1585     this problem.  [$(BUGZILLA 4217)] ) 
    14961586) 
    14971587 */ 
    1498 class AutoImplement( Base, 
    1499         alias how = generateEmptyFunction, alias what = isAbstractFunction ) 
    1500     : Base 
     1588class AutoImplement(Base, alias how, alias what = isAbstractFunction) : Base 
    15011589{ 
    15021590    private alias AutoImplement_Helper!( 
    15031591            "autoImplement_helper_", "Base", Base, how, what ) 
    15041592             autoImplement_helper_; 
    15051593    override mixin(autoImplement_helper_.code); 
    15061594} 
    15071595 
    15081596/* 
    15091597 * Code-generating stuffs are encupsulated in this helper template so that 
    15101598 * namespace pollusion, which can cause name confliction with Base's public 
     
    17181806        pragma(msg, "--------------------"); 
    17191807    } 
    17201808} 
    17211809 
    17221810//debug = SHOW_GENERATED_CODE; 
    17231811unittest 
    17241812{ 
    17251813    // no function to implement 
    17261814    { 
    17271815        interface I_1 {} 
    1728         auto o = new AutoImplement!I_1; 
    1729     } 
    1730     // return value 
    1731     { 
    1732         interface I_2 { real test(); } 
    1733         auto o = new AutoImplement!I_2; 
    1734         assert(o.test() !<>= 0); // NaN 
     1816        auto o = new BlackHole!I_1; 
    17351817    } 
    17361818    // parameters 
    17371819    { 
    17381820        interface I_3 { void test(int, in int, out int, ref int, lazy int); } 
    1739         auto o = new AutoImplement!I_3; 
     1821        auto o = new BlackHole!I_3; 
    17401822    } 
    17411823    // use of user-defined type 
    17421824    { 
    1743         typedef int MyInt; 
    1744         interface I_4 { MyInt test(); } 
    1745         auto o = new AutoImplement!I_4; 
     1825        struct S {} 
     1826        interface I_4 { S test(); } 
     1827        auto o = new BlackHole!I_4; 
    17461828    } 
    17471829    // overloads 
    17481830    { 
    17491831        interface I_5 
    17501832        { 
    17511833            void test(string); 
    17521834            real test(real); 
    17531835            int  test(); 
    17541836            int  test() @property; // ? 
    17551837        } 
    1756         auto o = new AutoImplement!I_5; 
     1838        auto o = new BlackHole!I_5; 
    17571839    } 
    17581840    // constructor forwarding 
    17591841    { 
    17601842        static class C_6 
    17611843        { 
    17621844            this(int n) { assert(n == 42); } 
    17631845            this(string s) { assert(s == "Deeee"); } 
    17641846            this(...) {} 
    17651847        } 
    1766         auto o1 = new AutoImplement!C_6(42); 
    1767         auto o2 = new AutoImplement!C_6("Deeee"); 
    1768         auto o3 = new AutoImplement!C_6(1, 2, 3, 4); 
     1848        auto o1 = new BlackHole!C_6(42); 
     1849        auto o2 = new BlackHole!C_6("Deeee"); 
     1850        auto o3 = new BlackHole!C_6(1, 2, 3, 4); 
    17691851    } 
    17701852    /+ // deep inheritance 
    17711853    { 
    17721854    // XXX [BUG 2525,3525] 
    17731855    // NOTE: [r494] func.c(504-571) FuncDeclaration::semantic() 
    17741856        interface I { void foo(); } 
    17751857        interface J : I {} 
    17761858        interface K : J {} 
    17771859        static abstract class C_8 : K {} 
    1778         auto o = new AutoImplement!C_8; 
    1779     } +/ 
    1780     // doc example 
    1781     { 
    1782         static class Base 
    1783         { 
    1784             int m_value; 
    1785             this(int v) { m_value = v; } 
    1786             int value() @property { return m_value; } 
    1787  
    1788             abstract real realValue() @property; 
    1789             abstract void doSomething(); 
    1790         } 
    1791  
    1792         auto obj = new AutoImplement!Base(42); 
    1793         assert(obj.value == 42); 
    1794  
    1795         assert(obj.realValue !<>= 0); // NaN 
    1796         obj.doSomething(); 
    1797     } 
    1798 
    1799  
    1800  
    1801 /** 
    1802 The default $(EM how)-policy for $(D AutoImplement).  Every generated function 
    1803 returns the default value without doing anything. 
     1860        auto o = new BlackHole!C_8; 
     1861    }+/ 
     1862
     1863 
     1864 
     1865/* 
     1866Used by MemberFunctionGenerator. 
     1867 */ 
     1868private template OverloadSet(string nam, T...) 
     1869
     1870    enum string name = nam; 
     1871    alias T contents; 
     1872
     1873 
     1874/* 
     1875Used by MemberFunctionGenerator. 
     1876 */ 
     1877private template FuncInfo(alias func, /+[BUG 4217 ?]+/ T = typeof(&func)) 
     1878
     1879    alias         ReturnType!(T) RT; 
     1880    alias ParameterTypeTuple!(T) PT; 
     1881
     1882 
     1883/* 
     1884General-purpose member function generator. 
     1885 */ 
     1886private template MemberFunctionGenerator(alias Policy) 
     1887
     1888private static: 
     1889    //mixin Policy; // can't 
     1890 
     1891    //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::// 
     1892    // Internal stuffs 
     1893    //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::// 
     1894 
     1895    enum CONSTRUCTOR_NAME = "__ctor"; 
     1896    enum WITH_BASE_CLASS  = __traits(compiles, Policy.BASE_CLASS_ID); 
     1897 
     1898    // Returns a tuple consisting of 0,1,2,...,n-1.  For static foreach. 
     1899    template CountUp(size_t n) 
     1900    { 
     1901        static if (n > 0) 
     1902            alias TypeTuple!(CountUp!(n - 1), n - 1) CountUp; 
     1903        else 
     1904            alias TypeTuple!() CountUp; 
     1905    } 
     1906 
     1907 
     1908    //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::// 
     1909    // Code generator 
     1910    //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::// 
     1911 
     1912    /* 
     1913     * Runs through all the target overload sets and generates D code which 
     1914     * implements all the functions in the overload sets. 
     1915     */ 
     1916    public string generateCode(overloads...)() @property 
     1917    { 
     1918        string code = ""; 
     1919 
     1920        // run through all the overload sets 
     1921        foreach (i_; CountUp!(0 + overloads.length)) // workaround 
     1922        { 
     1923            enum i = 0 + i_; // workaround 
     1924            alias overloads[i] oset; 
     1925 
     1926            code ~= generateCodeForOverloadSet!(oset); 
     1927 
     1928            static if (WITH_BASE_CLASS && oset.name != CONSTRUCTOR_NAME) 
     1929            { 
     1930                // The generated function declarations may hide existing ones 
     1931                // in the base class (cf. HiddenFuncError), so we put an alias 
     1932                // declaration here to reveal possible hidden functions. 
     1933                code ~= Format!("alias %s.%s %s;\n", 
     1934                            Policy.BASE_CLASS_ID, // [BUG 2540] super. 
     1935                            oset.name, oset.name ); 
     1936            } 
     1937        } 
     1938        return code; 
     1939    } 
     1940 
     1941    // handle each overload set 
     1942    private string generateCodeForOverloadSet(alias oset)() @property 
     1943    { 
     1944        string code = ""; 
     1945 
     1946        foreach (i_; CountUp!(0 + oset.contents.length)) // workaround 
     1947        { 
     1948            enum i = 0 + i_; // workaround 
     1949            code ~= generateFunction!( 
     1950                    oset.contents[i], Policy.FUNCINFO_ID!(oset.name, i)) ~ "\n"; 
     1951        } 
     1952        return code; 
     1953    } 
     1954 
     1955    /* 
     1956     * Returns D code which implements the function func.  This function 
     1957     * actually generates only the declarator part; the function body part is 
     1958     * generated by the functionGenerator() policy. 
     1959     */ 
     1960    //private string generateFunction(alias func, string myFuncInfo)() @property 
     1961    private string generateFunction(args_.../+[BUG 4217]+/)() @property 
     1962    { 
     1963        alias args_[0..1] func; enum myFuncInfo = args_[1]; 
     1964 
     1965        enum name   = __traits(identifier, func); 
     1966        enum isCtor = (name == CONSTRUCTOR_NAME); 
     1967 
     1968        string code; // the result 
     1969 
     1970        /*** Function Declarator ***/ 
     1971        { 
     1972            alias FunctionAttribute FA; 
     1973            enum atts     = functionAttributes!(func); 
     1974            enum realName = isCtor ? "this" : name; 
     1975 
     1976            /* Just for the sake of Format!(...). */ 
     1977            static string make_postAtts() 
     1978            { 
     1979                string poatts = ""; 
     1980                if (atts & FA.PURE    ) poatts ~= " pure"; 
     1981                if (atts & FA.NOTHROW ) poatts ~= " nothrow"; 
     1982                if (atts & FA.PROPERTY) poatts ~= " @property"; 
     1983                if (atts & FA.SAFE    ) poatts ~= " @safe"; 
     1984                if (atts & FA.TRUSTED ) poatts ~= " @trusted"; 
     1985                return poatts; 
     1986            } 
     1987            enum postAtts = make_postAtts(); 
     1988 
     1989            static string make_returnType() 
     1990            { 
     1991                string rtype = ""; 
     1992 
     1993                if (!isCtor) 
     1994                { 
     1995                    if (atts & FA.REF) rtype ~= "ret "; 
     1996                    rtype ~= myFuncInfo ~ ".RT"; 
     1997                } 
     1998                return rtype; 
     1999            } 
     2000            enum returnType = make_returnType(); 
     2001 
     2002            // 
     2003            code ~= Format!("extern(%s) %s %s(%s) %s\n", 
     2004                    functionLinkage!(func), 
     2005                    returnType, 
     2006                    realName, 
     2007                    ""~generateParameters!(func, myFuncInfo), 
     2008                    postAtts ); 
     2009        } 
     2010 
     2011        /*** Function Body ***/ 
     2012        code ~= "{\n"; 
     2013        { 
     2014            enum nparams = ParameterTypeTuple!(func).length; 
     2015 
     2016            /* Declare keywords: args, self and parent. */ 
     2017            string preamble; 
     2018 
     2019            preamble ~= "alias TypeTuple!(" ~ enumerateParameters!(nparams) ~ ") args;\n"; 
     2020            if (!isCtor) 
     2021            { 
     2022                preamble ~= "alias " ~ name ~ " self;\n"; 
     2023                if (WITH_BASE_CLASS && !__traits(isAbstractFunction, func)) 
     2024                    //preamble ~= "alias super." ~ name ~ " parent;\n"; // [BUG 2540] 
     2025                    preamble ~= "auto parent = &super." ~ name ~ ";\n"; 
     2026            } 
     2027 
     2028            // 
     2029            code ~= preamble; 
     2030            code ~= Policy.generateFunctionBody!(func); 
     2031        } 
     2032        code ~= "}"; 
     2033 
     2034        return code; 
     2035    } 
     2036 
     2037    /* 
     2038     * Returns D code which declares function parameters. 
     2039     * "ref int a0, real a1, ..." 
     2040     */ 
     2041    //private string generateParameters(alias func, string myFuncInfo)() @property 
     2042    private string generateParameters(args_.../+[BUG 4217]+/)() @property 
     2043    { 
     2044        alias args_[0..1] func; enum myFuncInfo = args_[1]; 
     2045 
     2046        alias ParameterStorageClass STC; 
     2047        alias ParameterStorageClassTuple!(func) stcs; 
     2048        enum nparams = stcs.length; 
     2049 
     2050        string params = ""; // the result 
     2051 
     2052        foreach (i, stc; stcs) 
     2053        { 
     2054            if (i > 0) params ~= ", "; 
     2055 
     2056            // Parameter storage classes. 
     2057            if (stc & STC.SCOPE) params ~= "scope "; 
     2058            if (stc & STC.OUT  ) params ~= "out "; 
     2059            if (stc & STC.REF  ) params ~= "ref "; 
     2060            if (stc & STC.LAZY ) params ~= "lazy "; 
     2061 
     2062            // Take parameter type from the FuncInfo. 
     2063            params ~= myFuncInfo ~ ".PT[" ~ toStringNow!(i) ~ "]"; 
     2064 
     2065            // Declare a parameter variable. 
     2066            params ~= " " ~ Policy.PARAMETER_VARIABLE_ID!(i); 
     2067        } 
     2068 
     2069        // Add some ellipsis part if needed. 
     2070        final switch (variadicFunctionStyle!(func)) 
     2071        { 
     2072            case Variadic.NO: 
     2073                break; 
     2074 
     2075            case Variadic.C, Variadic.D: 
     2076                // (...) or (a, b, ...) 
     2077                params ~= (nparams == 0) ? "..." : ", ..."; 
     2078                break; 
     2079 
     2080            case Variadic.TYPESAFE: 
     2081                params ~= " ..."; 
     2082                break; 
     2083        } 
     2084 
     2085        return params; 
     2086    } 
     2087 
     2088    // Returns D code which enumerates n parameter variables using comma as the 
     2089    // separator.  "a0, a1, a2, a3" 
     2090    private string enumerateParameters(size_t n)() @property 
     2091    { 
     2092        string params = ""; 
     2093 
     2094        foreach (i_; CountUp!(n)) 
     2095        { 
     2096            enum i = 0 + i_; // workaround 
     2097            if (i > 0) params ~= ", "; 
     2098            params ~= Policy.PARAMETER_VARIABLE_ID!(i); 
     2099        } 
     2100        return params; 
     2101    } 
     2102
     2103 
     2104 
     2105/** 
     2106Predefined how-policies for $(D AutoImplement).  These templates are used by 
     2107$(D BlackHole) and $(D WhiteHole), respectively. 
    18042108 */ 
    18052109template generateEmptyFunction(C, func.../+[BUG 4217]+/) 
    18062110{ 
    18072111    static if (is(ReturnType!(func) == void)) 
    18082112        enum string generateEmptyFunction = q{ 
    18092113        }; 
    18102114    else static if (functionAttributes!(func) & FunctionAttribute.REF) 
    18112115        enum string generateEmptyFunction = q{ 
    18122116            static typeof(return) dummy; 
    18132117            return dummy; 
    18142118        }; 
    18152119    else 
    18162120        enum string generateEmptyFunction = q{ 
    18172121            return typeof(return).init; 
    18182122        }; 
    18192123} 
    18202124 
    1821  
    1822 /** 
    1823 A $(EM how)-policy for $(D AutoImplement).  Every generated function fails with 
    1824 $(D AssertError) and does never return.  Useful for trapping use of 
    1825 not-yet-implemented functions. 
    1826  
    1827 Example: 
    1828 -------------------- 
    1829 class C 
    1830 
    1831     abstract void notYetImplemented(); 
    1832 
    1833  
    1834 void main() 
    1835 
    1836     auto obj = new AutoImplement!(C, generateAssertTrap); 
    1837     obj.notYetImplemented(); // throws AssertError 
    1838 
    1839 -------------------- 
    1840  */ 
     2125/// ditto 
    18412126template generateAssertTrap(C, func.../+[BUG 4217]+/) 
    18422127{ 
    18432128    enum string generateAssertTrap = 
    18442129        `assert(0, "` ~ (C.stringof ~ "." ~ __traits(identifier, func)) 
    18452130                ~ ` is not implemented");`; 
    18462131} 
    1847  
    1848 unittest // doc example 
    1849 { 
    1850     static class C 
    1851     { 
    1852         abstract void notYetImplemented(); 
    1853     } 
    1854  
    1855     auto o = new AutoImplement!(C, generateAssertTrap); 
    1856     try 
    1857     { 
    1858         o.notYetImplemented(); 
    1859         assert(0); 
    1860     } 
    1861     catch (Error e) {} 
    1862 } 
    1863  
    1864  
    1865 /* 
    1866 Used by MemberFunctionGenerator. 
    1867  */ 
    1868 private template OverloadSet(string nam, T...) 
    1869 { 
    1870     enum string name = nam; 
    1871     alias T contents; 
    1872 } 
    1873  
    1874 /* 
    1875 Used by MemberFunctionGenerator. 
    1876  */ 
    1877 private template FuncInfo(alias func, /+[BUG 4217 ?]+/ T = typeof(&func)) 
    1878 { 
    1879     alias         ReturnType!(T) RT; 
    1880     alias ParameterTypeTuple!(T) PT; 
    1881 } 
    1882  
    1883 /* 
    1884 General-purpose member function generator. 
    1885  */ 
    1886 private template MemberFunctionGenerator(alias Policy) 
    1887 { 
    1888 private static: 
    1889     //mixin Policy; // can't 
    1890  
    1891     //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::// 
    1892     // Internal stuffs 
    1893     //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::// 
    1894  
    1895     enum CONSTRUCTOR_NAME = "__ctor"; 
    1896     enum WITH_BASE_CLASS  = __traits(compiles, Policy.BASE_CLASS_ID); 
    1897  
    1898     // Returns a tuple consisting of 0,1,2,...,n-1.  For static foreach. 
    1899     template CountUp(size_t n) 
    1900     { 
    1901         static if (n > 0) 
    1902             alias TypeTuple!(CountUp!(n - 1), n - 1) CountUp; 
    1903         else 
    1904             alias TypeTuple!() CountUp; 
    1905     } 
    1906  
    1907  
    1908     //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::// 
    1909     // Code generator 
    1910     //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::// 
    1911  
    1912     /* 
    1913      * Runs through all the target overload sets and generates D code which 
    1914      * implements all the functions in the overload sets. 
    1915      */ 
    1916     public string generateCode(overloads...)() @property 
    1917     { 
    1918         string code = ""; 
    1919  
    1920         // run through all the overload sets 
    1921         foreach (i_; CountUp!(0 + overloads.length)) // workaround 
    1922         { 
    1923             enum i = 0 + i_; // workaround 
    1924             alias overloads[i] oset; 
    1925  
    1926             code ~= generateCodeForOverloadSet!(oset); 
    1927  
    1928             static if (WITH_BASE_CLASS && oset.name != CONSTRUCTOR_NAME) 
    1929             { 
    1930                 // The generated function declarations may hide existing ones 
    1931                 // in the base class (cf. HiddenFuncError), so we put an alias 
    1932                 // declaration here to reveal possible hidden functions. 
    1933                 code ~= Format!("alias %s.%s %s;\n", 
    1934                             Policy.BASE_CLASS_ID, // [BUG 2540] super. 
    1935                             oset.name, oset.name ); 
    1936             } 
    1937         } 
    1938         return code; 
    1939     } 
    1940  
    1941     // handle each overload set 
    1942     private string generateCodeForOverloadSet(alias oset)() @property 
    1943     { 
    1944         string code = ""; 
    1945  
    1946         foreach (i_; CountUp!(0 + oset.contents.length)) // workaround 
    1947         { 
    1948             enum i = 0 + i_; // workaround 
    1949             code ~= generateFunction!( 
    1950                     oset.contents[i], Policy.FUNCINFO_ID!(oset.name, i)) ~ "\n"; 
    1951         } 
    1952         return code; 
    1953     } 
    1954  
    1955     /* 
    1956      * Returns D code which implements the function func.  This function 
    1957      * actually generates only the declarator part; the function body part is 
    1958      * generated by the functionGenerator() policy. 
    1959      */ 
    1960     //private string generateFunction(alias func, string myFuncInfo)() @property 
    1961     private string generateFunction(args_.../+[BUG 4217]+/)() @property 
    1962     { 
    1963         alias args_[0..1] func; enum myFuncInfo = args_[1]; 
    1964  
    1965         enum name   = __traits(identifier, func); 
    1966         enum isCtor = (name == CONSTRUCTOR_NAME); 
    1967  
    1968         string code; // the result 
    1969  
    1970         /*** Function Declarator ***/ 
    1971         { 
    1972             alias FunctionAttribute FA; 
    1973             enum atts     = functionAttributes!(func); 
    1974             enum realName = isCtor ? "this" : name; 
    1975  
    1976             /* Just for the sake of Format!(...). */ 
    1977             static string make_postAtts() 
    1978             { 
    1979                 string poatts = ""; 
    1980                 if (atts & FA.PURE    ) poatts ~= " pure"; 
    1981                 if (atts & FA.NOTHROW ) poatts ~= " nothrow"; 
    1982                 if (atts & FA.PROPERTY) poatts ~= " @property"; 
    1983                 if (atts & FA.SAFE    ) poatts ~= " @safe"; 
    1984                 if (atts & FA.TRUSTED ) poatts ~= " @trusted"; 
    1985                 return poatts; 
    1986             } 
    1987             enum postAtts = make_postAtts(); 
    1988  
    1989             static string make_returnType() 
    1990             { 
    1991                 string rtype = ""; 
    1992  
    1993                 if (!isCtor) 
    1994                 { 
    1995                     if (atts & FA.REF) rtype ~= "ret "; 
    1996                     rtype ~= myFuncInfo ~ ".RT"; 
    1997                 } 
    1998                 return rtype; 
    1999             } 
    2000             enum returnType = make_returnType(); 
    2001  
    2002             // 
    2003             code ~= Format!("extern(%s) %s %s(%s) %s\n", 
    2004                     functionLinkage!(func), 
    2005                     returnType, 
    2006                     realName, 
    2007                     ""~generateParameters!(func, myFuncInfo), 
    2008                     postAtts ); 
    2009         } 
    2010  
    2011         /*** Function Body ***/ 
    2012         code ~= "{\n"; 
    2013         { 
    2014             enum nparams = ParameterTypeTuple!(func).length; 
    2015  
    2016             /* Declare keywords: args, self and parent. */ 
    2017             string preamble; 
    2018  
    2019             preamble ~= "alias TypeTuple!(" ~ enumerateParameters!(nparams) ~ ") args;\n"; 
    2020             if (!isCtor) 
    2021             { 
    2022                 preamble ~= "alias " ~ name ~ " self;\n"; 
    2023                 if (WITH_BASE_CLASS && !__traits(isAbstractFunction, func)) 
    2024                     //preamble ~= "alias super." ~ name ~ " parent;\n"; // [BUG 2540] 
    2025                     preamble ~= "auto parent = &super." ~ name ~ ";\n"; 
    2026             } 
    2027  
    2028             // 
    2029             code ~= preamble; 
    2030             code ~= Policy.generateFunctionBody!(func); 
    2031         } 
    2032         code ~= "}"; 
    2033  
    2034         return code; 
    2035     } 
    2036  
    2037     /* 
    2038      * Returns D code which declares function parameters. 
    2039      * "ref int a0, real a1, ..." 
    2040      */ 
    2041     //private string generateParameters(alias func, string myFuncInfo)() @property 
    2042     private string generateParameters(args_.../+[BUG 4217]+/)() @property 
    2043     { 
    2044         alias args_[0..1] func; enum myFuncInfo = args_[1]; 
    2045  
    2046         alias ParameterStorageClass STC; 
    2047         alias ParameterStorageClassTuple!(func) stcs; 
    2048         enum nparams = stcs.length; 
    2049  
    2050         string params = ""; // the result 
    2051  
    2052         foreach (i, stc; stcs) 
    2053         { 
    2054             if (i > 0) params ~= ", "; 
    2055  
    2056             // Parameter storage classes. 
    2057             if (stc & STC.SCOPE) params ~= "scope "; 
    2058             if (stc & STC.OUT  ) params ~= "out "; 
    2059             if (stc & STC.REF  ) params ~= "ref "; 
    2060             if (stc & STC.LAZY ) params ~= "lazy "; 
    2061  
    2062             // Take parameter type from the FuncInfo. 
    2063             params ~= myFuncInfo ~ ".PT[" ~ toStringNow!(i) ~ "]"; 
    2064  
    2065             // Declare a parameter variable. 
    2066             params ~= " " ~ Policy.PARAMETER_VARIABLE_ID!(i); 
    2067         } 
    2068  
    2069         // Add some ellipsis part if needed. 
    2070         final switch (variadicFunctionStyle!(func)) 
    2071         { 
    2072             case Variadic.NO: 
    2073                 break; 
    2074  
    2075             case Variadic.C, Variadic.D: 
    2076                 // (...) or (a, b, ...) 
    2077                 params ~= (nparams == 0) ? "..." : ", ..."; 
    2078                 break; 
    2079  
    2080             case Variadic.TYPESAFE: 
    2081                 params ~= " ..."; 
    2082                 break; 
    2083         } 
    2084  
    2085         return params; 
    2086     } 
    2087  
    2088     // Returns D code which enumerates n parameter variables using comma as the 
    2089     // separator.  "a0, a1, a2, a3" 
    2090     private string enumerateParameters(size_t n)() @property 
    2091     { 
    2092         string params = ""; 
    2093  
    2094         foreach (i_; CountUp!(n)) 
    2095         { 
    2096             enum i = 0 + i_; // workaround 
    2097             if (i > 0) params ~= ", "; 
    2098             params ~= Policy.PARAMETER_VARIABLE_ID!(i); 
    2099         } 
    2100         return params; 
    2101     } 
    2102 }