Source

gdc / gdc.test / compilable / 99bottles.d

Full commit
// { dg-prune-output .* }

// written by Don Clugston:
//    http://www.digitalmars.com/d/archives/digitalmars/D/announce/4374.html
//    http://www.99-bottles-of-beer.net/language-d-1212.html

// Displays the "99 bottles of beer" song at compile time,
// using the template metaprograming facilities of D. 
// No executable is generated. No libraries are used.
// Illustrates template default values, template string value parameters,
// compile-time concatenation of constant strings, static if.

module bottles99;

template decimaldigit(int n) {
    const string decimaldigit = "0123456789"[n..n+1];
}

template itoa(ulong n)
{
    static if ( n < 10L )
	const string itoa = decimaldigit!(n);
    else
	const string itoa = itoa!( n / 10L ) ~ decimaldigit!( n % 10L );
}

template showHowMany(int n, string where, bool needcapital = false)
{
  static if ( n > 1 ) 
      const string showHowMany = itoa!(n) ~ " bottles of beer" ~ where ~ "\n";
  else static if ( n == 1 )
      const string showHowMany = "1 bottle of beer" ~ where ~ "\n";
  else static if ( needcapital )
      const string showHowMany = "No more bottles of beer" ~ where ~ "\n";
  else 
      const string showHowMany = "no more bottles of beer" ~ where ~ "\n";
}

template beer(int maxbeers, int n = maxbeers)
{
  static if ( n > 0 )
    const string beer = showHowMany!(n, " on the wall,", true)
        ~ showHowMany!(n, ".")
        ~ "Take one down and pass it around, " ~ "\n" 
        ~ showHowMany!( n - 1 , " on the wall.") 
        ~ "\n" ~ beer!(maxbeers, n - 1); // recurse for subsequent verses.
  else
    const string beer = showHowMany!(n, " on the wall,", true)
        ~ showHowMany!(n, ".")
        ~ "Go to the store and buy some more, " ~ "\n"
        ~ showHowMany!( maxbeers, " on the wall.");
}

pragma(msg, beer!(99));