What you want, but have never been able to put into words, is a "two-phase" C compiler. You want compile-time C code that outputs run-time C code.
Example: Factorial function.
Naive C approach:
int factorial(int n)
{
int i, x = 1;
for (i = 2; i <= n; ++i) x *= i;
return x;
}
Realization - This code is inefficient and pointless. On 32-bit systems, passing anything larger than 12 into this function will fail. Even with 64-bit integers, the largest acceptable value is 20.
Problem - The optimized function is less readable. Calculating a factorial is a repetitive process by its nature, and we have obfuscated that for the sake of efficiency. Further, we had to spend our precious time calculating the results for every possible input. This would be unacceptable for most functions.
Solution - The "Two-Phase C" approach:
out <<END_TEXT
int factorial(int n)
{
int f[] =
{
1
END_TEXT
int i, j = 1;
for (i = 1; i <= 12; i++)
{
out ",";
j *= i;
out j;
}
out <<END_TEXT
};
return f[n];
}
END_TEXT
Obviously, the output of this "first-phase C" code is the "optimized C approach," shown above. It is now explicit to the maintainer of the code how the factorial is being calculated, even though no factorial calculation needs to be performed at run-time. Congratulations.
Show me a situation where this works for anything useful and I'll consider it. As is, this is just an obfuscated way to say ``if you write code that has a tiny number of inputs and which does not depend on run time, you might as well precompute it!''. Sepples already does this.
In practice, nobody would ever use that factorial function, precisely because it doesn't work for large numbers. So if you really cared about factorials, you'd be using gmp or something. Assuming that libraries work with this approach, you can't generate an array for all representable factorials at compile time, and if you did I would hate you, since you would be throwing pointless shit into my .data that I'm probably never going to use. The answer is to either precompute all possible output value or write a better algorithm in the first place, and I can do either one of those things without being cute and adding layers of abstraction.
Furthermore, your goddamn Two Phase factorial example is idiotic. It's less clear than simply declaring the array to begin with, especially since it's bending over backwards to pretend it's C in the first place, which makes it blend in with the output it's trying to give. Fuck you, if I want to use that approach I'd use Perl or Lisp or some other text-shuffling language that could be easily taught to tokenize and refactor C.
>>6 IHBT
Absorutery. It should have been obvious at at least one point: Problem - The optimized function is less readable.
It's not. As long as the function name is factorial it's obvious what it does.
For me it was at least a little fun fiddling around with TCC but what's your excuse for replying?
>>6 Show me a situation where this works for anything useful and I'll consider it.
Whatever approach/language it is that you use, if you don't understand the need to perform calculations at compile-time, then you're in the wrong... oh, no, wait, you're in exactly the right place. Carry on.
Would you guys recommend the old Kamen Rider shows (i.e., unhandsome Riders, I suppose), or old Super Sentai series? I thought about just watching some of the newer ones, but then I figured I might as well also watch something a little older.
Name:
Anonymous2013-08-31 7:52
That's right; I'm BREAKING the NYPA trend and i'll be your PA! Of course, i'd appreciate others to participate in the thread as well.
Name:
Anonymous2013-08-31 8:38
You can refactor in Haskell a lot. The types ensure your large scale changes will be safe, if you're using types wisely. This will help your codebase scale. Make sure that your refactorings will cause type errors until complete.