| 1414 | | The behavior can be customized with the parameters. |
|---|
| | 1416 | See_Also: |
|---|
| | 1417 | AutoImplement, generateEmptyFunction |
|---|
| | 1418 | */ |
|---|
| | 1419 | template BlackHole(Base) |
|---|
| | 1420 | { |
|---|
| | 1421 | alias AutoImplement!(Base, generateEmptyFunction, isAbstractFunction) |
|---|
| | 1422 | BlackHole; |
|---|
| | 1423 | } |
|---|
| | 1424 | |
|---|
| | 1425 | unittest |
|---|
| | 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 |
|---|
| | 1456 | all abstract member functions as throw-always functions. Each auto-implemented |
|---|
| | 1457 | function fails with $(D AsertError) and does never return. Useful for trapping |
|---|
| | 1458 | use of not-yet-implemented functions. |
|---|
| | 1459 | |
|---|
| | 1460 | Example: |
|---|
| | 1461 | -------------------- |
|---|
| | 1462 | class C |
|---|
| | 1463 | { |
|---|
| | 1464 | abstract void notYetImplemented(); |
|---|
| | 1465 | } |
|---|
| | 1466 | |
|---|
| | 1467 | void main() |
|---|
| | 1468 | { |
|---|
| | 1469 | auto c = new WhiteHole!C; |
|---|
| | 1470 | c.notYetImplemented(); // throws AssertError |
|---|
| | 1471 | } |
|---|
| | 1472 | -------------------- |
|---|
| | 1473 | |
|---|
| | 1474 | See_Also: |
|---|
| | 1475 | AutoImplement, generateAssertTrap |
|---|
| | 1476 | */ |
|---|
| | 1477 | template WhiteHole(Base) |
|---|
| | 1478 | { |
|---|
| | 1479 | alias AutoImplement!(Base, generateAssertTrap, isAbstractFunction) |
|---|
| | 1480 | WhiteHole; |
|---|
| | 1481 | } |
|---|
| | 1482 | |
|---|
| | 1483 | unittest |
|---|
| | 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 |
|---|
| | 1505 | functions in the class or interface $(D Base) in specified way. |
|---|
| 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 | /* |
|---|
| | 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 | } |
|---|
| | 2103 | |
|---|
| | 2104 | |
|---|
| | 2105 | /** |
|---|
| | 2106 | Predefined how-policies for $(D AutoImplement). These templates are used by |
|---|
| | 2107 | $(D BlackHole) and $(D WhiteHole), respectively. |
|---|
| 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 | | } |
|---|