Changeset 1561
- Timestamp:
- 05/26/10 14:22:06 (15 years ago)
- Files:
-
- trunk/phobos/std/functional.d (modified) (2 diffs)
- trunk/phobos/std/traits.d (modified) (1 diff)
- trunk/phobos/std/typecons.d (modified) (5 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
trunk/phobos/std/functional.d
r1556 r1561 507 507 // assert(compose!(baz, `to!(int)(a) + 1`, foo)(1) == 2.5); 508 508 // assert(compose!(baz, bar)("1"[]) == 2.5); 509 509 510 510 // @@@BUG@@@ 511 511 //assert(compose!(baz, bar)("1") == 2.5); 512 512 513 513 // @@@BUG@@@ 514 514 //assert(compose!(`a + 0.5`, `to!(int)(a) + 1`, foo)(1) == 2.5); 515 515 } 516 516 517 private struct DelegateFaker(R, Args...) { 518 R doIt(Args args) { 519 // When this function gets called, the this pointer isn't really a 520 // this pointer (no instance even really exists), but a function 521 // pointer that points to the function 522 // to be called. Cast it to the correct type and call it. 523 524 auto fp = cast(R function(Args)) &this; 525 return fp(args); 526 } 517 private struct DelegateFaker(F) { 518 /* 519 * What all the stuff below does is this: 520 *-------------------- 521 * struct DelegateFaker(F) { 522 * extern(linkage) 523 * [ref] ReturnType!F doIt(ParameterTypeTuple!F args) [@attributes] 524 * { 525 * auto fp = cast(F) &this; 526 * return fp(args); 527 * } 528 * } 529 *-------------------- 530 */ 531 532 // We will use MemberFunctionGenerator in std.typecons. This is a policy 533 // configuration for generating the doIt(). 534 template GeneratingPolicy() 535 { 536 // Inform the genereator that we only have type information. 537 enum WITHOUT_SYMBOL = true; 538 539 // Generate the function body of doIt(). 540 template generateFunctionBody(unused...) 541 { 542 enum generateFunctionBody = 543 // [ref] ReturnType doIt(ParameterTypeTuple args) @attributes 544 q{ 545 // When this function gets called, the this pointer isn't 546 // really a this pointer (no instance even really exists), but 547 // a function pointer that points to the function to be called. 548 // Cast it to the correct type and call it. 549 550 auto fp = cast(F) &this; // XXX doesn't work with @safe 551 return fp(args); 552 }; 553 } 554 } 555 // Type information used by the generated code. 556 alias FuncInfo!(F) FuncInfo_doIt; 557 558 // Generate the member function doIt(). 559 mixin( std.typecons.MemberFunctionGenerator!(GeneratingPolicy!()) 560 .generateFunction!("FuncInfo_doIt", "doIt", F) ); 527 561 } 528 562 529 563 /**Convert a callable to a delegate with the same parameter list and 530 564 * return type, avoiding heap allocations and use of auxiliary storage. 531 565 * 532 566 * Examples: 533 567 * --- 534 568 * void doStuff() { 535 569 * writeln("Hello, world."); 536 570 * } 537 571 * 538 572 * void runDelegate(void delegate() myDelegate) { 539 573 * myDelegate(); 540 574 * } 541 575 * 542 576 * auto delegateToPass = toDelegate(&doStuff); 543 577 * runDelegate(delegateToPass); // Calls doStuff, prints "Hello, world." 544 578 * --- 545 579 * 546 * Bugs: Doesn't work properly with ref return. (See DMD bug 3756.) 580 * BUGS: 581 * $(UL 582 * $(LI Does not work with $(D @safe) functions.) 583 * $(LI Ignores C-style / D-style variadic arguments.) 584 * ) 547 585 */ 548 586 auto toDelegate(F)(auto ref F fp) if (isCallable!(F)) { 549 587 550 588 static if (is(F == delegate)) 551 589 { 552 590 return fp; 553 591 } 554 592 else static if (is(typeof(&F.opCall) == delegate) 555 593 || (is(typeof(&F.opCall) V : V*) && is(V == function))) 556 594 { 557 595 return toDelegate(&fp.opCall); 558 596 } 559 597 else 560 598 { 561 // Workaround for DMD Bug 1818. 562 mixin("alias " ~ ReturnType!(F).stringof ~ 563 " delegate" ~ ParameterTypeTuple!(F).stringof ~ " DelType;"); 564 565 version(none) { 566 // What the code would be if it weren't for bug 1818: 567 alias ReturnType!(F) delegate(ParameterTypeTuple!(F)) DelType; 568 } 599 alias typeof(&(new DelegateFaker!(F)).doIt) DelType; 569 600 570 601 static struct DelegateFields { 571 602 union { 572 603 DelType del; 573 604 //pragma(msg, typeof(del)); 574 605 575 606 struct { 576 607 void* contextPtr; 577 608 void* funcPtr; 578 609 } 579 610 } 580 611 } 581 612 582 613 // fp is stored in the returned delegate's context pointer. 583 614 // The returned delegate's function pointer points to 584 615 // DelegateFaker.doIt. 585 616 DelegateFields df; 586 617 587 618 df.contextPtr = cast(void*) fp; 588 619 589 DelegateFaker!( ReturnType!(F), ParameterTypeTuple!(F)) dummy;620 DelegateFaker!(F) dummy; 590 621 auto dummyDel = &(dummy.doIt); 591 622 df.funcPtr = dummyDel.funcptr; 592 623 593 624 return df.del; 594 625 } 595 626 } 596 627 597 628 unittest { 598 629 static int inc(ref uint num) { 599 630 num++; … … 621 652 static assert(!is(typeof(&s1.opCall) == delegate)); 622 653 S1 s1; 623 654 auto getvals1 = toDelegate(s1); 624 655 assert(getvals1() == 4); 625 656 626 657 struct S2 { static int opCall() { return 123456; } } 627 658 static assert(!is(typeof(&S2.opCall) == delegate)); 628 659 S2 s2; 629 660 auto getvals2 =&S2.opCall; 630 661 assert(getvals2() == 123456); 631 } 662 663 /* test for attributes */ 664 { 665 static int refvar = 0xDeadFace; 666 667 static ref int func_ref() { return refvar; } 668 static int func_pure() pure { return 1; } 669 static int func_nothrow() nothrow { return 2; } 670 static int func_property() @property { return 3; } 671 static int func_safe() @safe { return 4; } 672 static int func_trusted() @trusted { return 5; } 673 static int func_system() @system { return 6; } 674 static int func_pure_nothrow() pure nothrow { return 7; } 675 static int func_pure_nothrow_safe() pure @safe { return 8; } 676 677 auto dg_ref = toDelegate(&func_ref); 678 auto dg_pure = toDelegate(&func_pure); 679 auto dg_nothrow = toDelegate(&func_nothrow); 680 auto dg_property = toDelegate(&func_property); 681 //auto dg_safe = toDelegate(&func_safe); 682 auto dg_trusted = toDelegate(&func_trusted); 683 auto dg_system = toDelegate(&func_system); 684 auto dg_pure_nothrow = toDelegate(&func_pure_nothrow); 685 //auto dg_pure_nothrow_safe = toDelegate(&func_pure_nothrow_safe); 686 687 //static assert(is(typeof(dg_ref) == ref int delegate())); // [BUG@DMD] 688 static assert(is(typeof(dg_pure) == int delegate() pure)); 689 static assert(is(typeof(dg_nothrow) == int delegate() nothrow)); 690 static assert(is(typeof(dg_property) == int delegate() @property)); 691 //static assert(is(typeof(dg_safe) == int delegate() @safe)); 692 static assert(is(typeof(dg_trusted) == int delegate() @trusted)); 693 static assert(is(typeof(dg_system) == int delegate() @system)); 694 static assert(is(typeof(dg_pure_nothrow) == int delegate() pure nothrow)); 695 //static assert(is(typeof(dg_pure_nothrow_safe) == int delegate() pure nothrow @safe)); 696 697 assert(dg_ref() == refvar); 698 assert(dg_pure() == 1); 699 assert(dg_nothrow() == 2); 700 assert(dg_property() == 3); 701 //assert(dg_safe() == 4); 702 assert(dg_trusted() == 5); 703 assert(dg_system() == 6); 704 assert(dg_pure_nothrow() == 7); 705 //assert(dg_pure_nothrow_safe() == 8); 706 } 707 /* test for linkage */ 708 { 709 struct S 710 { 711 extern(C) static void xtrnC() {} 712 extern(D) static void xtrnD() {} 713 } 714 auto dg_xtrnC = toDelegate(&S.xtrnC); 715 auto dg_xtrnD = toDelegate(&S.xtrnD); 716 static assert(! is(typeof(dg_xtrnC) == typeof(dg_xtrnD))); 717 } 718 } trunk/phobos/std/traits.d
r1551 r1561 2014 2014 static assert(isTypeTuple!(typeof(func))); 2015 2015 static assert(isTypeTuple!(int, char, double)); 2016 2016 2017 2017 static assert(! isTypeTuple!(c)); 2018 2018 static assert(! isTypeTuple!(isTypeTuple)); 2019 2019 static assert(! isTypeTuple!(CONST)); 2020 2020 } 2021 2021 2022 2022 2023 2023 /** 2024 Detect whether symbol or type $(D T) is a function pointer. 2025 */ 2026 template isFunctionPointer(T...) 2027 if (T.length == 1) 2028 { 2029 static if (is(T[0] U) || is(typeof(T[0]) U)) 2030 { 2031 static if (is(U F : F*) && is(F == function)) 2032 enum bool isFunctionPointer = true; 2033 else 2034 enum bool isFunctionPointer = false; 2035 } 2036 else 2037 enum bool isFunctionPointer = false; 2038 } 2039 2040 unittest 2041 { 2042 static void foo() {} 2043 void bar() {} 2044 2045 auto fpfoo = &foo; 2046 static assert(isFunctionPointer!(fpfoo)); 2047 static assert(isFunctionPointer!(void function())); 2048 2049 auto dgbar = &bar; 2050 static assert(! isFunctionPointer!(dgbar)); 2051 static assert(! isFunctionPointer!(void delegate())); 2052 static assert(! isFunctionPointer!(foo)); 2053 static assert(! isFunctionPointer!(bar)); 2054 } 2055 2056 2057 /** 2024 2058 Detect whether symbol or type $(D T) is a function, a function pointer or a delegate. 2025 2059 */ 2026 2060 template isSomeFunction(T...) 2027 2061 if (T.length == 1) 2028 2062 { 2029 2063 static if (is(typeof(& T[0]) U : U*) && is(U == function)) 2030 2064 { 2031 2065 // T is a function symbol. 2032 2066 enum bool isSomeFunction = true; 2033 2067 } trunk/phobos/std/typecons.d
r1554 r1561 1529 1529 } 1530 1530 1531 1531 1532 1532 /** 1533 1533 $(D AutoImplement) automatically implements (by default) all abstract member 1534 1534 functions in the class or interface $(D Base) in specified way. 1535 1535 1536 1536 Params: 1537 1537 how = template which specifies _how functions will be implemented/overridden. 1538 1538 1539 Two arguments are passed to $(D how): the first one is the $(D Base),1540 and the second one is an alias to a function to be implemented. Then1541 $(D how) must return a implementedfunction body as a string.1539 Two arguments are passed to $(D how): the type $(D Base) and an alias 1540 to an implemented function. Then $(D how) must return an implemented 1541 function body as a string. 1542 1542 1543 1543 The generated function body can use these keywords: 1544 1544 $(UL 1545 1545 $(LI $(D a0), $(D a1), …: arguments passed to the function;) 1546 1546 $(LI $(D args): a tuple of the arguments;) 1547 1547 $(LI $(D self): an alias to the function itself;) 1548 1548 $(LI $(D parent): an alias to the overridden function (if any).) 1549 1549 ) 1550 1550 1551 1551 You may want to use templated property functions (instead of Implicit … … 1766 1766 { 1767 1767 // base class identifier which generated code should use 1768 1768 enum string BASE_CLASS_ID = baseName; 1769 1769 1770 1770 // FuncInfo instance identifier which generated code should use 1771 1771 template FUNCINFO_ID(string name, size_t i) 1772 1772 { 1773 1773 enum string FUNCINFO_ID = 1774 1774 myName ~ "." ~ INTERNAL_FUNCINFO_ID!(name, i); 1775 1775 } 1776 1777 // preferred identifier for i-th parameter variable1778 template PARAMETER_VARIABLE_ID(size_t i)1779 {1780 enum string PARAMETER_VARIABLE_ID = "a" ~ toStringNow!(i);1781 }1782 1776 } 1783 1777 1784 1778 /* Policy configurations for generating constructors. */ 1785 1779 template ConstructorGeneratingPolicy() 1786 1780 { 1787 1781 mixin CommonGeneratingPolicy; 1788 1782 1789 1783 /* Generates constructor body. Just forward to the base class' one. */ 1790 1784 string generateFunctionBody(ctor.../+[BUG 4217]+/)() @property 1791 1785 { … … 1871 1865 static class C_6 1872 1866 { 1873 1867 this(int n) { assert(n == 42); } 1874 1868 this(string s) { assert(s == "Deeee"); } 1875 1869 this(...) {} 1876 1870 } 1877 1871 auto o1 = new BlackHole!C_6(42); 1878 1872 auto o2 = new BlackHole!C_6("Deeee"); 1879 1873 auto o3 = new BlackHole!C_6(1, 2, 3, 4); 1880 1874 } 1875 // attributes 1876 { 1877 interface I_7 1878 { 1879 ref int test_ref(); 1880 int test_pure() pure; 1881 int test_nothrow() nothrow; 1882 int test_property() @property; 1883 int test_safe() @safe; 1884 int test_trusted() @trusted; 1885 int test_system() @system; 1886 int test_pure_nothrow() pure nothrow; 1887 } 1888 auto o = new BlackHole!I_7; 1889 } 1890 // storage classes 1891 { 1892 interface I_8 1893 { 1894 void test_const() const; 1895 void test_immutable() immutable; 1896 void test_shared() shared; 1897 void test_shared_const() shared const; 1898 } 1899 auto o = new BlackHole!I_8; 1900 } 1881 1901 /+ // deep inheritance 1882 1902 { 1883 1903 // XXX [BUG 2525,3525] 1884 1904 // NOTE: [r494] func.c(504-571) FuncDeclaration::semantic() 1885 1905 interface I { void foo(); } 1886 1906 interface J : I {} 1887 1907 interface K : J {} 1888 static abstract class C_ 8: K {}1889 auto o = new BlackHole!C_ 8;1908 static abstract class C_9 : K {} 1909 auto o = new BlackHole!C_9; 1890 1910 }+/ 1891 1911 } 1892 1912 1893 1913 1894 1914 /* 1895 1915 Used by MemberFunctionGenerator. 1896 1916 */ 1897 p rivate template OverloadSet(string nam, T...)1917 package template OverloadSet(string nam, T...) 1898 1918 { 1899 1919 enum string name = nam; 1900 1920 alias T contents; 1901 1921 } 1902 1922 1903 1923 /* 1904 1924 Used by MemberFunctionGenerator. 1905 1925 */ 1906 p rivate template FuncInfo(alias func, /+[BUG 4217 ?]+/ T = typeof(&func))1926 package template FuncInfo(alias func, /+[BUG 4217 ?]+/ T = typeof(&func)) 1907 1927 { 1908 1928 alias ReturnType!(T) RT; 1909 1929 alias ParameterTypeTuple!(T) PT; 1910 1930 } 1931 package template FuncInfo(Func) 1932 { 1933 alias ReturnType!(Func) RT; 1934 alias ParameterTypeTuple!(Func) PT; 1935 } 1911 1936 1912 1937 /* 1913 1938 General-purpose member function generator. 1914 */ 1915 private template MemberFunctionGenerator(alias Policy) 1939 -------------------- 1940 template GeneratingPolicy() 1941 { 1942 // [optional] the name of the class where functions are derived 1943 enum string BASE_CLASS_ID; 1944 1945 // [optional] define this if you have only function types 1946 enum bool WITHOUT_SYMBOL; 1947 1948 // [optional] Returns preferred identifier for i-th parameter. 1949 template PARAMETER_VARIABLE_ID(size_t i); 1950 1951 // Returns the identifier of the FuncInfo instance for the i-th overload 1952 // of the specified name. The identifier must be accessible in the scope 1953 // where generated code is mixed. 1954 template FUNCINFO_ID(string name, size_t i); 1955 1956 // Returns implemented function body as a string. When WITHOUT_SYMBOL is 1957 // defined, the latter is used. 1958 template generateFunctionBody(alias func); 1959 template generateFunctionBody(string name, FuncType); 1960 } 1961 -------------------- 1962 */ 1963 package template MemberFunctionGenerator(alias Policy) 1916 1964 { 1917 1965 private static: 1918 //mixin Policy; // can't1919 1920 1966 //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::// 1921 1967 // Internal stuffs 1922 1968 //::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::// 1923 1969 1924 1970 enum CONSTRUCTOR_NAME = "__ctor"; 1925 enum WITH_BASE_CLASS = __traits(compiles, Policy.BASE_CLASS_ID); 1971 1972 // true if functions are derived from a base class 1973 enum WITH_BASE_CLASS = __traits(hasMember, Policy, "BASE_CLASS_ID"); 1974 1975 // true if functions are specified as types, not symbols 1976 enum WITHOUT_SYMBOL = __traits(hasMember, Policy, "WITHOUT_SYMBOL"); 1977 1978 // preferred identifier for i-th parameter variable 1979 static if (__traits(hasMember, Policy, "PARAMETER_VARIABLE_ID")) 1980 { 1981 alias Policy.PARAMETER_VARIABLE_ID PARAMETER_VARIABLE_ID; 1982 } 1983 else 1984 { 1985 template PARAMETER_VARIABLE_ID(size_t i) 1986 { 1987 enum string PARAMETER_VARIABLE_ID = "a" ~ toStringNow!(i); 1988 // default: a0, a1, ... 1989 } 1990 } 1926 1991 1927 1992 // Returns a tuple consisting of 0,1,2,...,n-1. For static foreach. 1928 1993 template CountUp(size_t n) 1929 1994 { 1930 1995 static if (n > 0) 1931 1996 alias TypeTuple!(CountUp!(n - 1), n - 1) CountUp; 1932 1997 else 1933 1998 alias TypeTuple!() CountUp; 1934 1999 } 1935 2000 … … 1969 2034 1970 2035 // handle each overload set 1971 2036 private string generateCodeForOverloadSet(alias oset)() @property 1972 2037 { 1973 2038 string code = ""; 1974 2039 1975 2040 foreach (i_; CountUp!(0 + oset.contents.length)) // workaround 1976 2041 { 1977 2042 enum i = 0 + i_; // workaround 1978 2043 code ~= generateFunction!( 1979 oset.contents[i], Policy.FUNCINFO_ID!(oset.name, i)) ~ "\n"; 2044 Policy.FUNCINFO_ID!(oset.name, i), oset.name, 2045 oset.contents[i]) ~ "\n"; 1980 2046 } 1981 2047 return code; 1982 2048 } 1983 2049 1984 2050 /* 1985 2051 * Returns D code which implements the function func. This function 1986 2052 * actually generates only the declarator part; the function body part is 1987 2053 * generated by the functionGenerator() policy. 1988 2054 */ 1989 //private string generateFunction(alias func, string myFuncInfo)() @property 1990 private string generateFunction(args_.../+[BUG 4217]+/)() @property 1991 { 1992 alias args_[0..1] func; enum myFuncInfo = args_[1]; 1993 1994 enum name = __traits(identifier, func); 2055 public string generateFunction( 2056 string myFuncInfo, string name, func... )() @property 2057 { 1995 2058 enum isCtor = (name == CONSTRUCTOR_NAME); 1996 2059 1997 2060 string code; // the result 1998 2061 1999 2062 /*** Function Declarator ***/ 2000 2063 { 2064 alias FunctionTypeOf!(func) Func; 2001 2065 alias FunctionAttribute FA; 2002 2066 enum atts = functionAttributes!(func); 2003 2067 enum realName = isCtor ? "this" : name; 2004 2068 2005 /* Just for the sake of Format!(...). */ 2069 /* Made them CTFE funcs just for the sake of Format!(...) */ 2070 2071 // return type with optional "ref" 2072 static string make_returnType() 2073 { 2074 string rtype = ""; 2075 2076 if (!isCtor) 2077 { 2078 if (atts & FA.REF) rtype ~= "ref "; 2079 rtype ~= myFuncInfo ~ ".RT"; 2080 } 2081 return rtype; 2082 } 2083 enum returnType = make_returnType(); 2084 2085 // function attributes attached after declaration 2006 2086 static string make_postAtts() 2007 2087 { 2008 2088 string poatts = ""; 2009 2089 if (atts & FA.PURE ) poatts ~= " pure"; 2010 2090 if (atts & FA.NOTHROW ) poatts ~= " nothrow"; 2011 2091 if (atts & FA.PROPERTY) poatts ~= " @property"; 2012 2092 if (atts & FA.SAFE ) poatts ~= " @safe"; 2013 2093 if (atts & FA.TRUSTED ) poatts ~= " @trusted"; 2014 2094 return poatts; 2015 2095 } 2016 2096 enum postAtts = make_postAtts(); 2017 2097 2018 static string make_returnType() 2098 // function storage class 2099 static string make_storageClass() 2019 2100 { 2020 string rtype = ""; 2021 2022 if (!isCtor) 2023 { 2024 if (atts & FA.REF) rtype ~= "ret "; 2025 rtype ~= myFuncInfo ~ ".RT"; 2026 } 2027 return rtype; 2101 string postc = ""; 2102 if (is(Func == shared)) postc ~= " shared"; 2103 if (is(Func == const)) postc ~= " const"; 2104 if (is(Func == immutable)) postc ~= " immutable"; 2105 return postc; 2028 2106 } 2029 enum returnType = make_returnType();2107 enum storageClass = make_storageClass(); 2030 2108 2031 2109 // 2032 code ~= Format!("extern(%s) %s %s(%s) %s \n",2110 code ~= Format!("extern(%s) %s %s(%s) %s %s\n", 2033 2111 functionLinkage!(func), 2034 2112 returnType, 2035 2113 realName, 2036 ""~generateParameters!( func, myFuncInfo),2037 postAtts );2114 ""~generateParameters!(myFuncInfo, func), 2115 postAtts, storageClass ); 2038 2116 } 2039 2117 2040 2118 /*** Function Body ***/ 2041 2119 code ~= "{\n"; 2042 2120 { 2043 2121 enum nparams = ParameterTypeTuple!(func).length; 2044 2122 2045 2123 /* Declare keywords: args, self and parent. */ 2046 2124 string preamble; 2047 2125 2048 2126 preamble ~= "alias TypeTuple!(" ~ enumerateParameters!(nparams) ~ ") args;\n"; 2049 2127 if (!isCtor) 2050 2128 { 2051 2129 preamble ~= "alias " ~ name ~ " self;\n"; 2052 2130 if (WITH_BASE_CLASS && !__traits(isAbstractFunction, func)) 2053 2131 //preamble ~= "alias super." ~ name ~ " parent;\n"; // [BUG 2540] 2054 2132 preamble ~= "auto parent = &super." ~ name ~ ";\n"; 2055 2133 } 2056 2134 2057 // 2135 // Function body 2136 static if (WITHOUT_SYMBOL) 2137 enum fbody = Policy.generateFunctionBody!(name, func); 2138 else 2139 enum fbody = Policy.generateFunctionBody!(func); 2140 2058 2141 code ~= preamble; 2059 code ~= Policy.generateFunctionBody!(func);2142 code ~= fbody; 2060 2143 } 2061 2144 code ~= "}"; 2062 2145 2063 2146 return code; 2064 2147 } 2065 2148 2066 2149 /* 2067 2150 * Returns D code which declares function parameters. 2068 2151 * "ref int a0, real a1, ..." 2069 2152 */ 2070 //private string generateParameters(alias func, string myFuncInfo)() @property 2071 private string generateParameters(args_.../+[BUG 4217]+/)() @property 2072 { 2073 alias args_[0..1] func; enum myFuncInfo = args_[1]; 2074 2153 private string generateParameters(string myFuncInfo, func...)() @property 2154 { 2075 2155 alias ParameterStorageClass STC; 2076 2156 alias ParameterStorageClassTuple!(func) stcs; 2077 2157 enum nparams = stcs.length; 2078 2158 2079 2159 string params = ""; // the result 2080 2160 2081 2161 foreach (i, stc; stcs) 2082 2162 { 2083 2163 if (i > 0) params ~= ", "; 2084 2164 2085 2165 // Parameter storage classes. 2086 2166 if (stc & STC.SCOPE) params ~= "scope "; 2087 2167 if (stc & STC.OUT ) params ~= "out "; 2088 2168 if (stc & STC.REF ) params ~= "ref "; 2089 2169 if (stc & STC.LAZY ) params ~= "lazy "; 2090 2170 2091 2171 // Take parameter type from the FuncInfo. 2092 2172 params ~= myFuncInfo ~ ".PT[" ~ toStringNow!(i) ~ "]"; 2093 2173 2094 2174 // Declare a parameter variable. 2095 params ~= " " ~ P olicy.PARAMETER_VARIABLE_ID!(i);2175 params ~= " " ~ PARAMETER_VARIABLE_ID!(i); 2096 2176 } 2097 2177 2098 2178 // Add some ellipsis part if needed. 2099 2179 final switch (variadicFunctionStyle!(func)) 2100 2180 { 2101 2181 case Variadic.NO: 2102 2182 break; 2103 2183 2104 2184 case Variadic.C, Variadic.D: 2105 2185 // (...) or (a, b, ...) … … 2117 2197 // Returns D code which enumerates n parameter variables using comma as the 2118 2198 // separator. "a0, a1, a2, a3" 2119 2199 private string enumerateParameters(size_t n)() @property 2120 2200 { 2121 2201 string params = ""; 2122 2202 2123 2203 foreach (i_; CountUp!(n)) 2124 2204 { 2125 2205 enum i = 0 + i_; // workaround 2126 2206 if (i > 0) params ~= ", "; 2127 params ~= P olicy.PARAMETER_VARIABLE_ID!(i);2207 params ~= PARAMETER_VARIABLE_ID!(i); 2128 2208 } 2129 2209 return params; 2130 2210 } 2131 2211 } 2132 2212 2133 2213 2134 2214 /** 2135 2215 Predefined how-policies for $(D AutoImplement). These templates are used by 2136 2216 $(D BlackHole) and $(D WhiteHole), respectively. 2137 2217 */
