Compile-time calculation

From Rosetta Code
Revision as of 14:55, 25 January 2010 by MikeMol (talk | contribs) (minor grammar patch)
Compile-time calculation is a draft programming task. It is not yet considered ready to be promoted as a complete task, for reasons that should be found in its talk page.

Some programming languages allow to calculation of values at compile time. For this task, calculate 10! at compile time. Print the result when the program is run.

Discuss what limitations apply to compile-time calculations in your language.

Warnings:

  • This task is a draft, you can modify it if you find a way to enhance it.

C++

<lang cpp>#include <iostream>

template<int i> struct Fac {

   static const int result = i * Fac<i-1>::result;

};

template<> struct Fac<1> {

   static const int result = 1;

};


int main(int argc, char* argv[]) {

   std::cout << "10! = " << Fac<10>::result << "\n";

}</lang>

Compile-time calculations in C++ look quite different from normal code. We can only use templates, type definitions and a subset of integer arithmetic. It is not possible to use iteration. C++ compile-time programs are similar to programs in pure functional programming languages, albeit with a peculiar syntax.

Oz

<lang oz>functor import

  System Application

prepare

  fun {Fac N}
     {FoldL {List.number 1 N 1} Number.'*' 1}
  end
  Fac10 = {Fac 10}

define

  {System.showInfo "10! = "#Fac10}
  {Application.exit 0}

end</lang>

Code in the prepare section of a functor is executed at compile time. External modules that are used in this code must be imported with a require statement (not shown in this example). Such external functors must have been compiled before the current functor is compiled (ozmake will automatically take care of this).

It is possible to export variables that are defined in the prepare statement. However, such variables must not be stateful entities, e.g. it is not possible to export a cell that was defined at compile time.

Tcl

In Tcl, compilation happens dynamically when required rather than being a separate step. That said, it is possible to use the language's introspection engine to discover what code has been compiled to, making it easy to show that known-constant expressions are compiled to their results. Generating the expression to compile is then simple enough.

Works with: Tcl version 8.5

<lang tcl>proc makeFacExpr n {

   set exp 1
   for {set i 2} {$i <= $n} {incr i} {
       append exp " * $i"
   }
   return "expr \{$exp\}"

} eval [makeFacExpr 10]</lang> How to show that the results were compiled? Like this: <lang tcl>% tcl::unsupported::disassemble script [makeFacExpr 10] ByteCode 0x0x4de10, refCt 1, epoch 3, interp 0x0x31c10 (epoch 3)

 Source "expr {1 * 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10}"
 Cmds 1, src 45, inst 3, litObjs 1, aux 0, stkDepth 1, code/src 0.00
 Commands 1:
     1: pc 0-1, src 0-44
 Command 1: "expr {1 * 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10}"
   (0) push1 0 	# "3628800"
   (2) done 

</lang> As you can see, that expression was transformed into just a push of the results (and an instruction to mark the end of the bytecode segment).