Compile-time calculation: Difference between revisions

From Rosetta Code
Content added Content deleted
m (→‎{{header|Wren}}: Changed to Wren S/H)
 
(37 intermediate revisions by 13 users not shown)
Line 13: Line 13:
=={{header|360 Assembly}}==
=={{header|360 Assembly}}==
First example with the assembler equivalence pseudo instruction (EQU):
First example with the assembler equivalence pseudo instruction (EQU):
<lang 360asm>COMPCALA CSECT
<syntaxhighlight lang="360asm">COMPCALA CSECT
L R1,=A(FACT10) r1=10!
L R1,=A(FACT10) r1=10!
XDECO R1,PG
XDECO R1,PG
Line 19: Line 19:
BR R14 exit
BR R14 exit
FACT10 EQU 10*9*8*7*6*5*4*3*2*1 factorial computation
FACT10 EQU 10*9*8*7*6*5*4*3*2*1 factorial computation
PG DS CL12</lang>
PG DS CL12</syntaxhighlight>
{{out}} in the assembler listing ( 375F00 hexadecimal of 10!)
{{out}} in the assembler listing ( 375F00 hexadecimal of 10!)
<pre>
<pre>
Line 29: Line 29:
</pre>
</pre>
Second example with an assembler macro instruction:
Second example with an assembler macro instruction:
<lang 360asm> MACRO
<syntaxhighlight lang="360asm"> MACRO
&LAB FACT &REG,&N parameters
&LAB FACT &REG,&N parameters
&F SETA 1 f=1
&F SETA 1 f=1
Line 50: Line 50:
PG DS CL12
PG DS CL12
YREGS
YREGS
END COMPCALB</lang>
END COMPCALB</syntaxhighlight>
{{out}} in the assembler listing
{{out}} in the assembler listing
<pre>
<pre>
Line 58: Line 58:
</pre>
</pre>
=={{header|6502 Assembly}}==
=={{header|6502 Assembly}}==
{{works with|ca65 targeting the C-64}}
{{works with|ca65}}


The ca65 cross-assembler supports computing and storing double-word (32-bit) integer values; unfortunately most 8-bit systems have no built-in support for manipulating such values. On Commodore machines, unless you write your own arithmetic routines, you have to use floating point instead of integers for numbers that large; unfortunately the assembler doesn't support generating floating point constants. Nor is there a ROM routine to convert a 32-bit integer to a float, even though there is one to go the other way.
The ca65 cross-assembler supports computing and storing double-word (32-bit) integer values; unfortunately most 6502-based systems have no built-in support for manipulating such values. But the assembler also supports converting them directly to strings, which are easily printed at runtime. So, here's a straightforward implementation. As written, it works for any Commodore 8-bits, but it could be ported to a different 6502 machine just by changing the print loop to use the appropriate output routine for the target system.


<syntaxhighlight lang="6502">; Display the value of 10!, which is precomputed at assembly time
So in this solution the assembler computes the value of 10! and stores it as a 32-bit integer; the runtime code converts that to floating point using ROM routines, dealing with it 16 bits at a time.
; on any Commodore 8-bit.


.ifndef __CBM__
<lang 6502>; Display the value of 10!, which is precomputed at assembly time
.error "Target must be a Commodore system."
;
.endif
fac = $61 ; location of the floating point accumulator used by ROM routines

facsgn = fac+5 ; specific location of the sign byte
; zero-page work pointer
temp = $fb


; ROM routines used
; ROM routines used
chrout = $ffd2
putfac = $aabc ; print out the value in the FAC
givayf = $b391 ; convert 16-bit integer in AY to floating-point value in FAC
fmult = $ba28 ; multiply FAC by float in memory
fadd = $b867 ; add float in memory to FAC
movfm = $bbd4 ; copy FAC to memory


.code
.code
; convert the upper half
ldy tenfactorial+2
lda tenfactorial+3
jsr givayf


lda #<tenfactorial
; and multiply by 65536
lda #<fp65536
sta temp
ldy #>fp65536
lda #>tenfactorial
jsr fmult
sta temp+1
ldy #0

loop:
; stash it
ldx #<fac_copy
lda (temp),y
ldy #>fac_copy
beq done
jsr movfm
jsr chrout
iny

bne loop
; now convert the lower half
done:
ldy tenfactorial
lda tenfactorial+1
jsr givayf

; since it's the bottom half of a larger number
; it may have the high bit set, which will cause the above to
; treat it as negative. If that happened, correct by adding 65536.
lda facsgn
beq ok ; it's positive, so skip the correction

; it's negative, so add 65536
lda #<fp65536
ldy #>fp65536
jsr fadd

ok:
; FAC now has lower half; add our copy of upper half
lda #<fac_copy
ldy #>fac_copy
jsr fadd

; and print out the result
jsr putfac
rts
rts


.data
.data

; 65536 as a float for operations
fp65536: .byte 145,0,0,0,0,0


; the actual value to print
; the actual value to print
tenfactorial: .dword 10*9*8*7*6*5*4*3*2*1
tenfactorial: .byte 13,"10! = ",.string(10*9*8*7*6*5*4*3*2*1),13,0</syntaxhighlight>

.bss
; a place to stash partial results whlie using the FAC for other operations
fac_copy: .res 6</lang>


{{Out}}
{{Out}}
Here's what it looks like when run immediately upon booting a C-64:
<pre>
<pre>
**** COMMODORE 64 BASIC V2 ****
**** COMMODORE 64 BASIC V2 ****
Line 143: Line 110:
READY.
READY.
RUN:
RUN:

3628800
10! = 3628800


READY.</pre>
READY.</pre>
Line 150: Line 118:
VASM allows you to define values using mathematical operators prior to assembly, but you can only do this with constants.
VASM allows you to define values using mathematical operators prior to assembly, but you can only do this with constants.
The following are all valid:
The following are all valid:
<lang 68000devpac>tenfactorial equ 10*9*8*7*6*5*4*3*2
<syntaxhighlight lang="68000devpac">tenfactorial equ 10*9*8*7*6*5*4*3*2


MOVE.L #tenfactorial,D1 ;load the constant integer 10! into D1
MOVE.L #tenfactorial,D1 ;load the constant integer 10! into D1
LEA tenfactorial,A1 ;load into A1 the memory address 10! = 0x375F00
LEA tenfactorial,A1 ;load into A1 the memory address 10! = 0x375F00
ADD.L #tenfactorial,D2 ;add 10! to whatever is stored in D2 and store the result in D2</lang>
ADD.L #tenfactorial,D2 ;add 10! to whatever is stored in D2 and store the result in D2</syntaxhighlight>

=={{header|8086 Assembly}}==
Since 10! is bigger than 16 bits, I'll use 8! instead to demonstrate. Most assemblers only support the standard C operators for compile-time calculation, so we're going to need to multiply out the factorial manually.
<syntaxhighlight lang="asm">mov ax,8*7*6*5*4*3*2 ;8! equals 40,320 or 0x9D80
call Monitor ;unimplemented routine, displays the register contents to screen</syntaxhighlight>
{{out}}
<tt>0x9D80</tt>


=={{header|Ada}}==
=={{header|Ada}}==
Here's a hardcoded version:
Here's a hardcoded version:
<lang ada>
<syntaxhighlight lang="ada">
with Ada.Text_Io;
with Ada.Text_Io;
procedure CompileTimeCalculation is
procedure CompileTimeCalculation is
Line 166: Line 141:
Ada.Text_Io.Put(Integer'Image(Factorial));
Ada.Text_Io.Put(Integer'Image(Factorial));
end CompileTimeCalculation;
end CompileTimeCalculation;
</syntaxhighlight>
</lang>
And here's a recursive function version that prints the exact same thing.
And here's a recursive function version that prints the exact same thing.
<lang ada>
<syntaxhighlight lang="ada">
with Ada.Text_Io;
with Ada.Text_Io;
procedure CompileTimeCalculation is
procedure CompileTimeCalculation is
Line 184: Line 159:
begin
begin
Ada.Text_Io.Put(Integer'Image(Fact10));
Ada.Text_Io.Put(Integer'Image(Fact10));
end CompileTimeCalculation;</lang>
end CompileTimeCalculation;</syntaxhighlight>


===Unbounded Compile-Time Calculation===
===Unbounded Compile-Time Calculation===
Line 190: Line 165:
An interesting property of Ada is that such calculations at compile time are performed with mathematical (i.e., unbounded) integers for intermediate results. On a compiler with 32-bit integers (gcc), the following code prints the value of '20 choose 10' = 184756:
An interesting property of Ada is that such calculations at compile time are performed with mathematical (i.e., unbounded) integers for intermediate results. On a compiler with 32-bit integers (gcc), the following code prints the value of '20 choose 10' = 184756:


<lang Ada>with Ada.Text_IO;
<syntaxhighlight lang="ada">with Ada.Text_IO;


procedure Unbounded_Compile_Time_Calculation is
procedure Unbounded_Compile_Time_Calculation is
Line 201: Line 176:
-- Ada.Text_IO.Put_Line -- would not compile
-- Ada.Text_IO.Put_Line -- would not compile
-- ("Factorial(20) =" & Integer'Image(A_11_15 * A_16_20 * F_10));
-- ("Factorial(20) =" & Integer'Image(A_11_15 * A_16_20 * F_10));
end Unbounded_Compile_Time_Calculation;</lang>
end Unbounded_Compile_Time_Calculation;</syntaxhighlight>


The same compiler refuses to compile the two two lines
The same compiler refuses to compile the two two lines


<lang Ada> Ada.Text_IO.Put_Line -- would not compile
<syntaxhighlight lang="ada"> Ada.Text_IO.Put_Line -- would not compile
("Factorial(20) =" & Integer'Image(A_11_15 * A_16_20 * F_10));</lang>
("Factorial(20) =" & Integer'Image(A_11_15 * A_16_20 * F_10));</syntaxhighlight>


because the final result A_11_15 * A_16_20 * F_10 is a '''value not in range of type "Standard.Integer"''' -- the same intermediate value that was used above to compute '20 choose 10'.
because the final result A_11_15 * A_16_20 * F_10 is a '''value not in range of type "Standard.Integer"''' -- the same intermediate value that was used above to compute '20 choose 10'.
Line 213: Line 188:
The values of AppleScript 'property' variables are set when a script's compiled, although they can also be changed when the script's run. (If it's a top-level script run from a compiled file, the values of its properties when it finishes are saved back to the file and the properties will start off with those values next time it's run.) Property declarations are single lines, but the lines can be calls to handlers declared upscript from the properties themselves.
The values of AppleScript 'property' variables are set when a script's compiled, although they can also be changed when the script's run. (If it's a top-level script run from a compiled file, the values of its properties when it finishes are saved back to the file and the properties will start off with those values next time it's run.) Property declarations are single lines, but the lines can be calls to handlers declared upscript from the properties themselves.


<lang applescript>-- This handler must be declared somewhere above the relevant property declaration
<syntaxhighlight lang="applescript">-- This handler must be declared somewhere above the relevant property declaration
-- so that the compiler knows about it when compiling the property.
-- so that the compiler knows about it when compiling the property.
on factorial(n)
on factorial(n)
Line 230: Line 205:
on run
on run
return compiledValue
return compiledValue
end run</lang>
end run</syntaxhighlight>


{{output}}
{{output}}
<lang applescript>3628800</lang>
<syntaxhighlight lang="applescript">3628800</syntaxhighlight>

=={{header|Arturo}}==
<syntaxhighlight lang="arturo">f10: 1*2*3*4*5*6*7*8*9*10 ; this is evaluated at compile time

; the generate bytecode is:
; [ :bytecode
; ================================
; DATA
; ================================
; 0: 3628800 :integer
; 1: f10 :label

; ================================
; CODE
; ================================
; push0
; store1
; end
; ]

print f10</syntaxhighlight>

{{out}}

<pre>3628800</pre>


=={{header|BASIC}}==
=={{header|BASIC}}==
Most BASICs perform compile-time calculation on anything they can determine is a constant. This can either be done explicitly:
Most BASICs perform compile-time calculation on anything they can determine is a constant. This can either be done explicitly:
<lang qbasic>CONST factorial10 = 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10</lang>
<syntaxhighlight lang="qbasic">CONST factorial10 = 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10</syntaxhighlight>


or implicitly:
or implicitly:


<lang qbasic>DIM factorial10 AS LONG
<syntaxhighlight lang="qbasic">DIM factorial10 AS LONG
factorial10 = 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10</lang>
factorial10 = 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10</syntaxhighlight>


In both cases, the identifier <code>factorial10</code> is given the value 3628800 without any runtime calculations, although in many (or perhaps most) BASICs the first one is handled similarly to C's <code>#define</code>: if it isn't used elsewhere in the code, it doesn't appear at all in the final executable.
In both cases, the identifier <code>factorial10</code> is given the value 3628800 without any runtime calculations, although in many (or perhaps most) BASICs the first one is handled similarly to C's <code>#define</code>: if it isn't used elsewhere in the code, it doesn't appear at all in the final executable.

=={{header|BASIC256}}==
<syntaxhighlight lang="basic">factorial = 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10
print "10! = "; factorial # 3628800</syntaxhighlight>


=={{header|C}}==
=={{header|C}}==
Line 250: Line 254:


The Order macro library [[Order|implements a full virtual machine and high-level, functional programming language]] available to C programs at compile-time:
The Order macro library [[Order|implements a full virtual machine and high-level, functional programming language]] available to C programs at compile-time:
<lang c>#include <stdio.h>
<syntaxhighlight lang="c">#include <stdio.h>
#include <order/interpreter.h>
#include <order/interpreter.h>


Line 259: Line 263:
printf("10! = %d\n", ORDER_PP( 8to_lit( 8fac(10) ) ) );
printf("10! = %d\n", ORDER_PP( 8to_lit( 8fac(10) ) ) );
return 0;
return 0;
}</lang>
}</syntaxhighlight>


In this example, the <code>8fac</code> function computes the factorial by folding <code>8times</code> (the binary multiplication primitive) over a numeric range created by <code>8seq_iota</code> (which requires <code>8X</code> to be incremented, as it creates lists from L to R-1), a familiar way of computing this in functional languages. The result of the factorial calculation is an internal, "native" number which need to be converted to decimal by the <code>8to_lit</code> function.
In this example, the <code>8fac</code> function computes the factorial by folding <code>8times</code> (the binary multiplication primitive) over a numeric range created by <code>8seq_iota</code> (which requires <code>8X</code> to be incremented, as it creates lists from L to R-1), a familiar way of computing this in functional languages. The result of the factorial calculation is an internal, "native" number which need to be converted to decimal by the <code>8to_lit</code> function.
Line 272: Line 276:
===C (simpler version)===
===C (simpler version)===
This is a simple version, showing that 10! was computed at compile time:
This is a simple version, showing that 10! was computed at compile time:
<lang c>#include <stdio.h>
<syntaxhighlight lang="c">#include <stdio.h>
const int val = 2*3*4*5*6*7*8*9*10;
const int val = 2*3*4*5*6*7*8*9*10;
int main(void) {
int main(void) {
printf("10! = %d\n", val );
printf("10! = %d\n", val );
return 0;
return 0;
}</lang>
}</syntaxhighlight>


{{out}}<pre>10! = 3628800</pre>
{{out}}<pre>10! = 3628800</pre>
Line 319: Line 323:
</pre>
</pre>


=={{header|C sharp}}==
=={{header|C sharp|C#}}==
'''Compiler:''' Roslyn C#, language version 7.3
'''Compiler:''' Roslyn C#, language version 7.3


The Roslyn compiler performs constant folding at compile-time and emits IL that contains the result.
The Roslyn compiler performs constant folding at compile-time and emits IL that contains the result.


<lang csharp>using System;
<syntaxhighlight lang="csharp">using System;


public static class Program
public static class Program
Line 333: Line 337:
Console.WriteLine(FACTORIAL_10);
Console.WriteLine(FACTORIAL_10);
}
}
}</lang>
}</syntaxhighlight>


{{out|Emitted IL|note=disassembled with ILSpy}}
{{out|Emitted IL|note=disassembled with ILSpy}}


<!--CIL assembly has a similar overall syntax to C#, so colorize it as such.-->
<!--CIL assembly has a similar overall syntax to C#, so colorize it as such.-->
<lang csharp>.class public auto ansi abstract sealed beforefieldinit Program
<syntaxhighlight lang="csharp">.class public auto ansi abstract sealed beforefieldinit Program
extends [System.Runtime]System.Object
extends [System.Runtime]System.Object
{
{
Line 358: Line 362:
} // end of method Program::Main
} // end of method Program::Main


} // end of class Program</lang>
} // end of class Program</syntaxhighlight>


Note that the constant field is generated only when both it and the containing class are visible outside of the assembly.
Note that the constant field is generated only when both it and the containing class are visible outside of the assembly.
Line 364: Line 368:
Constant expressions that appear outside of constant declarations are also folded, so
Constant expressions that appear outside of constant declarations are also folded, so


<lang csharp>using System;
<syntaxhighlight lang="csharp">using System;


static class Program
static class Program
Line 372: Line 376:
Console.WriteLine(10 * 9 * 8 * 7 * 6 * 5 * 4 * 3 * 2 * 1);
Console.WriteLine(10 * 9 * 8 * 7 * 6 * 5 * 4 * 3 * 2 * 1);
}
}
}</lang>
}</syntaxhighlight>


and
and


<lang csharp>using System;
<syntaxhighlight lang="csharp">using System;


static class Program
static class Program
Line 386: Line 390:
Console.WriteLine(factorial);
Console.WriteLine(factorial);
}
}
}</lang>
}</syntaxhighlight>


produce the same IL, except without the field.
produce the same IL, except without the field.
Line 392: Line 396:
{{out|Emitted IL|note=disassembled with ILSpy}}
{{out|Emitted IL|note=disassembled with ILSpy}}


<lang csharp>.class private auto ansi abstract sealed beforefieldinit Program
<syntaxhighlight lang="csharp">.class private auto ansi abstract sealed beforefieldinit Program
extends [System.Runtime]System.Object
extends [System.Runtime]System.Object
{
{
Line 409: Line 413:
} // end of method Program::Main
} // end of method Program::Main


} // end of class Program</lang>
} // end of class Program</syntaxhighlight>


{{out}}
{{out}}
Line 416: Line 420:
=={{header|C++}}==
=={{header|C++}}==
This is called [[wp:Template metaprogramming|Template metaprogramming]]. In fact, templates in C++ are Turing-complete, making deciding whether a program will compile undecidable.
This is called [[wp:Template metaprogramming|Template metaprogramming]]. In fact, templates in C++ are Turing-complete, making deciding whether a program will compile undecidable.
<lang cpp>#include <iostream>
<syntaxhighlight lang="cpp">#include <iostream>


template<int i> struct Fac
template<int i> struct Fac
Line 433: Line 437:
std::cout << "10! = " << Fac<10>::result << "\n";
std::cout << "10! = " << Fac<10>::result << "\n";
return 0;
return 0;
}</lang>
}</syntaxhighlight>


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.
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.
Line 440: Line 444:
Alternative version, using constexpr in C++11:
Alternative version, using constexpr in C++11:


<lang cpp>#include <stdio.h>
<syntaxhighlight lang="cpp">#include <stdio.h>


constexpr int factorial(int n) {
constexpr int factorial(int n) {
Line 451: Line 455:
printf("%d\n", f10);
printf("%d\n", f10);
return 0;
return 0;
}</lang>
}</syntaxhighlight>
Output:
Output:
<pre>3628800</pre>
<pre>3628800</pre>
The asm produced by G++ 4.6.0 32 bit (-std=c++0x -S), shows the computation is done at compile-time:
The asm produced by G++ 4.6.0 32 bit (-std=c++0x -S), shows the computation is done at compile-time:
<lang asm>_main:
<syntaxhighlight lang="asm">_main:
pushl %ebp
pushl %ebp
movl %esp, %ebp
movl %esp, %ebp
Line 466: Line 470:
movl $0, %eax
movl $0, %eax
leave
leave
ret</lang>
ret</syntaxhighlight>


=={{header|C3}}==
C3 has semantic macros that use a different syntax from the regular runtime syntax.

<syntaxhighlight lang="c">macro int factorial($n)
{
$if ($n == 0):
return 1;
$else:
return $n * factorial($n - 1);
$endif;
}

extern fn void printf(char *fmt, ...);

fn void main()
{
int x = factorial(10);
printf("10! = %d\n", x);
}</syntaxhighlight>

{{out}}
<pre>10! = 3628800</pre>


=={{header|Clojure}}==
=={{header|Clojure}}==
<lang clojure>
<syntaxhighlight lang="clojure">
(defn fac [n] (apply * (range 1 (inc n))))
(defn fac [n] (apply * (range 1 (inc n))))
(defmacro ct-factorial [n] (fac n))</lang>
(defmacro ct-factorial [n] (fac n))</syntaxhighlight>


=={{header|Common Lisp}}==
=={{header|Common Lisp}}==
Line 477: Line 505:
Assuming a definition from [[Factorial function#Common Lisp]], we first have to make a small adjustment so that the function is available at compile time. Common Lisp does not have a single image building and deployment model. For instance, Common Lisp implementations can support a "C like" model whereby a compiler is invoked as a separate process to handle individual files, which are then loaded to form an image (analogous to linking). A Lisp compiler will not make available to itself the functions in a source file which it happens to be compiling, unless told to do so:
Assuming a definition from [[Factorial function#Common Lisp]], we first have to make a small adjustment so that the function is available at compile time. Common Lisp does not have a single image building and deployment model. For instance, Common Lisp implementations can support a "C like" model whereby a compiler is invoked as a separate process to handle individual files, which are then loaded to form an image (analogous to linking). A Lisp compiler will not make available to itself the functions in a source file which it happens to be compiling, unless told to do so:


<lang lisp>(eval-when (:compile-toplevel :load-toplevel :execute)
<syntaxhighlight lang="lisp">(eval-when (:compile-toplevel :load-toplevel :execute)
(defun factorial ...))</lang>
(defun factorial ...))</syntaxhighlight>


With that, here are ways to do compile-time evaluation:
With that, here are ways to do compile-time evaluation:


<lang lisp>(defmacro ct-factorial (n)
<syntaxhighlight lang="lisp">(defmacro ct-factorial (n)
(factorial n))
(factorial n))


...
...


(print (ct-factorial 10))</lang>
(print (ct-factorial 10))</syntaxhighlight>


The <code>factorial</code> function must be defined before any use of the <code>ct-factorial</code> macro is evaluated or compiled.
The <code>factorial</code> function must be defined before any use of the <code>ct-factorial</code> macro is evaluated or compiled.
Line 493: Line 521:
If the data resulting from the compile-time calculation is not necessarily a number or other [http://www.lispworks.com/documentation/HyperSpec/Body/03_abac.htm self-evaluating object], as it is in the factorial case, then the macro must quote it to avoid it being interpreted as code (a form):
If the data resulting from the compile-time calculation is not necessarily a number or other [http://www.lispworks.com/documentation/HyperSpec/Body/03_abac.htm self-evaluating object], as it is in the factorial case, then the macro must quote it to avoid it being interpreted as code (a form):


<lang lisp>(defmacro ct-factorial (n)
<syntaxhighlight lang="lisp">(defmacro ct-factorial (n)
`(quote ,(factorial n)))
`(quote ,(factorial n)))


; or, equivalently,
; or, equivalently,
(defmacro ct-factorial (n)
(defmacro ct-factorial (n)
`',(factorial n))</lang>
`',(factorial n))</syntaxhighlight>


It is also possible to have a value [http://www.lispworks.com/documentation/HyperSpec/Body/s_ld_tim.htm computed at ''load time''], when the code is loaded into the process, rather than at compile time; this is useful if the value to be computed contains objects that do not yet exist at compile time, or the value might vary due to properties which might be different while yet using the same compiled program (e.g. pathnames), but it is still constant for one execution of the program:
It is also possible to have a value [http://www.lispworks.com/documentation/HyperSpec/Body/s_ld_tim.htm computed at ''load time''], when the code is loaded into the process, rather than at compile time; this is useful if the value to be computed contains objects that do not yet exist at compile time, or the value might vary due to properties which might be different while yet using the same compiled program (e.g. pathnames), but it is still constant for one execution of the program:


<lang lisp>(print (load-time-value (factorial 10)))</lang>
<syntaxhighlight lang="lisp">(print (load-time-value (factorial 10)))</syntaxhighlight>


Further it's also possible to have the value computed at read time using the read macro <code>#.</code> .
Further it's also possible to have the value computed at read time using the read macro <code>#.</code> .


<lang lisp>(print (#. (factorial 10)))</lang>
<syntaxhighlight lang="lisp">(print (#. (factorial 10)))</syntaxhighlight>


Lastly, Common Lisp has "compiler macros" which are user-defined handlers for function call optimization. A compiler macro is defined which has the same name as some user-defined function. When calls to that function are being compiled, they pass through the macro. The macro must analyze the arguments and rewrite the function call into something else, or return the original form.
Lastly, Common Lisp has "compiler macros" which are user-defined handlers for function call optimization. A compiler macro is defined which has the same name as some user-defined function. When calls to that function are being compiled, they pass through the macro. The macro must analyze the arguments and rewrite the function call into something else, or return the original form.


<lang lisp>(define-compiler-macro factorial (&whole form arg)
<syntaxhighlight lang="lisp">(define-compiler-macro factorial (&whole form arg)
(if (constantp arg)
(if (constantp arg)
(factorial arg)
(factorial arg)
form))</lang>
form))</syntaxhighlight>


Test with CLISP (taking advantage of its <code>!</code> function) showing how a factorial call with a constant argument of 10 ends up compiled to the constant 3268800, but a factorial call with the argument a is compiled to a variable access and function call:
Test with CLISP (taking advantage of its <code>!</code> function) showing how a factorial call with a constant argument of 10 ends up compiled to the constant 3268800, but a factorial call with the argument a is compiled to a variable access and function call:
Line 554: Line 582:
=={{header|D}}==
=={{header|D}}==
The D compiler is able to run many functions at compile-time [http://dlang.org/function.html#interpretation Compile Time Function Execution (CTFE)]:
The D compiler is able to run many functions at compile-time [http://dlang.org/function.html#interpretation Compile Time Function Execution (CTFE)]:
<lang d>long fact(in long x) pure nothrow @nogc {
<syntaxhighlight lang="d">long fact(in long x) pure nothrow @nogc {
long result = 1;
long result = 1;
foreach (immutable i; 2 .. x + 1)
foreach (immutable i; 2 .. x + 1)
Line 568: Line 596:


printf("%ld\n", fact10);
printf("%ld\n", fact10);
}</lang>
}</syntaxhighlight>


The 32-bit asm generated by DMD shows the computation is done at compile-time:
The 32-bit asm generated by DMD shows the computation is done at compile-time:
<lang asm>__Dmain
<syntaxhighlight lang="asm">__Dmain
push EAX
push EAX
mov EAX,offset FLAT:_DATA
mov EAX,offset FLAT:_DATA
Line 581: Line 609:
xor EAX,EAX
xor EAX,EAX
pop ECX
pop ECX
ret</lang>
ret</syntaxhighlight>


=={{header|Delphi}}==
=={{header|Delphi}}==
Line 589: Line 617:
In DWScript, constant expressions and referentially-transparent built-in functions, such as ''Factorial'', are evaluated at compile time.
In DWScript, constant expressions and referentially-transparent built-in functions, such as ''Factorial'', are evaluated at compile time.


<lang delphi>const fact10 = Factorial(10);</lang>
<syntaxhighlight lang="delphi">const fact10 = Factorial(10);</syntaxhighlight>


=={{header|EchoLisp}}==
=={{header|EchoLisp}}==
'''define-constant''' may be used to compute data, which in turn may be used in other define-constant, or in the final code.
'''define-constant''' may be used to compute data, which in turn may be used in other define-constant, or in the final code.
<lang scheme>
<syntaxhighlight lang="scheme">
(define-constant DIX! (factorial 10))
(define-constant DIX! (factorial 10))
(define-constant DIX!+1 (1+ DIX!))
(define-constant DIX!+1 (1+ DIX!))
Line 599: Line 627:
(writeln DIX!+1)
(writeln DIX!+1)
3628801
3628801
</syntaxhighlight>
</lang>

=={{header|EDSAC order code}}==
Under David Wheeler's Initial Orders 2, the effect of compile-time calculation could be achieved on EDSAC by the use of "interludes" in the loading process. Code for an interlude was loaded into store, then loading was paused while the interlude was executed. When finished, the interlude passed control back to initial orders, and normal loading was resumed. Code that was used only by the interlude could then be overwritten. In this way once-only code was not left taking up storage space, which was in short supply on EDSAC.

Interludes could be used for calculation or for other purposes. E.g. the library subroutine M3 ran as an interlude; it printed a header on the teleprinter, and then M3 and the header text were overwritten.

Code for an interlude should not change locations in the initial orders. Also, if the multiplier register is used, its original value should be restored before exit from the interlude. The interlude in the demo program below is based on a shorter example in Wilkes, Wheeler & Gill, 1951 edn, p. 112.
<syntaxhighlight lang="edsac">
[Demo of calculating a constant in an interlude at load time.
EDSAC program, Initial Orders 2.]

[Arrange the storage]
T46K P56F [N parameter: library subroutine P7 to print integer]
T47K P100F [M parameter: main routine]

E25K TM GK [M parameter, main routine]
T#Z PF [clear 35-bit value at relative locations
0 & 1, including the middle ("sandwich") bit]
T2#Z PF [same for 2 & 3]
T4#Z PF [same for 4 & 5]
TZ [resume normal loading at relative location 0]
[Storage for interlude, must be at even address]
[0] PD PF [35-bit factorial, initially integer 1]
[2] PD PF [35-bit factor 1..10, initially integer 1]
[4] PF K4096F [to save multiplier register (MR), initially floating point -1]
[6] PD [17-bit integer 1]
[7] P5F [17-bit integer 10 (or number whose factorial is required)]
[8] PF [dump for clearing acc]
[Executable code for interlude; here with acc = 0]
[9] N4#@ [acc := MR, by subtracting (-1 * MR)]
T4#@ [save MR over interlude]
[11] T8@ [start of loop: clear acc]
A2@ [acc := factor]
A6@ [add 1]
T2@ [update factor, clear acc]
H2#@ [MR := factor, extended to 35 bits]
V#@ [times 35-bit product, result in acc]
L1024F L1024F L256F [integer scaling: shift 34 left]
T#@ [update product]
A2@ [acc := factor just used]
S7@ [is it 10 yet?]
G11@ [if not, loop back]
H4#@ [restore MR before exit from interlude]
E25F [pass control back to initial orders]
[At this point the interlude has been loaded but not executed.
The next control combination starts execution.]
E9Z [pass control to relative location 9 above]
PF [value in accumulator when control is passed: here = 0]
[After the interlude, loading resumes here.]
T2Z [resume normal loading at relative location 2,
overwriting the above interlude except the factorial]
[Teleprinter characters]
[2] #F [set figures mode]
[3] @F [carriage return]
[4] &F [line feed]
[Enter here with acc = 0]
[5] O2@ [set teleprinter to figures]
A#@ [acc := factorial, as calculated in the interlude]
TD [pass to print subroutine]
[8] A8@ GN [call print subroutine]
O3@ O4@ [print CR, LF]
O2@ [dummy character to flush teleprinter buffer]
ZF [stop]

E25K TN [N parameter]
[Library subroutine P7, prints 35-bit strictly positive integer in 0D.]
[10 characters, right justified, padded left with spaces.]
[Even address; 35 storage locations; working position 4D.]
GKA3FT26@H28#@NDYFLDT4DS27@TFH8@S8@T1FV4DAFG31@SFLDUFOFFFSF
L4FT4DA1FA27@G11@XFT28#ZPFT27ZP1024FP610D@524D!FO30@SFL8FE22@

E25K TM GK [M parameter again]
E5Z [define entry point]
PF [acc = 0 on entry]
</syntaxhighlight>
{{out}}
<pre>
3628800
</pre>


=={{header|Erlang}}==
=={{header|Erlang}}==
Line 607: Line 714:
Technically, this calculation happens at parse-time, before any compilation takes place. Calculating factorial at compile-time is not useful in Factor.
Technically, this calculation happens at parse-time, before any compilation takes place. Calculating factorial at compile-time is not useful in Factor.


<lang factor>: factorial ( n -- n! ) [1,b] product ;
<syntaxhighlight lang="factor">: factorial ( n -- n! ) [1,b] product ;


CONSTANT: 10-factorial $[ 10 factorial ]</lang>
CONSTANT: 10-factorial $[ 10 factorial ]</syntaxhighlight>


=={{header|Forth}}==
=={{header|Forth}}==
During a word definition, you can drop out of the compilation state with '''[''' and go back in with ''']'''. (This is where the naming conventions for '''[CHAR]''' and '''[']''' come from.) There are several flavors of '''LITERAL''' for compiling the result into the word.
During a word definition, you can drop out of the compilation state with '''[''' and go back in with ''']'''. (This is where the naming conventions for '''[CHAR]''' and '''[']''' come from.) There are several flavors of '''LITERAL''' for compiling the result into the word.


<lang forth>: fac ( n -- n! ) 1 swap 1+ 2 max 2 ?do i * loop ;
<syntaxhighlight lang="forth">: fac ( n -- n! ) 1 swap 1+ 2 max 2 ?do i * loop ;


: main ." 10! = " [ 10 fac ] literal . ;
: main ." 10! = " [ 10 fac ] literal . ;
Line 620: Line 727:
see main
see main
: main
: main
.\" 10! = " 3628800 . ; ok</lang>
.\" 10! = " 3628800 . ; ok</syntaxhighlight>


Outside of a word definition, it's fuzzy. If the following code is itself followed by a test and output, and is run in a script, then the construction of the '''bignum''' array (and the perhaps native-code compilation of '''more''') happens at runtime. If the following code is followed by a command that creates an executable, the array will not be rebuilt on each run.
Outside of a word definition, it's fuzzy. If the following code is itself followed by a test and output, and is run in a script, then the construction of the '''bignum''' array (and the perhaps native-code compilation of '''more''') happens at runtime. If the following code is followed by a command that creates an executable, the array will not be rebuilt on each run.


<lang forth>
<syntaxhighlight lang="forth">
: more ( "digits" -- ) \ store "1234" as 1 c, 2 c, 3 c, 4 c,
: more ( "digits" -- ) \ store "1234" as 1 c, 2 c, 3 c, 4 c,
parse-word bounds ?do
parse-word bounds ?do
Line 633: Line 740:
more 73167176531330624919225119674426574742355349194934
more 73167176531330624919225119674426574742355349194934
more 96983520312774506326239578318016984801869478851843
more 96983520312774506326239578318016984801869478851843
...</lang>
...</syntaxhighlight>


=={{header|Fortran}}==
=={{header|Fortran}}==
In Fortran, parameters can be defined where the value is computed at compile time:
In Fortran, parameters can be defined where the value is computed at compile time:
<lang fortran> program test
<syntaxhighlight lang="fortran"> program test


implicit none
implicit none
Line 645: Line 752:


end program test
end program test
</syntaxhighlight>
</lang>


=={{header|FreeBASIC}}==
=={{header|FreeBASIC}}==
<lang freebasic>' FB 1.05.0 Win64
<syntaxhighlight lang="freebasic">' FB 1.05.0 Win64


' Calculations can be done in a Const declaration at compile time
' Calculations can be done in a Const declaration at compile time
Line 655: Line 762:
Const factorial As Integer = 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10
Const factorial As Integer = 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10
Print factorial ' 3628800
Print factorial ' 3628800
Sleep</lang>
Sleep</syntaxhighlight>


=={{header|Go}}==
=={{header|Go}}==
Constant expressions are evaluated at compile time. A constant expression though, is pretty simple and can't have much more than literals, operators, and a special thing called iota. There is no way to loop in a constant expression and so the expanded expression below is about the simplest way of completing this task.
Constant expressions are evaluated at compile time. A constant expression though, is pretty simple and can't have much more than literals, operators, and a special thing called iota. There is no way to loop in a constant expression and so the expanded expression below is about the simplest way of completing this task.
<lang go>package main
<syntaxhighlight lang="go">package main


import "fmt"
import "fmt"
Line 665: Line 772:
func main() {
func main() {
fmt.Println(2*3*4*5*6*7*8*9*10)
fmt.Println(2*3*4*5*6*7*8*9*10)
}</lang>
}</syntaxhighlight>


=={{header|Haskell}}==
=={{header|Haskell}}==
Line 671: Line 778:
With Template Haskell, it is quite easy to do compile time embedding. The functions used at compile-time need to be already compiled. Therefore, you generally need two modules.
With Template Haskell, it is quite easy to do compile time embedding. The functions used at compile-time need to be already compiled. Therefore, you generally need two modules.


<lang haskell>module Factorial where
<syntaxhighlight lang="haskell">module Factorial where
import Language.Haskell.TH.Syntax
import Language.Haskell.TH.Syntax


Line 677: Line 784:


factQ :: Integer -> Q Exp
factQ :: Integer -> Q Exp
factQ = lift . fact</lang>
factQ = lift . fact</syntaxhighlight>


<lang haskell>{-# LANGUAGE TemplateHaskell #-}
<syntaxhighlight lang="haskell">{-# LANGUAGE TemplateHaskell #-}
import Factorial
import Factorial


main = print $(factQ 10)</lang>
main = print $(factQ 10)</syntaxhighlight>


Note: Doing <code>$([|fact 10|])</code> is the same than doing <code>fact 10</code>. <code>[|something|]</code> returns the abstract syntax tree of <code>something</code>. Thus <code>[|fact 10|]</code> returns the AST of the call to the <code>fact</code> function with 10 as argument. <code>$(something)</code> waits for an AST from a call to <code>something</code>.
Note: Doing <code>$([|fact 10|])</code> is the same than doing <code>fact 10</code>. <code>[|something|]</code> returns the abstract syntax tree of <code>something</code>. Thus <code>[|fact 10|]</code> returns the AST of the call to the <code>fact</code> function with 10 as argument. <code>$(something)</code> waits for an AST from a call to <code>something</code>.
Line 692: Line 799:
Thus, a program which prints 10 factorial:
Thus, a program which prints 10 factorial:


<lang J>pf10=: smoutput bind (!10)</lang>
<syntaxhighlight lang="j">pf10=: smoutput bind (!10)</syntaxhighlight>


When the definition of pf10 is examined, it contains the value 3628800. J has several ways of representing tacit programs. Here all five of them are presented for this program (the last two happen to look identical for this trivial case):
When the definition of pf10 is examined, it contains the value 3628800. J has several ways of representing tacit programs. Here all five of them are presented for this program (the last two happen to look identical for this trivial case):


<lang J> 9!:3]1 2 4 5 6
<syntaxhighlight lang="j"> 9!:3]1 2 4 5 6


pf10
pf10
Line 721: Line 828:
└─ " ──────┴─ _
└─ " ──────┴─ _
smoutput@(3628800"_)
smoutput@(3628800"_)
smoutput@(3628800"_)</lang>
smoutput@(3628800"_)</syntaxhighlight>


Finally, when this program is run, it displays this number:
Finally, when this program is run, it displays this number:


<lang J> pf10 ''
<syntaxhighlight lang="j"> pf10 ''
3628800</lang>
3628800</syntaxhighlight>


Note: Currently, the mediawiki implementation is corrupting the above display due to a cascading sequence of bad design decisions and mis-interpreted specifications on the part of someone "contributing" to that implementation. To work around this issue, and see the original display, you can currently use either the "Edit" or "View Source" option, depending on whether you are logged in to rosettacode with an account that has edit rights here. (Please don't actually save changes though.) If you are using View Source, you might want to do that in a new tab (so you also stay here with this view) and use your browser's search capability to quickly scroll to this location in the source view.
Note: Currently, the mediawiki implementation is corrupting the above display due to a cascading sequence of bad design decisions and mis-interpreted specifications on the part of someone "contributing" to that implementation. To work around this issue, and see the original display, you can currently use either the "Edit" or "View Source" option, depending on whether you are logged in to rosettacode with an account that has edit rights here. (Please don't actually save changes though.) If you are using View Source, you might want to do that in a new tab (so you also stay here with this view) and use your browser's search capability to quickly scroll to this location in the source view.

=={{header|Java}}==
<pre>
The Java compiler is able to calculate expressions that contain constant variables
and certain operators during code compilation.
As defined in the Java language specification,
the following operators and expressions may be used for constant expressions:

Unary operators: +, -, ~, !
Multiplicative operators: *, /, %
Additive operators: +, –
Shift operators: <<, >>, >>>
Relational operators: <, <=, >, >=
Equality operators: ==, !=
Bitwise and logical operators: &, ^, |
Conditional-and and the conditional-or operator: &&, ||
Ternary conditional operator: ?:
Parenthesized expressions whose contained expression is a constant expression
Simple names that refer to constant variables
</pre>
<syntaxhighlight lang="java">

public final class CompileTimeCalculation {

public static void main(String[] aArgs) {
System.out.println(tenFactorial);
}
private static int tenFactorial = 10 * 9 * 8 * 7 * 6 * 5 * 4 * 3 * 2 * 1;

}
</syntaxhighlight>
{{ out }}
<pre>
3628800
</pre>


=={{header|Julia}}==
=={{header|Julia}}==
Julia includes a powerful macro feature that can perform arbitrary code transformations at compile-time (or technically at parse-time), and can also execute arbitrary Julia code. For example, the following macro computes the factorial of <code>n</code> (a literal constant) and returns the value (e.g. to inline it in the resulting source code)
Julia includes a powerful macro feature that can perform arbitrary code transformations at compile-time (or technically at parse-time), and can also execute arbitrary Julia code. For example, the following macro computes the factorial of <code>n</code> (a literal constant) and returns the value (e.g. to inline it in the resulting source code)
<lang julia>macro fact(n)
<syntaxhighlight lang="julia">macro fact(n)
factorial(n)
factorial(n)
end</lang>
end</syntaxhighlight>
If we now use this in a function, e.g.
If we now use this in a function, e.g.
<lang julia>foo() = @fact 10</lang>
<syntaxhighlight lang="julia">foo() = @fact 10</syntaxhighlight>
then the value of 10! = 3628800 is computed at parse-time and is inlined in the compiled function <code>foo</code>, as can be verified by inspecting the assembly code via the built-in function <code>code_native(foo, ())</code>.
then the value of 10! = 3628800 is computed at parse-time and is inlined in the compiled function <code>foo</code>, as can be verified by inspecting the assembly code via the built-in function <code>code_native(foo, ())</code>.


=={{header|Kotlin}}==
=={{header|Kotlin}}==
Compile time calculations are possible in Kotlin using the 'const' modifier provided one sticks to literals or other constants when specifying the calculation to be performed:
Compile time calculations are possible in Kotlin using the 'const' modifier provided one sticks to literals or other constants when specifying the calculation to be performed:
<lang scala>// version 1.0.6
<syntaxhighlight lang="scala">// version 1.0.6
const val TEN_FACTORIAL = 10 * 9 * 8 * 7 * 6 * 5 * 4 * 3 * 2
const val TEN_FACTORIAL = 10 * 9 * 8 * 7 * 6 * 5 * 4 * 3 * 2


fun main(args: Array<String>) {
fun main(args: Array<String>) {
println("10! = $TEN_FACTORIAL")
println("10! = $TEN_FACTORIAL")
}</lang>
}</syntaxhighlight>


{{out}}
{{out}}
Line 755: Line 899:
=={{header|Lingo}}==
=={{header|Lingo}}==
As an interpreted language with the interpreter always being present, Lingo has no clear separation of compile-time and runtime. Whenever you change the code of a script at runtime, it's immediately (re)compiled to bytecode (in memory). You can also create new scripts at runtime:
As an interpreted language with the interpreter always being present, Lingo has no clear separation of compile-time and runtime. Whenever you change the code of a script at runtime, it's immediately (re)compiled to bytecode (in memory). You can also create new scripts at runtime:
<lang lingo>-- create new (movie) script at runtime
<syntaxhighlight lang="lingo">-- create new (movie) script at runtime
m = new(#script)
m = new(#script)


Line 762: Line 906:


put fac10()
put fac10()
-- 3628800</lang>
-- 3628800</syntaxhighlight>


=={{header|Lua}}==
=={{header|Lua}}==
Lua's compiler will attempt to fold constant expressions, which appears to be enough to satisfy this specific task's requirements:
Lua's compiler will attempt to fold constant expressions, which appears to be enough to satisfy this specific task's requirements:
<lang lua>local factorial = 10*9*8*7*6*5*4*3*2*1
<syntaxhighlight lang="lua">local factorial = 10*9*8*7*6*5*4*3*2*1
print(factorial)</lang>
print(factorial)</syntaxhighlight>
{{out}}<pre>3628800</pre>
{{out}}<pre>3628800</pre>
Proof via disassembly (Lua 5.3 used - the lookup of global "print" may vary a bit among 5.x versions, but not significant):
Proof via disassembly (Lua 5.3 used - the lookup of global "print" may vary a bit among 5.x versions, but not significant):
Line 786: Line 930:
This example uses m4 as a front end to [[AWK]]. m4 calculates factorial of 10, where AWK program calls macro.
This example uses m4 as a front end to [[AWK]]. m4 calculates factorial of 10, where AWK program calls macro.


<lang m4>define(`factorial',
<syntaxhighlight lang="m4">define(`factorial',
`ifelse($1, 0, 1, `eval($1 * factorial(eval($1 - 1)))')')dnl
`ifelse($1, 0, 1, `eval($1 * factorial(eval($1 - 1)))')')dnl
dnl
dnl
BEGIN {
BEGIN {
print "10! is factorial(10)"
print "10! is factorial(10)"
}</lang>
}</syntaxhighlight>


One runs <code>m4 program.m4 > program.awk</code> to make this valid AWK program.
One runs <code>m4 program.m4 > program.awk</code> to make this valid AWK program.


<lang awk>BEGIN {
<syntaxhighlight lang="awk">BEGIN {
print "10! is 3628800"
print "10! is 3628800"
}</lang>
}</syntaxhighlight>


=={{header|Mathematica}} / {{header|Wolfram Language}}==
=={{header|Mathematica}} / {{header|Wolfram Language}}==
Mathematica is not a compiled language, you can construct compiled functions in Mathematica by the build-in function "Compile". Constants are calculated at "compile-time".
Mathematica is not a compiled language, you can construct compiled functions in Mathematica by the build-in function "Compile". Constants are calculated at "compile-time".
<lang>f = Compile[{}, 10!]</lang>
<syntaxhighlight lang="text">f = Compile[{}, 10!]</syntaxhighlight>
{{Out}}
{{Out}}
<pre>CompiledFunction[{},3628800,-CompiledCode-]</pre>
<pre>CompiledFunction[{},3628800,-CompiledCode-]</pre>
<lang>f[]</lang>
<syntaxhighlight lang="text">f[]</syntaxhighlight>
{{Out}}
{{Out}}
<pre>3628800</pre>
<pre>3628800</pre>

=={{header|MIPS Assembly}}==
While most assemblers support compile-time expressions, factorial is typically not one of them. However, you can multiply out the factorial manually. It's not feasible for larger factorials but it's better than nothing.
<syntaxhighlight lang="mips">li t0,10*9*8*7*6*5*4*3*2 ;= 10! = 0x375F00
jal monitor ;display all registers to the screen
nop</syntaxhighlight>
{{out}}
<pre>t0:00375F00</pre>


=={{header|Nim}}==
=={{header|Nim}}==
Nim can evaluate procedures at compile-time, this can be forced by calling a procedure with a const keyword like so:
Nim can evaluate procedures at compile-time, this can be forced by calling a procedure with a const keyword like so:


<lang Nim>proc fact(x: int): int =
<syntaxhighlight lang="nim">proc fact(x: int): int =
result = 1
result = 1
for i in 2..x:
for i in 2..x:
Line 817: Line 969:


const fact10 = fact(10)
const fact10 = fact(10)
echo(fact10)</lang>
echo(fact10)</syntaxhighlight>


We can see that this is evaluated at compile-time by looking at the generated C code:
We can see that this is evaluated at compile-time by looking at the generated C code:


<lang C>...
<syntaxhighlight lang="c">...
STRING_LITERAL(TMP122, "3628800", 7);
STRING_LITERAL(TMP122, "3628800", 7);
...</lang>
...</syntaxhighlight>


The Nim compiler can also be told to try to evaluate procedures at compile-time even for variables by using the --implicitStatic:on command line switch.
The Nim compiler can also be told to try to evaluate procedures at compile-time even for variables by using the --implicitStatic:on command line switch.
Line 830: Line 982:
=={{header|Oberon-2}}==
=={{header|Oberon-2}}==
Works with oo2c Version 2
Works with oo2c Version 2
<lang oberon2>
<syntaxhighlight lang="oberon2">
MODULE CompileTime;
MODULE CompileTime;
IMPORT
IMPORT
Line 839: Line 991:
Out.String("10! =");Out.LongInt(tenfac,0);Out.Ln
Out.String("10! =");Out.LongInt(tenfac,0);Out.Ln
END CompileTime.
END CompileTime.
</syntaxhighlight>
</lang>


=={{header|Objeck}}==
=={{header|Objeck}}==
Objeck will fold constants at compiler time as long as the -s2 or -s3 compiler switches are enabled.
Objeck will fold constants at compiler time as long as the -s2 or -s3 compiler switches are enabled.


<lang objeck>
<syntaxhighlight lang="objeck">
bundle Default {
bundle Default {
class CompileTime {
class CompileTime {
Line 852: Line 1,004:
}
}
}
}
</syntaxhighlight>
</lang>


=={{header|OCaml}}==
=={{header|OCaml}}==
Line 858: Line 1,010:
OCaml does not calculate operations that involve functions calls, as for example factorial 10, but OCaml does calculate simple mathematical operations at compile-time, for example in the code below <code>(24 * 60 * 60)</code> will be replaced by its result <code>86400</code>.
OCaml does not calculate operations that involve functions calls, as for example factorial 10, but OCaml does calculate simple mathematical operations at compile-time, for example in the code below <code>(24 * 60 * 60)</code> will be replaced by its result <code>86400</code>.


<lang ocaml>let days_to_seconds n =
<syntaxhighlight lang="ocaml">let days_to_seconds n =
let conv = 24 * 60 * 60 in
let conv = 24 * 60 * 60 in
(n * conv)
(n * conv)
;;</lang>
;;</syntaxhighlight>


It is easy to verify this using the argument <code>-S</code> to keep the intermediate assembly file:
It is easy to verify this using the argument <code>-S</code> to keep the intermediate assembly file:
Line 870: Line 1,022:
If you wish to verify this property in your own projects, you have to know that integer values most often have their OCaml internal representation in the assembly, which for an integer <code>x</code> its OCaml internal representation will be <code>(((x) << 1) + 1)</code>. So for example if we modify the previous code for:
If you wish to verify this property in your own projects, you have to know that integer values most often have their OCaml internal representation in the assembly, which for an integer <code>x</code> its OCaml internal representation will be <code>(((x) << 1) + 1)</code>. So for example if we modify the previous code for:


<lang ocaml>let conv = 24 * 60 * 60
<syntaxhighlight lang="ocaml">let conv = 24 * 60 * 60


let days_to_seconds n =
let days_to_seconds n =
(n * conv)
(n * conv)
;;</lang>
;;</syntaxhighlight>


# (24 * 60 * 60) lsl 1 + 1 ;;
# (24 * 60 * 60) lsl 1 + 1 ;;
Line 885: Line 1,037:
However, with the introduction of [https://github.com/ocaml-flambda/flambda-backend Flambda] (an alternative intermediate language, inliner, and optimiser), OCaml compilers which equip this backend have a limited ability to reduce pure and annotated function calls to constants:
However, with the introduction of [https://github.com/ocaml-flambda/flambda-backend Flambda] (an alternative intermediate language, inliner, and optimiser), OCaml compilers which equip this backend have a limited ability to reduce pure and annotated function calls to constants:


<lang ocaml>let fact10 =
<syntaxhighlight lang="ocaml">let fact10 =
let rec factorial n =
let rec factorial n =
if n = 1 then n else n * factorial (n-1)
if n = 1 then n else n * factorial (n-1)
Line 893: Line 1,045:
(* The unrolled annotation is what allows flambda to keep reducing the call
(* The unrolled annotation is what allows flambda to keep reducing the call
* Beware that the number of unrollings must be greater than or equal to the
* Beware that the number of unrollings must be greater than or equal to the
* number of iterations (recursive calls) for this to compile down to a constant. *)</lang>
* number of iterations (recursive calls) for this to compile down to a constant. *)</syntaxhighlight>


The assembler output (cleaned up and demangled a little) shows exactly what's expected, stored as data
The assembler output (cleaned up and demangled a little) shows exactly what's expected, stored as data
Line 912: Line 1,064:
You can do any calculation you want before or after, create constants, ...
You can do any calculation you want before or after, create constants, ...


<lang Oforth>10 seq reduce(#*) Constant new: FACT10
<syntaxhighlight lang="oforth">10 seq reduce(#*) Constant new: FACT10
: newFunction FACT10 . ;</lang>
: newFunction FACT10 . ;</syntaxhighlight>


You can also calculate all factorials for 1 to 20 before defining fact method :
You can also calculate all factorials for 1 to 20 before defining fact method :
<lang Oforth>20 seq map(#[ seq reduce(#*) ]) Constant new: ALLFACTS
<syntaxhighlight lang="oforth">20 seq map(#[ seq reduce(#*) ]) Constant new: ALLFACTS
: fact(n) n ifZero: [ 1 ] else: [ ALLFACTS at(n) ] ;
: fact(n) n ifZero: [ 1 ] else: [ ALLFACTS at(n) ] ;


ALLFACTS println</lang>
ALLFACTS println</syntaxhighlight>


{{out}}
{{out}}
Line 933: Line 1,085:
To dimension a static array, the macro Pling10 is resolved at compile time. The overall compile time (ready to execute) was around 23 milliseconds.
To dimension a static array, the macro Pling10 is resolved at compile time. The overall compile time (ready to execute) was around 23 milliseconds.


<lang oxygenbasic>
<syntaxhighlight lang="oxygenbasic">
'LIBRARY CALLS
'LIBRARY CALLS
'=============
'=============
Line 986: Line 1,138:
o2_exec 'Run the program
o2_exec 'Run the program
end if
end if
</syntaxhighlight>
</lang>


=={{header|Oz}}==
=={{header|Oz}}==
<lang oz>functor
<syntaxhighlight lang="oz">functor
import
import
System Application
System Application
Line 1,000: Line 1,152:
{System.showInfo "10! = "#Fac10}
{System.showInfo "10! = "#Fac10}
{Application.exit 0}
{Application.exit 0}
end</lang>
end</syntaxhighlight>


Code in the <code>prepare</code> section of a functor is executed at compile time. External modules that are used in this code must be imported with a <code>require</code> statement (not shown in this example). Such external functors must have been compiled before the current functor is compiled (<code>ozmake</code> will automatically take care of this).
Code in the <code>prepare</code> section of a functor is executed at compile time. External modules that are used in this code must be imported with a <code>require</code> statement (not shown in this example). Such external functors must have been compiled before the current functor is compiled (<code>ozmake</code> will automatically take care of this).
Line 1,011: Line 1,163:
as the values can be resolved.
as the values can be resolved.


<lang pascal>
<syntaxhighlight lang="pascal">
program in out;
program in out;


Line 1,023: Line 1,175:


end;
end;
</syntaxhighlight>
</lang>


=={{header|Perl}}==
=={{header|Perl}}==
Line 1,029: Line 1,181:
There are few limits on code you can put in <code>BEGIN</code> blocks, which are executed at compile-time. Unfortunately, you can't in general save the compiled form of a program to run later. Instead, <code>perl</code> recompiles your program every time you run it.
There are few limits on code you can put in <code>BEGIN</code> blocks, which are executed at compile-time. Unfortunately, you can't in general save the compiled form of a program to run later. Instead, <code>perl</code> recompiles your program every time you run it.


<lang perl>my $tenfactorial;
<syntaxhighlight lang="perl">my $tenfactorial;
print "$tenfactorial\n";
print "$tenfactorial\n";


BEGIN
BEGIN
{$tenfactorial = 1;
{$tenfactorial = 1;
$tenfactorial *= $_ foreach 1 .. 10;}</lang>
$tenfactorial *= $_ foreach 1 .. 10;}</syntaxhighlight>


Note however that all constant folding is done at compile time, so this actually does the factorial at compile time.
Note however that all constant folding is done at compile time, so this actually does the factorial at compile time.


<lang perl>my $tenfactorial = 10 * 9 * 8 * 7 * 6 * 5 * 4 * 3 * 2;</lang>
<syntaxhighlight lang="perl">my $tenfactorial = 10 * 9 * 8 * 7 * 6 * 5 * 4 * 3 * 2;</syntaxhighlight>


=={{header|Phix}}==
=={{header|Phix}}==
The Phix compiler uses constant folding/propagation, so running p -d on the following snippet
The Phix compiler uses constant folding/propagation, so running p -d on the following snippet
<!--<syntaxhighlight lang="phix">(phixonline)-->
<lang Phix>integer a,b
<span style="color: #004080;">integer</span> <span style="color: #000000;">a</span><span style="color: #0000FF;">,</span><span style="color: #000000;">b</span>
a = 10*9*8*7*6*5*4*3*2*1
<span style="color: #000000;">a</span> <span style="color: #0000FF;">=</span> <span style="color: #000000;">10</span><span style="color: #0000FF;">*</span><span style="color: #000000;">9</span><span style="color: #0000FF;">*</span><span style="color: #000000;">8</span><span style="color: #0000FF;">*</span><span style="color: #000000;">7</span><span style="color: #0000FF;">*</span><span style="color: #000000;">6</span><span style="color: #0000FF;">*</span><span style="color: #000000;">5</span><span style="color: #0000FF;">*</span><span style="color: #000000;">4</span><span style="color: #0000FF;">*</span><span style="color: #000000;">3</span><span style="color: #0000FF;">*</span><span style="color: #000000;">2</span><span style="color: #0000FF;">*</span><span style="color: #000000;">1</span>
b = factorial(10)
<span style="color: #000000;">b</span> <span style="color: #0000FF;">=</span> <span style="color: #7060A8;">factorial</span><span style="color: #0000FF;">(</span><span style="color: #000000;">10</span><span style="color: #0000FF;">)</span>
?{a,b}</lang>
<span style="color: #0000FF;">?{</span><span style="color: #000000;">a</span><span style="color: #0000FF;">,</span><span style="color: #000000;">b</span><span style="color: #0000FF;">}</span>
<!--</syntaxhighlight>-->
produces a listing file containing
produces a listing file containing
<pre>
<pre>
Line 1,067: Line 1,221:
runs, arbitrary expressions can be executed with the backqoute and tilde
runs, arbitrary expressions can be executed with the backqoute and tilde
operators ([http://software-lab.de/doc/ref.html#macro-io read macros]).
operators ([http://software-lab.de/doc/ref.html#macro-io read macros]).
<lang PicoLisp>(de fact (N)
<syntaxhighlight lang="picolisp">(de fact (N)
(apply * (range 1 N)) )
(apply * (range 1 N)) )


(de foo ()
(de foo ()
(prinl "The value of fact(10) is " `(fact 10)) )</lang>
(prinl "The value of fact(10) is " `(fact 10)) )</syntaxhighlight>
Output:
Output:
<pre>: (pp 'foo) # Pretty-print the function
<pre>: (pp 'foo) # Pretty-print the function
Line 1,083: Line 1,237:


=={{header|PL/I}}==
=={{header|PL/I}}==
<syntaxhighlight lang="pl/i">
<lang PL/I>
/* Factorials using the pre-processor. */
/* Factorials using the pre-processor. */
test: procedure options (main);
test: procedure options (main);
Line 1,110: Line 1,264:


end test;
end test;
</syntaxhighlight>
</lang>


Output from the pre-processor:
Output from the pre-processor:


<lang>
<syntaxhighlight lang="text">
/* Factorials using the pre-processor. */
/* Factorials using the pre-processor. */
test: procedure options (main);
test: procedure options (main);
Line 1,123: Line 1,277:
put skip list ('factorial 6 is ', y);
put skip list ('factorial 6 is ', y);
end test;
end test;
</syntaxhighlight>
</lang>


Execution results:
Execution results:


<lang>
<syntaxhighlight lang="text">
factorial 4 is 24
factorial 4 is 24
factorial 6 is 720
factorial 6 is 720
</syntaxhighlight>
</lang>


=={{header|PowerShell}}==
=={{header|PowerShell}}==
<syntaxhighlight lang="powershell">
<lang PowerShell>
function fact([BigInt]$n){
function fact([BigInt]$n){
if($n -ge ([BigInt]::Zero)) {
if($n -ge ([BigInt]::Zero)) {
Line 1,148: Line 1,302:
"$((Measure-Command {$fact = fact 10}).TotalSeconds) Seconds"
"$((Measure-Command {$fact = fact 10}).TotalSeconds) Seconds"
$fact
$fact
</syntaxhighlight>
</lang>
<b>Output:</b>
<b>Output:</b>
<pre>
<pre>
Line 1,159: Line 1,313:


goal_expansion/2 will change the goal in the code at compile time to be something else, in the case the constant number.
goal_expansion/2 will change the goal in the code at compile time to be something else, in the case the constant number.
<lang Prolog>% Taken from RosettaCode Factorial page for Prolog
<syntaxhighlight lang="prolog">% Taken from RosettaCode Factorial page for Prolog
fact(X, 1) :- X<2.
fact(X, 1) :- X<2.
fact(X, F) :- Y is X-1, fact(Y,Z), F is Z*X.
fact(X, F) :- Y is X-1, fact(Y,Z), F is Z*X.
Line 1,167: Line 1,321:
test :-
test :-
F = factorial_of(10),
F = factorial_of(10),
format('!10 = ~p~n', F).</lang>
format('!10 = ~p~n', F).</syntaxhighlight>
{{out}}
{{out}}
<pre>
<pre>
Line 1,182: Line 1,336:
=={{header|PureBasic}}==
=={{header|PureBasic}}==
PureBasic will do most calculation during compiling, e.g.
PureBasic will do most calculation during compiling, e.g.
<lang PureBasic>a=1*2*3*4*5*6*7*8*9*10</lang>
<syntaxhighlight lang="purebasic">a=1*2*3*4*5*6*7*8*9*10</syntaxhighlight>
could on a x86 be complied to
could on a x86 be complied to
<pre>MOV dword [v_a],3628800</pre>
<pre>MOV dword [v_a],3628800</pre>
Line 1,190: Line 1,344:
To compute and print 10! during compilation:
To compute and print 10! during compilation:


<lang Quackery>[ 1 10 times [ i 1+ * ] echo ] now!</lang>
<syntaxhighlight lang="quackery">[ 1 10 times [ i 1+ * ] echo ] now!</syntaxhighlight>


To compute 10! during compilation and print the result at runtime:
To compute 10! during compilation and print the result at runtime:


<lang Quackery>[ 1 10 times [ i 1+ * ] ] constant echo</lang>
<syntaxhighlight lang="quackery">[ 1 10 times [ i 1+ * ] ] constant echo</syntaxhighlight>


Any Quackery code can be executed during compilation, but the programmer must bear in mind that the compiler uses the stack, so executed code should have no overall stack effect in the case of <code>now!</code>, or leave a single item on the stack to be compiled in the case of <code>constant</code>.
Any Quackery code can be executed during compilation, but the programmer must bear in mind that the compiler uses the stack, so executed code should have no overall stack effect in the case of <code>now!</code>, or leave a single item on the stack to be compiled in the case of <code>constant</code>.
Line 1,202: Line 1,356:
Racket, like most Lisp descendants, allows arbitrary code to be executed at compile-time.
Racket, like most Lisp descendants, allows arbitrary code to be executed at compile-time.


<lang racket>
<syntaxhighlight lang="racket">
#lang racket
#lang racket


Line 1,224: Line 1,378:
;; use the macro defined above
;; use the macro defined above
(fact10)
(fact10)
</syntaxhighlight>
</lang>


=={{header|Raku}}==
=={{header|Raku}}==
(formerly Perl 6)
(formerly Perl 6)


<lang perl6>constant $tenfact = [*] 2..10;
<syntaxhighlight lang="raku" line>constant $tenfact = [*] 2..10;
say $tenfact;</lang>
say $tenfact;</syntaxhighlight>


Like Perl 5, we also have a BEGIN block, but it also works to introduce a blockless statement,
Like Perl 5, we also have a BEGIN block, but it also works to introduce a blockless statement,
the value of which will be stored up to be used in the surrounding expression at run time:
the value of which will be stored up to be used as an expression at run time:


<lang perl6> say(BEGIN [*] 2..10);</lang>
<syntaxhighlight lang="raku" line> say BEGIN [*] 2..10;</syntaxhighlight>


=={{header|REXX}}==
=={{header|REXX}}==
Line 1,260: Line 1,414:


Since REXX is an interpreted language &nbsp; (as are other languages entered for this Rosetta Code task), &nbsp; run time is compile time.
Since REXX is an interpreted language &nbsp; (as are other languages entered for this Rosetta Code task), &nbsp; run time is compile time.
<lang rexx>/*REXX program computes 10! (ten factorial) during REXX's equivalent of "compile─time". */
<syntaxhighlight lang="rexx">/*REXX program computes 10! (ten factorial) during REXX's equivalent of "compile─time". */


say '10! =' !(10)
say '10! =' !(10)
exit /*stick a fork in it, we're all done. */
exit /*stick a fork in it, we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
/*──────────────────────────────────────────────────────────────────────────────────────*/
!: procedure; !=1; do j=2 to arg(1); !=!*j; end /*j*/; return !</lang>
!: procedure; !=1; do j=2 to arg(1); !=!*j; end /*j*/; return !</syntaxhighlight>
'''output'''
'''output'''
<pre>
<pre>
Line 1,272: Line 1,426:


=={{header|Ring}}==
=={{header|Ring}}==
<lang ring>
<syntaxhighlight lang="ring">
a = 10*9*8*7*6*5*4*3*2*1
a = 10*9*8*7*6*5*4*3*2*1
b = factorial(10)
b = factorial(10)
Line 1,279: Line 1,433:


func factorial nr if nr = 1 return 1 else return nr * factorial(nr-1) ok
func factorial nr if nr = 1 return 1 else return nr * factorial(nr-1) ok
</syntaxhighlight>
</lang>

=={{header|Run BASIC}}==
{{works with|Just BASIC}}
{{works with|Liberty BASIC}}
<syntaxhighlight lang="vb">factorial = 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10
print "10! = "; factorial ' 3628800</syntaxhighlight>


=={{header|Rust}}==
=={{header|Rust}}==
The Rust compiler can automatically do optimizations in the code to calculate the factorial.
The Rust compiler can automatically do optimizations in the code to calculate the factorial.


<lang rust>fn factorial(n: i64) -> i64 {
<syntaxhighlight lang="rust">fn factorial(n: i64) -> i64 {
let mut total = 1;
let mut total = 1;
for i in 1..n+1 {
for i in 1..n+1 {
Line 1,294: Line 1,454:
fn main() {
fn main() {
println!("Factorial of 10 is {}.", factorial(10));
println!("Factorial of 10 is {}.", factorial(10));
}</lang>
}</syntaxhighlight>


If we compile this with <code>rustc factorial.rs -O --emit asm</code> and inspect the outputted assembly, we can see <code>movq $3628800, (%rsp)</code>. This means the result of 3628800 was calculated in compile-time rather than run-time.
If we compile this with <code>rustc factorial.rs -O --emit asm</code> and inspect the outputted assembly, we can see <code>movq $3628800, (%rsp)</code>. This means the result of 3628800 was calculated in compile-time rather than run-time.


=={{header|Scala}}==
=={{header|Scala}}==

<lang Scala>object Main extends {
Scala 3 supports proper compile time evaluation

<syntaxhighlight lang="scala">
transparent inline def factorial(inline n: Int): Int =
inline n match
case 0 => 1
case _ => n * factorial(n - 1)

inline val factorial10/*: 3628800*/ = factorial(10)
</syntaxhighlight>

Alternative version that works with Scala 2:

<syntaxhighlight lang="scala">object Main extends {
val tenFactorial = 10 * 9 * 8 * 7 * 6 * 5 * 4 * 3 * 2
val tenFactorial = 10 * 9 * 8 * 7 * 6 * 5 * 4 * 3 * 2


Line 1,305: Line 1,479:


println(s"10! = $tenFactorial", tenFac)
println(s"10! = $tenFactorial", tenFac)
}</lang>
}</syntaxhighlight>
As it can been seen in the always heavily optimized run-time code the calculations are already computed for the field constant and function method.
As it can been seen in the always heavily optimized run-time code the calculations are already computed for the field constant and function method.
<pre>
<pre>
Line 1,343: Line 1,517:
The ! operator is predefined, so no user defined function is necessary.
The ! operator is predefined, so no user defined function is necessary.


<lang seed7>$ include "seed7_05.s7i";
<syntaxhighlight lang="seed7">$ include "seed7_05.s7i";


const proc: main is func
const proc: main is func
Line 1,350: Line 1,524:
begin
begin
writeln(factorial);
writeln(factorial);
end func;</lang>
end func;</syntaxhighlight>


=={{header|Sidef}}==
=={{header|Sidef}}==
The compile-time evaluation is limited at a constant expression, which cannot refer at any other user-defined data, such as variables or functions.
The compile-time evaluation is limited at a constant expression, which cannot refer at any other user-defined data, such as variables or functions.
<lang ruby>define n = (10!);
<syntaxhighlight lang="ruby">define n = (10!);
say n;</lang>
say n;</syntaxhighlight>


or:
or:
<lang ruby>define n = (func(n){ n > 0 ? __FUNC__(n-1)*n : 1 }(10));
<syntaxhighlight lang="ruby">define n = (func(n){ n > 0 ? __FUNC__(n-1)*n : 1 }(10));
say n;</lang>
say n;</syntaxhighlight>


=={{header|Tcl}}==
=={{header|Tcl}}==
Line 1,365: Line 1,539:


{{works with|Tcl|8.5}}
{{works with|Tcl|8.5}}
<lang tcl>proc makeFacExpr n {
<syntaxhighlight lang="tcl">proc makeFacExpr n {
set exp 1
set exp 1
for {set i 2} {$i <= $n} {incr i} {
for {set i 2} {$i <= $n} {incr i} {
Line 1,372: Line 1,546:
return "expr \{$exp\}"
return "expr \{$exp\}"
}
}
eval [makeFacExpr 10]</lang>
eval [makeFacExpr 10]</syntaxhighlight>
How to show that the results were compiled? Like this:
How to show that the results were compiled? Like this:
<lang tcl>% tcl::unsupported::disassemble script [makeFacExpr 10]
<syntaxhighlight lang="tcl">% tcl::unsupported::disassemble script [makeFacExpr 10]
ByteCode 0x0x4de10, refCt 1, epoch 3, interp 0x0x31c10 (epoch 3)
ByteCode 0x0x4de10, refCt 1, epoch 3, interp 0x0x31c10 (epoch 3)
Source "expr {1 * 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10}"
Source "expr {1 * 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10}"
Line 1,383: Line 1,557:
(0) push1 0 # "3628800"
(0) push1 0 # "3628800"
(2) done
(2) done
</syntaxhighlight>
</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).
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).

=={{header|TXR}}==

In TXR Lisp, the standard <code>macro-time</code> macro evaluates an expression at macro-expansion time, and replaces it by its result, which is then treated as a literal (because the macro inserts `quote` around it, if required).

Such a macro is easy to implement in Common Lisp and similar dialects. The [https://www.nongnu.org/txr/txr-manpage.html#N-0131B069 documentation] provides a reference implementation which is easily ported.

Example: provide a function <code>buildinfo</code> in the compiled program which returns the build machine name, and time and date of the compilation. A global variable which provides this value could similarly be defined:

<syntaxhighlight lang="txrlisp">
(defun buildinfo ()
(macro-time
`Built by @{(uname).nodename} on @(time-string-local (time) "%c")`))
</syntaxhighlight>

If we compile and disassemble the function, we see it just contains a canned literal:

<pre>
3> (compile 'buildinfo)
#<vm fun: 0 param>
4> (disassemble *3)
data:
0: buildinfo
1: "Built by sun-go on Sat Oct 1 20:01:25 2022"
syms:
code:
0: 8C000005 close t2 0 2 5 0 0 nil
1: 00000002
2: 00000000
3: 00000002
4: 10000401 end d1
5: 10000002 end t2
instruction count:
3
entry point:
4
#<vm fun: 0 param>
</pre>


=={{header|Ursala}}==
=={{header|Ursala}}==
Any user-defined or library function callable at run time can also be called at compile time
Any user-defined or library function callable at run time can also be called at compile time
and evaluated with no unusual ceremony involved.
and evaluated with no unusual ceremony involved.
<lang Ursala>#import nat
<syntaxhighlight lang="ursala">#import nat


x = factorial 10
x = factorial 10
Line 1,395: Line 1,607:
#executable&
#executable&


comcal = ! (%nP x)--<''></lang>
comcal = ! (%nP x)--<''></syntaxhighlight>
some notes:
some notes:
* <code>x</code> is declared as a constant equal to ten factorial using the <code>factorial</code> function imported from the <code>nat</code> library.
* <code>x</code> is declared as a constant equal to ten factorial using the <code>factorial</code> function imported from the <code>nat</code> library.
Line 1,423: Line 1,635:
The Roslyn compiler performs constant folding at compile-time and emits IL that contains the result.
The Roslyn compiler performs constant folding at compile-time and emits IL that contains the result.


<lang vbnet>Module Program
<syntaxhighlight lang="vbnet">Module Program
Const FACTORIAL_10 = 10 * 9 * 8 * 7 * 6 * 5 * 4 * 3 * 2 * 1
Const FACTORIAL_10 = 10 * 9 * 8 * 7 * 6 * 5 * 4 * 3 * 2 * 1


Line 1,429: Line 1,641:
Console.WriteLine(FACTORIAL_10)
Console.WriteLine(FACTORIAL_10)
End Sub
End Sub
End Module</lang>
End Module</syntaxhighlight>


{{out|Emitted IL|note=disassembled with ILSpy}}
{{out|Emitted IL|note=disassembled with ILSpy}}


<!--CIL assembly has a similar overall syntax to C#, so colorize it as such.-->
<!--CIL assembly has a similar overall syntax to C#, so colorize it as such.-->
<lang csharp>.class private auto ansi sealed Program
<syntaxhighlight lang="csharp">.class private auto ansi sealed Program
extends [System.Runtime]System.Object
extends [System.Runtime]System.Object
{
{
Line 1,460: Line 1,672:
} // end of method Program::Main
} // end of method Program::Main


} // end of class Program</lang>
} // end of class Program</syntaxhighlight>


Constant expressions that appear outside of constant declarations are also folded, so
Constant expressions that appear outside of constant declarations are also folded, so


<lang vbnet>Module Program
<syntaxhighlight lang="vbnet">Module Program
Sub Main()
Sub Main()
Console.WriteLine(10 * 9 * 8 * 7 * 6 * 5 * 4 * 3 * 2 * 1)
Console.WriteLine(10 * 9 * 8 * 7 * 6 * 5 * 4 * 3 * 2 * 1)
End Sub
End Sub
End Module</lang>
End Module</syntaxhighlight>


and
and


<lang vbnet>Module Program
<syntaxhighlight lang="vbnet">Module Program
Sub Main()
Sub Main()
Dim factorial As Integer
Dim factorial As Integer
Line 1,478: Line 1,690:
Console.WriteLine(factorial)
Console.WriteLine(factorial)
End Sub
End Sub
End Module</lang>
End Module</syntaxhighlight>


produce the same IL, albeit without the constant field that other assemblies can reference.
produce the same IL, albeit without the constant field that other assemblies can reference.


{{out|Emitted IL|note=disassembled with ILSpy}}
{{out|Emitted IL|note=disassembled with ILSpy}}
<lang csharp>.class private auto ansi sealed Program
<syntaxhighlight lang="csharp">.class private auto ansi sealed Program
extends [System.Runtime]System.Object
extends [System.Runtime]System.Object
{
{
Line 1,506: Line 1,718:
} // end of method Program::Main
} // end of method Program::Main


} // end of class Program</lang>
} // end of class Program</syntaxhighlight>


{{out}}
{{out}}
Line 1,516: Line 1,728:
Also Wren has no notion of constants - at compile time or otherwise - and is thoroughly object-oriented. Even literals such as ''123'' and ''true'' are technically instances of the immutable built-in classes Num and Bool.
Also Wren has no notion of constants - at compile time or otherwise - and is thoroughly object-oriented. Even literals such as ''123'' and ''true'' are technically instances of the immutable built-in classes Num and Bool.


There is little public information on the workings of the bytecode compiler other than that it is single pass and stack based. However, from what I have said above, I'd be surprised if it does any calculations and the likelihood is that the factorial calculation in the program below is done at runtine.
There is little public information on the workings of the bytecode compiler other than that it is single pass and stack based. However, I gather that it does no compile time calculations at all and the factorial calculation in the program below is therefore done at runtime.


Not that it makes much difference in practice as the compiler which is written in C is so quick (at least with scripts of moderate length and on modern hardware) that the compile and runtime stages are indistinguishable to the user.
Not that it makes much difference in practice as the compiler which is written in C is so quick (at least with scripts of moderate length and on modern hardware) that the compile and runtime stages are indistinguishable to the user.
<lang ecmascript>var factorial10 = 10 * 9 * 8 * 7 * 6 * 5 * 4 * 3 * 2
<syntaxhighlight lang="wren">var factorial10 = 10 * 9 * 8 * 7 * 6 * 5 * 4 * 3 * 2


System.print(factorial10)</lang>
System.print(factorial10)</syntaxhighlight>


{{out}}
{{out}}
Line 1,530: Line 1,742:
=={{header|XLISP}}==
=={{header|XLISP}}==
Macros can be used to evaluate expressions at compile time:
Macros can be used to evaluate expressions at compile time:
<lang lisp>(defmacro f10-at-compile-time () (* 2 3 4 5 6 7 8 9 10))</lang>
<syntaxhighlight lang="lisp">(defmacro f10-at-compile-time () (* 2 3 4 5 6 7 8 9 10))</syntaxhighlight>
If the expression is <i>quoted</i>, however, it is <i>not</i> evaluated—it is inserted 'as is', and will be evaluated at run time:
If the expression is <i>quoted</i>, however, it is <i>not</i> evaluated—it is inserted 'as is', and will be evaluated at run time:
<lang lisp>(defmacro f10-at-run-time () '(* 2 3 4 5 6 7 8 9 10))</lang>
<syntaxhighlight lang="lisp">(defmacro f10-at-run-time () '(* 2 3 4 5 6 7 8 9 10))</syntaxhighlight>
To show what is going on, first start a REPL and define little functions that just invoke each macro:
To show what is going on, first start a REPL and define little functions that just invoke each macro:
<lang lisp>[1] (defun test-f10-ct () (f10-at-compile-time))
<syntaxhighlight lang="lisp">[1] (defun test-f10-ct () (f10-at-compile-time))


TEST-F10-CT
TEST-F10-CT
[2] (defun test-f10-rt () (f10-at-run-time))
[2] (defun test-f10-rt () (f10-at-run-time))


TEST-F10-RT</lang>
TEST-F10-RT</syntaxhighlight>
Then use <tt>DECOMPILE</tt> to examine the bytecode generated for each function. First, the one where the calculation was performed at compile time:
Then use <tt>DECOMPILE</tt> to examine the bytecode generated for each function. First, the one where the calculation was performed at compile time:
<pre>[3] (decompile test-f10-ct)
<pre>[3] (decompile test-f10-ct)
Line 1,575: Line 1,787:


=={{header|XPL0}}==
=={{header|XPL0}}==
<lang XPL0>code IntOut=11;
<syntaxhighlight lang="xpl0">code IntOut=11;
IntOut(0, 10*9*8*7*6*5*4*3*2);
IntOut(0, 10*9*8*7*6*5*4*3*2);
</syntaxhighlight>
</lang>
Generates this 80386 assembly code:
Generates this 80386 assembly code:
<pre>
<pre>
Line 1,586: Line 1,798:
RET
RET
</pre>
</pre>

=={{header|Yabasic}}==
<syntaxhighlight lang="basic">factorial = 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10
print "10! = ", factorial // 3628800</syntaxhighlight>

=={{header|Z80 Assembly}}==
{{trans|8086 Assembly}}
Since 10! is bigger than 16 bits, I'll use 8! instead to demonstrate. Most assemblers only support the standard C operators for compile-time calculation, so we're going to need to multiply out the factorial manually.
<syntaxhighlight lang="z80">ld hl,8*7*6*5*4*3*2 ;8! equals 40,320 or 0x9D80
call Monitor ;unimplemented routine, displays the register contents to screen</syntaxhighlight>
{{out}}
<tt>0x9D80</tt>


=={{header|zkl}}==
=={{header|zkl}}==
zkl has two ways to do compile time calculations: a variant of C's macros and "parse time" calculations (since the compiler is written in zkl, the parser just recurses).
zkl has two ways to do compile time calculations: a variant of C's macros and "parse time" calculations (since the compiler is written in zkl, the parser just recurses).
File foo.zkl:
File foo.zkl:
<lang zkl>const { [1..10].reduce('*).println(" parse time") }
<syntaxhighlight lang="zkl">const { [1..10].reduce('*).println(" parse time") }


#fcn fact(N) { [1..N].reduce('*).println(" tokenize time"); ""}
#fcn fact(N) { [1..N].reduce('*).println(" tokenize time"); ""}
Line 1,596: Line 1,820:
#tokenize fact(10)
#tokenize fact(10)


println("compiled program running.");</lang>
println("compiled program running.");</syntaxhighlight>
Run the program: zkl foo:
Run the program: zkl foo:
{{out}}
{{out}}
Line 1,608: Line 1,832:
=={{header|Zig}}==
=={{header|Zig}}==
Zig provides arbitrary CTFE with limitations in IO, memoization and forbidding closures for compilation efficiency.
Zig provides arbitrary CTFE with limitations in IO, memoization and forbidding closures for compilation efficiency.
<lang zig>const std = @import("std");
<syntaxhighlight lang="zig">const std = @import("std");
fn factorial(n: u64) u64 {
fn factorial(n: u64) u64 {
var total: u64 = 1;
var total: u64 = 1;
Line 1,621: Line 1,845:
const res = comptime factorial(10); // arbitrary Compile Time Function Evaluation
const res = comptime factorial(10); // arbitrary Compile Time Function Evaluation
std.debug.print("res: {d}", .{res}); // output only at runtime
std.debug.print("res: {d}", .{res}); // output only at runtime
}</lang>
}</syntaxhighlight>
Output:
Output:
<pre>3628800</pre>
<pre>3628800</pre>

Latest revision as of 15:40, 20 November 2023

Task
Compile-time calculation
You are encouraged to solve this task according to the task description, using any language you may know.

Some programming languages allow calculation of values at compile time.


Task

Calculate   10!   (ten factorial)   at compile time.

Print the result when the program is run.

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

360 Assembly

First example with the assembler equivalence pseudo instruction (EQU):

COMPCALA CSECT
         L      R1,=A(FACT10)      r1=10!
         XDECO  R1,PG
         XPRNT  PG,L'PG            print buffer
         BR     R14                exit
FACT10   EQU    10*9*8*7*6*5*4*3*2*1   factorial computation
PG       DS     CL12
Output:

in the assembler listing ( 375F00 hexadecimal of 10!)

.... 00375F00 .... FACT10   EQU    10*9*8*7*6*5*4*3*2*1   factorial computation
Output:

at execution time

     3628800

Second example with an assembler macro instruction:

         MACRO
&LAB     FACT   &REG,&N            parameters
&F       SETA   1                  f=1
&I       SETA   1                  i=1
.EA      AIF    (&I GT &N).EB      ea: if i>n then goto eb
&F       SETA   &F*&I              f=f*i
&I       SETA   &I+1               i=i+1
         AGO    .EA                goto ea
.EB      ANOP                      eb:
         MNOTE  0,'Load &REG with &N! = &F'   macro note
&LAB     L      &REG,=A(&F)        load reg with factorial
         MEND                      macro end
COMPCALB CSECT
         USING  COMPCALB,R12       base register
         LR     R12,R15            set base register
         FACT   R1,10              macro call
         XDECO  R1,PG
         XPRNT  PG,L'PG            print buffer
         BR     R14                exit
PG       DS     CL12
         YREGS
         END    COMPCALB
Output:

in the assembler listing

          FACT   R1,10              macro call
+         MNOTE 'Load R1 with 10! = 3628800'   macro note
+         L      R1,=A(3628800)        load reg with factorial

6502 Assembly

Works with: ca65

The ca65 cross-assembler supports computing and storing double-word (32-bit) integer values; unfortunately most 6502-based systems have no built-in support for manipulating such values. But the assembler also supports converting them directly to strings, which are easily printed at runtime. So, here's a straightforward implementation. As written, it works for any Commodore 8-bits, but it could be ported to a different 6502 machine just by changing the print loop to use the appropriate output routine for the target system.

; Display the value of 10!, which is precomputed at assembly time
; on any Commodore 8-bit.

.ifndef __CBM__
.error "Target must be a Commodore system."
.endif

; zero-page work pointer
temp         = $fb

; ROM routines used
chrout       = $ffd2

    .code

    lda #<tenfactorial
    sta temp
    lda #>tenfactorial
    sta temp+1
    ldy #0
loop:
    lda (temp),y
    beq done
    jsr chrout
    iny
    bne loop
done:
    rts

    .data

; the actual value to print
tenfactorial: .byte 13,"10! = ",.string(10*9*8*7*6*5*4*3*2*1),13,0
Output:

Here's what it looks like when run immediately upon booting a C-64:

    **** COMMODORE 64 BASIC V2 ****

 64K RAM SYSTEM  38911 BASIC BYTES FREE

READY.
LOAD"*",8,1

SEARCHING FOR *
LOADING
READY.
RUN:

10! = 3628800

READY.

68000 Assembly

VASM allows you to define values using mathematical operators prior to assembly, but you can only do this with constants. The following are all valid:

tenfactorial equ 10*9*8*7*6*5*4*3*2

MOVE.L #tenfactorial,D1  ;load the constant integer 10! into D1
LEA tenfactorial,A1      ;load into A1 the memory address 10! = 0x375F00
ADD.L #tenfactorial,D2   ;add 10! to whatever is stored in D2 and store the result in D2

8086 Assembly

Since 10! is bigger than 16 bits, I'll use 8! instead to demonstrate. Most assemblers only support the standard C operators for compile-time calculation, so we're going to need to multiply out the factorial manually.

mov ax,8*7*6*5*4*3*2 ;8! equals 40,320 or 0x9D80
call Monitor         ;unimplemented routine, displays the register contents to screen
Output:

0x9D80

Ada

Here's a hardcoded version:

with Ada.Text_Io;
procedure CompileTimeCalculation is
   Factorial : constant Integer := 10*9*8*7*6*5*4*3*2*1;
   
begin
   Ada.Text_Io.Put(Integer'Image(Factorial));
end CompileTimeCalculation;

And here's a recursive function version that prints the exact same thing.

with Ada.Text_Io;
procedure CompileTimeCalculation is
   
   function Factorial (Int : in Integer) return Integer is
   begin
      if Int > 1 then
         return Int * Factorial(Int-1);
      else
         return 1;
      end if;
   end;
     
     Fact10 : Integer := Factorial(10);
begin
   Ada.Text_Io.Put(Integer'Image(Fact10));
end CompileTimeCalculation;

Unbounded Compile-Time Calculation

An interesting property of Ada is that such calculations at compile time are performed with mathematical (i.e., unbounded) integers for intermediate results. On a compiler with 32-bit integers (gcc), the following code prints the value of '20 choose 10' = 184756:

with Ada.Text_IO;

procedure Unbounded_Compile_Time_Calculation is
   F_10 : constant Integer := 10*9*8*7*6*5*4*3*2*1;
   A_11_15 : constant Integer := 15*14*13*12*11;
   A_16_20 : constant Integer := 20*19*18*17*16;
begin
   Ada.Text_IO.Put_Line -- prints out
     ("20 choose 10 =" & Integer'Image((A_11_15 * A_16_20 * F_10) / (F_10 * F_10)));
--   Ada.Text_IO.Put_Line -- would not compile
--     ("Factorial(20) =" & Integer'Image(A_11_15 * A_16_20 * F_10));
end Unbounded_Compile_Time_Calculation;

The same compiler refuses to compile the two two lines

   Ada.Text_IO.Put_Line -- would not compile
      ("Factorial(20) =" & Integer'Image(A_11_15 * A_16_20 * F_10));

because the final result A_11_15 * A_16_20 * F_10 is a value not in range of type "Standard.Integer" -- the same intermediate value that was used above to compute '20 choose 10'.

AppleScript

The values of AppleScript 'property' variables are set when a script's compiled, although they can also be changed when the script's run. (If it's a top-level script run from a compiled file, the values of its properties when it finishes are saved back to the file and the properties will start off with those values next time it's run.) Property declarations are single lines, but the lines can be calls to handlers declared upscript from the properties themselves.

-- This handler must be declared somewhere above the relevant property declaration
-- so that the compiler knows about it when compiling the property.
on factorial(n)
    set f to 1
    repeat with i from 2 to n
        set f to f * i
    end repeat
    
    return f
end factorial

property compiledValue : factorial(10)
-- Or of course simply:
-- property compiledValue : 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10

on run
    return compiledValue
end run
Output:
3628800

Arturo

f10: 1*2*3*4*5*6*7*8*9*10 ; this is evaluated at compile time

; the generate bytecode is:
; [ :bytecode
;         ================================
;          DATA
;         ================================
;         0: 3628800 :integer
;         1: f10 :label

;         ================================
;          CODE
;         ================================
;         push0
;         store1
;         end
; ]

print f10
Output:
3628800

BASIC

Most BASICs perform compile-time calculation on anything they can determine is a constant. This can either be done explicitly:

CONST factorial10 = 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10

or implicitly:

DIM factorial10 AS LONG
factorial10 = 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10

In both cases, the identifier factorial10 is given the value 3628800 without any runtime calculations, although in many (or perhaps most) BASICs the first one is handled similarly to C's #define: if it isn't used elsewhere in the code, it doesn't appear at all in the final executable.

BASIC256

factorial = 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10
print "10! = "; factorial # 3628800

C

C includes a macro processor that runs at compile-time. With the use of suitably imaginative macro library includes, it can be used in a similar way to C++ template metaprogramming or Lisp macros. Like C++, and unlike Lisp, the language used is usually very different from the C language used to write runtime code.

The Order macro library implements a full virtual machine and high-level, functional programming language available to C programs at compile-time:

#include <stdio.h>
#include <order/interpreter.h>

#define ORDER_PP_DEF_8fac ORDER_PP_FN( \
8fn(8X, 8seq_fold(8times, 1, 8seq_iota(1, 8inc(8X)))) )

int main(void) {
	printf("10! = %d\n", ORDER_PP( 8to_lit( 8fac(10) ) ) );
	return 0;
}

In this example, the 8fac function computes the factorial by folding 8times (the binary multiplication primitive) over a numeric range created by 8seq_iota (which requires 8X to be incremented, as it creates lists from L to R-1), a familiar way of computing this in functional languages. The result of the factorial calculation is an internal, "native" number which need to be converted to decimal by the 8to_lit function.

If the compiler allows, run the preprocessor only (the -E option with GCC) to see the result in place.

Output:
3628800

This and similar macro libraries are very demanding on the preprocessor, and will require a standards-compliant implementation such as GCC.

C (simpler version)

This is a simple version, showing that 10! was computed at compile time:

#include <stdio.h>
const int val = 2*3*4*5*6*7*8*9*10;
int main(void) {
	printf("10! = %d\n", val );
	return 0;
}
Output:
10! = 3628800

asm from compiler

$ gcc 10fact.c -S
$ cat 10fact.s
        .file   "10fact.c"
        .globl  val
        .section .rdata,"dr"
        .align 4
val:
        .long   3628800
        .def    __main; .scl    2;      .type   32;     .endef
.LC0:
        .ascii "10! = %d\12\0"
        .text
        .globl  main
        .def    main;   .scl    2;      .type   32;     .endef
        .seh_proc       main
main:
        pushq   %rbp
        .seh_pushreg    %rbp
        movq    %rsp, %rbp
        .seh_setframe   %rbp, 0
        subq    $32, %rsp
        .seh_stackalloc 32
        .seh_endprologue
        call    __main
        movl    $3628800, %eax   # critical line showing the compiler computed the result.
        movl    %eax, %edx
        leaq    .LC0(%rip), %rcx
        call    printf
        movl    $0, %eax
        addq    $32, %rsp
        popq    %rbp
        ret
        .seh_endproc
        .ident  "GCC: (GNU) 4.9.3"
        .def    printf; .scl    2;      .type   32;     .endef

C#

Compiler: Roslyn C#, language version 7.3

The Roslyn compiler performs constant folding at compile-time and emits IL that contains the result.

using System;

public static class Program
{
    public const int FACTORIAL_10 = 10 * 9 * 8 * 7 * 6 * 5 * 4 * 3 * 2 * 1;
    static void Main()
    {
        Console.WriteLine(FACTORIAL_10);
    }
}
Emitted IL (disassembled with ILSpy):
.class public auto ansi abstract sealed beforefieldinit Program
	extends [System.Runtime]System.Object
{
	// Fields
	.field public static literal int32 FACTORIAL_10 = int32(3628800)

	// Methods
	.method private hidebysig static 
		void Main () cil managed 
	{
		// Method begins at RVA 0x2050
		// Code size 11 (0xb)
		.maxstack 8
		.entrypoint

		IL_0000: ldc.i4 3628800
		IL_0005: call void [System.Console]System.Console::WriteLine(int32)
		IL_000a: ret
	} // end of method Program::Main

} // end of class Program

Note that the constant field is generated only when both it and the containing class are visible outside of the assembly.

Constant expressions that appear outside of constant declarations are also folded, so

using System;

static class Program
{
    static void Main()
    {
        Console.WriteLine(10 * 9 * 8 * 7 * 6 * 5 * 4 * 3 * 2 * 1);
    }
}

and

using System;

static class Program
{
    static void Main()
    {
        int factorial;
        factorial = 10 * 9 * 8 * 7 * 6 * 5 * 4 * 3 * 2 * 1;
        Console.WriteLine(factorial);
    }
}

produce the same IL, except without the field.

Emitted IL (disassembled with ILSpy):
.class private auto ansi abstract sealed beforefieldinit Program
	extends [System.Runtime]System.Object
{
	// Methods
	.method private hidebysig static 
		void Main () cil managed 
	{
		// Method begins at RVA 0x2050
		// Code size 11 (0xb)
		.maxstack 8
		.entrypoint

		IL_0000: ldc.i4 3628800
		IL_0005: call void [System.Console]System.Console::WriteLine(int32)
		IL_000a: ret
	} // end of method Program::Main

} // end of class Program
Output:
3628800

C++

This is called Template metaprogramming. In fact, templates in C++ are Turing-complete, making deciding whether a program will compile undecidable.

#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()
{
    std::cout << "10! = " << Fac<10>::result << "\n";
    return 0;
}

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.

Works with: C++11

Alternative version, using constexpr in C++11:

#include <stdio.h>

constexpr int factorial(int n) {
    return n ? (n * factorial(n - 1)) : 1;
}

constexpr int f10 = factorial(10);

int main() {
    printf("%d\n", f10);
    return 0;
}

Output:

3628800

The asm produced by G++ 4.6.0 32 bit (-std=c++0x -S), shows the computation is done at compile-time:

_main:
	pushl	%ebp
	movl	%esp, %ebp
	andl	$-16, %esp
	subl	$16, %esp
	call	___main
	movl	$3628800, 4(%esp)
	movl	$LC0, (%esp)
	call	_printf
	movl	$0, %eax
	leave
	ret


C3

C3 has semantic macros that use a different syntax from the regular runtime syntax.

macro int factorial($n)
{
	$if ($n == 0):
		return 1;
	$else:
		return $n * factorial($n - 1);
	$endif;
}

extern fn void printf(char *fmt, ...);

fn void main()
{
	int x = factorial(10);
	printf("10! = %d\n", x);
}
Output:
10! = 3628800

Clojure

(defn fac [n] (apply * (range 1 (inc n))))
(defmacro ct-factorial [n] (fac n))

Common Lisp

Assuming a definition from Factorial function#Common Lisp, we first have to make a small adjustment so that the function is available at compile time. Common Lisp does not have a single image building and deployment model. For instance, Common Lisp implementations can support a "C like" model whereby a compiler is invoked as a separate process to handle individual files, which are then loaded to form an image (analogous to linking). A Lisp compiler will not make available to itself the functions in a source file which it happens to be compiling, unless told to do so:

(eval-when (:compile-toplevel :load-toplevel :execute)
  (defun factorial ...))

With that, here are ways to do compile-time evaluation:

(defmacro ct-factorial (n)
  (factorial n))

...

(print (ct-factorial 10))

The factorial function must be defined before any use of the ct-factorial macro is evaluated or compiled.

If the data resulting from the compile-time calculation is not necessarily a number or other self-evaluating object, as it is in the factorial case, then the macro must quote it to avoid it being interpreted as code (a form):

(defmacro ct-factorial (n)
  `(quote ,(factorial n)))

; or, equivalently,
(defmacro ct-factorial (n)
  `',(factorial n))

It is also possible to have a value computed at load time, when the code is loaded into the process, rather than at compile time; this is useful if the value to be computed contains objects that do not yet exist at compile time, or the value might vary due to properties which might be different while yet using the same compiled program (e.g. pathnames), but it is still constant for one execution of the program:

(print (load-time-value (factorial 10)))

Further it's also possible to have the value computed at read time using the read macro #. .

(print (#. (factorial 10)))

Lastly, Common Lisp has "compiler macros" which are user-defined handlers for function call optimization. A compiler macro is defined which has the same name as some user-defined function. When calls to that function are being compiled, they pass through the macro. The macro must analyze the arguments and rewrite the function call into something else, or return the original form.

(define-compiler-macro factorial (&whole form arg)
  (if (constantp arg)
    (factorial arg)
    form))

Test with CLISP (taking advantage of its ! function) showing how a factorial call with a constant argument of 10 ends up compiled to the constant 3268800, but a factorial call with the argument a is compiled to a variable access and function call:

[1]> (defun factorial (x) (! x))
FACTORIAL
[2]> (define-compiler-macro factorial (&whole form arg)
  (if (constantp arg)
    (factorial arg)
    form))
FACTORIAL
[3]> (defun test-constant () (factorial 10))
TEST-CONSTANT
[4]> (disassemble 'test-constant)

Disassembly of function TEST-CONSTANT
(CONST 0) = 3628800
[ .. snip ... ]
0     (CONST 0)                           ; 3628800
1     (SKIP&RET 1)
NIL
[5]> (defun test-nonconstant () (factorial a))
TEST-NONCONSTANT
[6]> (disassemble 'test-nonconstant)
WARNING in TEST-NONCONSTANT :
A is neither declared nor bound,
it will be treated as if it were declared SPECIAL.

Disassembly of function TEST-NONCONSTANT
(CONST 0) = A
(CONST 1) = FACTORIAL
[ .. snip ... ]
reads special variable: A
3 byte-code instructions:
0     (GETVALUE&PUSH 0)                   ; A
2     (CALL1 1)                           ; FACTORIAL
4     (SKIP&RET 1)
NIL

D

The D compiler is able to run many functions at compile-time Compile Time Function Execution (CTFE):

long fact(in long x) pure nothrow @nogc {
    long result = 1;
    foreach (immutable i; 2 .. x + 1)
        result *= i;
    return result;
}

void main() {
    // enum means "compile-time constant", it forces CTFE.
    enum fact10 = fact(10);

    import core.stdc.stdio;

    printf("%ld\n", fact10);
}

The 32-bit asm generated by DMD shows the computation is done at compile-time:

__Dmain
    push EAX
    mov  EAX,offset FLAT:_DATA
    push 0
    push 0375F00h
    push EAX
    call near ptr _printf
    add  ESP,0Ch
    xor  EAX,EAX
    pop  ECX
    ret

Delphi

See Pascal

DWScript

In DWScript, constant expressions and referentially-transparent built-in functions, such as Factorial, are evaluated at compile time.

const fact10 = Factorial(10);

EchoLisp

define-constant may be used to compute data, which in turn may be used in other define-constant, or in the final code.

(define-constant DIX! (factorial 10))
(define-constant DIX!+1 (1+ DIX!))

(writeln DIX!+1)
3628801

EDSAC order code

Under David Wheeler's Initial Orders 2, the effect of compile-time calculation could be achieved on EDSAC by the use of "interludes" in the loading process. Code for an interlude was loaded into store, then loading was paused while the interlude was executed. When finished, the interlude passed control back to initial orders, and normal loading was resumed. Code that was used only by the interlude could then be overwritten. In this way once-only code was not left taking up storage space, which was in short supply on EDSAC.

Interludes could be used for calculation or for other purposes. E.g. the library subroutine M3 ran as an interlude; it printed a header on the teleprinter, and then M3 and the header text were overwritten.

Code for an interlude should not change locations in the initial orders. Also, if the multiplier register is used, its original value should be restored before exit from the interlude. The interlude in the demo program below is based on a shorter example in Wilkes, Wheeler & Gill, 1951 edn, p. 112.

[Demo of calculating a constant in an interlude at load time.
 EDSAC program, Initial Orders 2.]

        [Arrange the storage]
          T46K P56F     [N parameter: library subroutine P7 to print integer]
          T47K P100F    [M parameter: main routine]

          E25K TM GK    [M parameter, main routine]
          T#Z PF        [clear 35-bit value at relative locations
                         0 & 1, including the middle ("sandwich") bit]
          T2#Z PF       [same for 2 & 3]
          T4#Z PF       [same for 4 & 5]
          TZ            [resume normal loading at relative location 0]
        [Storage for interlude, must be at even address]
    [0]   PD PF         [35-bit factorial, initially integer 1]
    [2]   PD PF         [35-bit factor 1..10, initially integer 1]
    [4]   PF K4096F     [to save multiplier register (MR), initially floating point -1]
    [6]   PD            [17-bit integer 1]
    [7]   P5F           [17-bit integer 10 (or number whose factorial is required)]
    [8]   PF            [dump for clearing acc]
        [Executable code for interlude; here with acc = 0]
    [9]   N4#@          [acc := MR, by subtracting (-1 * MR)]
          T4#@          [save MR over interlude]
   [11]   T8@           [start of loop: clear acc]
          A2@           [acc := factor]
          A6@           [add 1]
          T2@           [update factor, clear acc]
          H2#@          [MR := factor, extended to 35 bits]
          V#@           [times 35-bit product, result in acc]
          L1024F L1024F L256F [integer scaling: shift 34 left]
          T#@           [update product]
          A2@           [acc := factor just used]
          S7@           [is it 10 yet?]
          G11@          [if not, loop back]
          H4#@          [restore MR before exit from interlude]
          E25F          [pass control back to initial orders]
[At this point the interlude has been loaded but not executed.
 The next control combination starts execution.]
          E9Z           [pass control to relative location 9 above]
          PF            [value in accumulator when control is passed: here = 0]
[After the interlude, loading resumes here.]
          T2Z           [resume normal loading at relative location 2,
                         overwriting the above interlude except the factorial]
        [Teleprinter characters]
    [2]   #F            [set figures mode]
    [3]   @F            [carriage return]
    [4]   &F            [line feed]
        [Enter here with acc = 0]
    [5]   O2@           [set teleprinter to figures]
          A#@           [acc := factorial, as calculated in the interlude]
          TD            [pass to print subroutine]
    [8]   A8@ GN        [call print subroutine]
          O3@ O4@       [print CR, LF]
          O2@           [dummy character to flush teleprinter buffer]
          ZF            [stop]

          E25K TN       [N parameter]
[Library subroutine P7, prints 35-bit strictly positive integer in 0D.]
[10 characters, right justified, padded left with spaces.]
[Even address; 35 storage locations; working position 4D.]
  GKA3FT26@H28#@NDYFLDT4DS27@TFH8@S8@T1FV4DAFG31@SFLDUFOFFFSF
  L4FT4DA1FA27@G11@XFT28#ZPFT27ZP1024FP610D@524D!FO30@SFL8FE22@

          E25K TM GK    [M parameter again]
          E5Z           [define entry point]
          PF            [acc = 0 on entry]
Output:
   3628800

Erlang

This is a placeholder since to do something more complex than text substitution macros Erlang offers parse transformations. This is a quote from their documentation: "Programmers are strongly advised not to engage in parse transformations". Somebody can do this task, but not I.

Factor

Technically, this calculation happens at parse-time, before any compilation takes place. Calculating factorial at compile-time is not useful in Factor.

: factorial ( n -- n! ) [1,b] product ;

CONSTANT: 10-factorial $[ 10 factorial ]

Forth

During a word definition, you can drop out of the compilation state with [ and go back in with ]. (This is where the naming conventions for [CHAR] and ['] come from.) There are several flavors of LITERAL for compiling the result into the word.

: fac ( n -- n! ) 1 swap 1+ 2 max 2 ?do i * loop ;

: main  ." 10! = " [ 10 fac ] literal . ;

see main 
: main  
  .\" 10! = " 3628800 . ; ok

Outside of a word definition, it's fuzzy. If the following code is itself followed by a test and output, and is run in a script, then the construction of the bignum array (and the perhaps native-code compilation of more) happens at runtime. If the following code is followed by a command that creates an executable, the array will not be rebuilt on each run.

: more  ( "digits" -- )  \ store "1234" as 1 c, 2 c, 3 c, 4 c,
  parse-word bounds ?do
    i c@ [char] 0 - c,
  loop ;

create bignum
more 73167176531330624919225119674426574742355349194934
more 96983520312774506326239578318016984801869478851843
...

Fortran

In Fortran, parameters can be defined where the value is computed at compile time:

 program test

   implicit none
   integer,parameter :: t = 10*9*8*7*6*5*4*3*2  !computed at compile time

   write(*,*) t  !write the value the console.

 end program test

FreeBASIC

' FB 1.05.0 Win64

' Calculations can be done in a Const declaration at compile time
' provided only literals or other constant expressions are used
 
Const factorial As Integer = 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10
Print factorial ' 3628800
Sleep

Go

Constant expressions are evaluated at compile time. A constant expression though, is pretty simple and can't have much more than literals, operators, and a special thing called iota. There is no way to loop in a constant expression and so the expanded expression below is about the simplest way of completing this task.

package main

import "fmt"

func main() {
    fmt.Println(2*3*4*5*6*7*8*9*10)
}

Haskell

With Template Haskell, it is quite easy to do compile time embedding. The functions used at compile-time need to be already compiled. Therefore, you generally need two modules.

module Factorial where
import Language.Haskell.TH.Syntax

fact n = product [1..n]

factQ :: Integer -> Q Exp
factQ = lift . fact
{-# LANGUAGE TemplateHaskell #-}
import Factorial

main = print $(factQ 10)

Note: Doing $([|fact 10|]) is the same than doing fact 10. [|something|] returns the abstract syntax tree of something. Thus [|fact 10|] returns the AST of the call to the fact function with 10 as argument. $(something) waits for an AST from a call to something.

J

J is an interpreter, and not a compiler, so could be said to not have any "compile time". Nevertheless, J tacit programs are stored using an internal representation -- the program is parsed once, well before it is used.

Thus, a program which prints 10 factorial:

pf10=: smoutput bind (!10)

When the definition of pf10 is examined, it contains the value 3628800. J has several ways of representing tacit programs. Here all five of them are presented for this program (the last two happen to look identical for this trivial case):

   9!:3]1 2 4 5 6

   pf10
┌───────────────────────────────────────┐
│┌─┬───────────────────────────────────┐│
││@│┌────────┬────────────────────────┐││
││ ││smoutput│┌─┬────────────────────┐│││
││ ││        ││"│┌────────────┬─────┐││││
││ ││        ││ ││┌─┬────────┐│┌─┬─┐│││││
││ ││        ││ │││03.6288e6│││0_││││││
││ ││        ││ ││└─┴────────┘│└─┴─┘│││││
││ ││        ││ │└────────────┴─────┘││││
││ ││        │└─┴────────────────────┘│││
││ │└────────┴────────────────────────┘││
│└─┴───────────────────────────────────┘│
└───────────────────────────────────────┘
┌────────┬─┬──────────────┐
smoutput@│┌────────┬─┬─┐│
         ││3.6288e6"_││
         │└────────┴─┴─┘│
└────────┴─┴──────────────┘
      ┌─ smoutput          
── @ ─┤          ┌─ 3628800
      └─ " ──────┴─ _      
smoutput@(3628800"_)
smoutput@(3628800"_)

Finally, when this program is run, it displays this number:

   pf10 ''
3628800

Note: Currently, the mediawiki implementation is corrupting the above display due to a cascading sequence of bad design decisions and mis-interpreted specifications on the part of someone "contributing" to that implementation. To work around this issue, and see the original display, you can currently use either the "Edit" or "View Source" option, depending on whether you are logged in to rosettacode with an account that has edit rights here. (Please don't actually save changes though.) If you are using View Source, you might want to do that in a new tab (so you also stay here with this view) and use your browser's search capability to quickly scroll to this location in the source view.

Java

The Java compiler is able to calculate expressions that contain constant variables
and certain operators during code compilation.
 
As defined in the Java language specification,
the following operators and expressions may be used for constant expressions:

Unary operators: +, -, ~, !
Multiplicative operators: *, /, %
Additive operators: +, –
Shift operators: <<, >>,  >>>
Relational operators: <, <=, >, >=
Equality operators: ==, !=
Bitwise and logical operators: &, ^, |
Conditional-and and the conditional-or operator: &&, ||
Ternary conditional operator: ?:
Parenthesized expressions whose contained expression is a constant expression
Simple names that refer to constant variables
public final class CompileTimeCalculation {

	public static void main(String[] aArgs) {
		System.out.println(tenFactorial);
	}
	
	private static int tenFactorial = 10 * 9 * 8 * 7 * 6 * 5 * 4 * 3 * 2 * 1;

}
Output:
3628800

Julia

Julia includes a powerful macro feature that can perform arbitrary code transformations at compile-time (or technically at parse-time), and can also execute arbitrary Julia code. For example, the following macro computes the factorial of n (a literal constant) and returns the value (e.g. to inline it in the resulting source code)

macro fact(n)
  factorial(n)
end

If we now use this in a function, e.g.

foo() = @fact 10

then the value of 10! = 3628800 is computed at parse-time and is inlined in the compiled function foo, as can be verified by inspecting the assembly code via the built-in function code_native(foo, ()).

Kotlin

Compile time calculations are possible in Kotlin using the 'const' modifier provided one sticks to literals or other constants when specifying the calculation to be performed:

// version 1.0.6
const val TEN_FACTORIAL = 10 * 9 * 8 * 7 * 6 * 5 * 4 * 3 * 2 

fun main(args: Array<String>) {
    println("10! = $TEN_FACTORIAL")
}
Output:
10! = 3628800

Lingo

As an interpreted language with the interpreter always being present, Lingo has no clear separation of compile-time and runtime. Whenever you change the code of a script at runtime, it's immediately (re)compiled to bytecode (in memory). You can also create new scripts at runtime:

-- create new (movie) script at runtime
m = new(#script)

-- the following line triggers compilation to bytecode
m.scriptText = "on fac10"&RETURN&"return "&(10*9*8*7*6*5*4*3*2)&RETURN&"end"

put fac10()
-- 3628800

Lua

Lua's compiler will attempt to fold constant expressions, which appears to be enough to satisfy this specific task's requirements:

local factorial = 10*9*8*7*6*5*4*3*2*1
print(factorial)
Output:
3628800

Proof via disassembly (Lua 5.3 used - the lookup of global "print" may vary a bit among 5.x versions, but not significant):

> luac -l compiletime.lua

main <compiletime.lua:0,0> (5 instructions at 0000000000ac8a40)
0+ params, 3 slots, 1 upvalue, 1 local, 2 constants, 0 functions
        1       [1]     LOADK           0 -1    ; 3628800
        2       [2]     GETTABUP        1 0 -2  ; _ENV "print"
        3       [2]     MOVE            2 0
        4       [2]     CALL            1 2 1
        5       [2]     RETURN          0 1

m4

m4 expands macros at run time, not compile time. If m4 is a front end to some other langugage, then m4's run time is part of other language's compile time.

This example uses m4 as a front end to AWK. m4 calculates factorial of 10, where AWK program calls macro.

define(`factorial',
`ifelse($1, 0, 1, `eval($1 * factorial(eval($1 - 1)))')')dnl
dnl
BEGIN {
	print "10! is factorial(10)"
}

One runs m4 program.m4 > program.awk to make this valid AWK program.

BEGIN {
	print "10! is 3628800"
}

Mathematica / Wolfram Language

Mathematica is not a compiled language, you can construct compiled functions in Mathematica by the build-in function "Compile". Constants are calculated at "compile-time".

f = Compile[{}, 10!]
Output:
CompiledFunction[{},3628800,-CompiledCode-]
f[]
Output:
3628800

MIPS Assembly

While most assemblers support compile-time expressions, factorial is typically not one of them. However, you can multiply out the factorial manually. It's not feasible for larger factorials but it's better than nothing.

li t0,10*9*8*7*6*5*4*3*2 ;= 10! = 0x375F00
jal monitor ;display all registers to the screen
nop
Output:
t0:00375F00

Nim

Nim can evaluate procedures at compile-time, this can be forced by calling a procedure with a const keyword like so:

proc fact(x: int): int =
  result = 1
  for i in 2..x:
    result = result * i

const fact10 = fact(10)
echo(fact10)

We can see that this is evaluated at compile-time by looking at the generated C code:

...
STRING_LITERAL(TMP122, "3628800", 7);
...

The Nim compiler can also be told to try to evaluate procedures at compile-time even for variables by using the --implicitStatic:on command line switch. The Nim compiler performs a side effect analysis to make sure that the procedure is side effect free, if it is not; a compile-time error is raised.

Oberon-2

Works with oo2c Version 2

MODULE CompileTime;
IMPORT 
  Out;
CONST
    tenfac = 10*9*8*7*6*5*4*3*2;
BEGIN
  Out.String("10! =");Out.LongInt(tenfac,0);Out.Ln
END CompileTime.

Objeck

Objeck will fold constants at compiler time as long as the -s2 or -s3 compiler switches are enabled.

bundle Default {
  class CompileTime {
    function : Main(args : String[]) ~ Nil {
      (10*9*8*7*6*5*4*3*2*1)->PrintLine();
    }
  }
}

OCaml

OCaml does not calculate operations that involve functions calls, as for example factorial 10, but OCaml does calculate simple mathematical operations at compile-time, for example in the code below (24 * 60 * 60) will be replaced by its result 86400.

let days_to_seconds n =
  let conv = 24 * 60 * 60 in
  (n * conv)
;;

It is easy to verify this using the argument -S to keep the intermediate assembly file:

ocamlopt -S sec.ml 
grep 86400 sec.s
        imull   $86400, %eax

If you wish to verify this property in your own projects, you have to know that integer values most often have their OCaml internal representation in the assembly, which for an integer x its OCaml internal representation will be (((x) << 1) + 1). So for example if we modify the previous code for:

let conv = 24 * 60 * 60

let days_to_seconds n =
  (n * conv)
;;
# (24 * 60 * 60) lsl 1 + 1 ;;
- : int = 172801
grep 172801 sec.s
        movl    $172801, camlSec



However, with the introduction of Flambda (an alternative intermediate language, inliner, and optimiser), OCaml compilers which equip this backend have a limited ability to reduce pure and annotated function calls to constants:

let fact10 =
  let rec factorial n =
   if n = 1 then n else n * factorial (n-1)
  in
  (factorial[@unrolled 10]) 10

(* The unrolled annotation is what allows flambda to keep reducing the call
 * Beware that the number of unrollings must be greater than or equal to the
 * number of iterations (recursive calls) for this to compile down to a constant. *)

The assembler output (cleaned up and demangled a little) shows exactly what's expected, stored as data

 Example:
       .quad   7257601
 Example.entry:
       movl    $1, %eax
       ret

And converting the tagged int to regular int we get

 # 7257601 lsr 1 ;;
 - : int = 3628800

example.ml is compiled with ocaml.4.12.0+flambda (2021); the unrolling annotation is older than that, compilers as old as 4.03.0+flambda (2016) support it.

Oforth

Not easy to define "compile time" with Oforth : oforth interpreter read input and perform it. If that intput creates function or methods, it creates and compile them.

You can do any calculation you want before or after, create constants, ...

10 seq reduce(#*) Constant new: FACT10
: newFunction  FACT10 . ;

You can also calculate all factorials for 1 to 20 before defining fact method :

20 seq map(#[ seq reduce(#*) ]) Constant new: ALLFACTS
: fact(n)  n ifZero: [ 1 ] else: [ ALLFACTS at(n) ] ;

ALLFACTS println
Output:
[1, 2, 6, 24, 120, 720, 5040, 40320, 362880, 3628800, 39916800, 479001600, 6227020800, 871
78291200, 1307674368000, 20922789888000, 355687428096000, 6402373705728000, 12164510040883
2000, 2432902008176640000]

OxygenBasic

To demonstrate compiler timing, A custom compiler is created here with the system performance counter to measure lapsed time. The source code is embedded for brevity.

To dimension a static array, the macro Pling10 is resolved at compile time. The overall compile time (ready to execute) was around 23 milliseconds.

'LIBRARY CALLS
'=============

extern lib "../../oxygen.dll"

declare o2_basic (string src)
declare o2_exec  (optional sys p) as sys
declare o2_errno () as sys
declare o2_error () as string

extern lib "kernel32.dll"

declare QueryPerformanceFrequency(quad*freq)
declare QueryPerformanceCounter(quad*count)

end extern

'EMBEDDED SOURCE CODE
'====================

src=quote

===Source===

def  Pling10 2*3*4*5*6*7*8*9*10

byte a[pling10] 'Pling10 is resolved to a number here at compile time

print pling10

===Source===


'TIMER
'=====

quad ts,tc,freq
QueryPerformanceFrequency freq
QueryPerformanceCounter ts

'COMPILE/EXECUTE
'===============

o2_basic src

if o2_errno then
  print o2_error
else
  QueryPerformanceCounter tc
  print "Compile time: " str((tc-ts)*1000/freq, 1) " MilliSeconds"
  o2_exec 'Run the program
end if

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

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.

Pascal

All the variants of pascal have always been able to calculate the values of constants at compile time as long as the values can be resolved.

program in out;

const

X = 10*9*8*7*6*5*4*3*2*1 ;

begin

writeln(x);

end;

Perl

There are few limits on code you can put in BEGIN blocks, which are executed at compile-time. Unfortunately, you can't in general save the compiled form of a program to run later. Instead, perl recompiles your program every time you run it.

my $tenfactorial;
print "$tenfactorial\n";

BEGIN
   {$tenfactorial = 1;
    $tenfactorial *= $_ foreach 1 .. 10;}

Note however that all constant folding is done at compile time, so this actually does the factorial at compile time.

my $tenfactorial = 10 * 9 * 8 * 7 * 6 * 5 * 4 * 3 * 2;

Phix

The Phix compiler uses constant folding/propagation, so running p -d on the following snippet

integer a,b
a = 10*9*8*7*6*5*4*3*2*1
b = factorial(10)
?{a,b}

produces a listing file containing

;     1 integer a,b
;     2 a = 10*9*8*7*6*5*4*3*2*1
    mov [#0040278C] (a), dword 3628800    ;#0042904E: 307005 8C274000 005F3700   uv 00 00  1  15      
;     3 b = factorial(10)
    mov ecx,5                             ;#00429058: 271 05000000               vu 02 00  1  15      
    mov edx,85                            ;#0042905D: 272 55000000               uv 04 00  1  16      
    call :%opFrame (factorial)            ;#00429062: 350 0BE80000               v  00 00  1  16      
    ...
Output:
{3628800,3628800}

PicoLisp

The PicoLisp "compiler" is the so-called "reader", which converts the human-readable source code into nested internal pointer structures. When it runs, arbitrary expressions can be executed with the backqoute and tilde operators (read macros).

(de fact (N)
   (apply * (range 1 N)) )

(de foo ()
   (prinl "The value of fact(10) is " `(fact 10)) )

Output:

: (pp 'foo)  # Pretty-print the function
(de foo NIL
   (prinl "The value of fact(10) is " 3628800) )
-> foo

: (foo)  # Execute it
The value of fact(10) is 3628800
-> 3628800

PL/I

/* Factorials using the pre-processor. */
test: procedure options (main);



%factorial: procedure (N) returns (fixed);
   declare N fixed;
   declare (i, k) fixed;

   k = 1;
   do i = 2 to N;
      k = k*i;
   end;
   return (k);

%end factorial;

%activate factorial;

   declare (x, y) fixed decimal;
   x = factorial (4);
   put ('factorial 4  is ', x);
   y = factorial (6);
   put skip list ('factorial 6 is ', y);

end test;

Output from the pre-processor:

/* Factorials using the pre-processor. */
test: procedure options (main);
   declare (x, y) fixed decimal;
   x =       24;
   put ('factorial 4  is ', x);
   y =      720;
   put skip list ('factorial 6 is ', y);
end test;

Execution results:

factorial 4  is               24 
factorial 6 is               720

PowerShell

function fact([BigInt]$n){
    if($n -ge ([BigInt]::Zero)) {
        $fact = [BigInt]::One
        ([BigInt]::One)..$n | foreach{
            $fact = [BigInt]::Multiply($fact, $_)
        }
        $fact
 
    } else {
        Write-Error "$n is lower than 0"
    }
}
"$((Measure-Command {$fact = fact 10}).TotalSeconds) Seconds"
$fact

Output:

0.0030411 Seconds
3628800

Prolog

For this, and many other complex calculations, goal_expansion/2 can be used.

goal_expansion/2 will change the goal in the code at compile time to be something else, in the case the constant number.

% Taken from RosettaCode Factorial page for Prolog
fact(X, 1) :- X<2.
fact(X, F) :- Y is X-1, fact(Y,Z), F is Z*X.
	
goal_expansion((X = factorial_of(N)), (X = F)) :- fact(N,F).
				
test :-	
	F = factorial_of(10),
	format('!10 = ~p~n', F).
Output:
?- test.
!10 = 3628800
true.

?- listing(test).
test :-
        A=3628800,
        format('!10 = ~p~n', A).

PureBasic

PureBasic will do most calculation during compiling, e.g.

a=1*2*3*4*5*6*7*8*9*10

could on a x86 be complied to

MOV    dword [v_a],3628800

Quackery

To compute and print 10! during compilation:

[ 1 10 times [ i 1+ * ] echo ] now!

To compute 10! during compilation and print the result at runtime:

[ 1 10 times [ i 1+ * ] ] constant echo

Any Quackery code can be executed during compilation, but the programmer must bear in mind that the compiler uses the stack, so executed code should have no overall stack effect in the case of now!, or leave a single item on the stack to be compiled in the case of constant.

Racket

Racket, like most Lisp descendants, allows arbitrary code to be executed at compile-time.

#lang racket

;; Import the math library for compile-time
;; Note: included in Racket v5.3.2
(require (for-syntax math))

;; In versions older than v5.3.2, just define the function
;; for compile-time
;;
;; (begin-for-syntax
;;   (define (factorial n)
;;     (if (zero? n)
;;         1
;;         (factorial (- n 1)))))

;; define a macro that calls factorial at compile-time
(define-syntax (fact10 stx)
  #`#,(factorial 10))

;; use the macro defined above
(fact10)

Raku

(formerly Perl 6)

constant $tenfact = [*] 2..10; 
say $tenfact;

Like Perl 5, we also have a BEGIN block, but it also works to introduce a blockless statement, the value of which will be stored up to be used as an expression at run time:

 say BEGIN [*] 2..10;

REXX

Since REXX is an interpreted language   (as are other languages entered for this Rosetta Code task),   run time is compile time.

/*REXX program computes 10! (ten factorial) during REXX's equivalent of "compile─time". */

say '10! ='    !(10)
exit                                             /*stick a fork in it,  we're all done. */
/*──────────────────────────────────────────────────────────────────────────────────────*/
!: procedure;  !=1;            do j=2  to arg(1);    !=!*j;    end  /*j*/;        return !

output

10! = 3628800

Ring

a = 10*9*8*7*6*5*4*3*2*1
b = factorial(10)
see a + nl
see b + nl

func factorial nr if nr = 1 return 1 else return nr * factorial(nr-1) ok

Run BASIC

Works with: Just BASIC
Works with: Liberty BASIC
factorial = 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10
print "10! = "; factorial ' 3628800

Rust

The Rust compiler can automatically do optimizations in the code to calculate the factorial.

fn factorial(n: i64) -> i64 {
    let mut total = 1;
    for i in 1..n+1 {
        total *= i;
    }
    return total;
}

fn main() {
    println!("Factorial of 10 is {}.", factorial(10));
}

If we compile this with rustc factorial.rs -O --emit asm and inspect the outputted assembly, we can see movq $3628800, (%rsp). This means the result of 3628800 was calculated in compile-time rather than run-time.

Scala

Scala 3 supports proper compile time evaluation

transparent inline def factorial(inline n: Int): Int =
  inline n match
    case 0 => 1
    case _ => n * factorial(n - 1)

inline val factorial10/*: 3628800*/ = factorial(10)

Alternative version that works with Scala 2:

object Main extends {
  val tenFactorial = 10 * 9 * 8 * 7 * 6 * 5 * 4 * 3 * 2

  def tenFac = 10 * 9 * 8 * 7 * 6 * 5 * 4 * 3 * 2

  println(s"10! = $tenFactorial", tenFac)
}

As it can been seen in the always heavily optimized run-time code the calculations are already computed for the field constant and function method.

  public int tenFac();
    descriptor: ()I
    flags: (0x0001) ACC_PUBLIC
    Code:
      stack=1, locals=1, args_size=1
         0: ldc           #28                 // int 3628800
         2: ireturn
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0       3     0  this   L$line2/$read$$iw$$iw$Main$;
      LineNumberTable:
        line 14: 0

  public $line2.$read$$iw$$iw$Main$();
    descriptor: ()V
    flags: (0x0001) ACC_PUBLIC
    Code:
      stack=6, locals=1, args_size=1
         0: aload_0
         1: invokespecial #29                 // Method java/lang/Object."<init>":()V
         4: aload_0
         5: putstatic     #31                 // Field MODULE$:L$line2/$read$$iw$$iw$Main$;
         8: aload_0
         9: ldc           #28                 // int 3628800
        11: putfield      #25                 // Field tenFactorial:I
        14: getstatic     #36                 // Field scala/Predef$.MODULE$:Lscala/Predef$;
        17: new           #38                 // class scala/Tuple2
        20: dup
        21: new           #40                 // class java/lang/StringBuilder

Seed7

Seed7 allows predefined and user defined initialisation expressions. The ! operator is predefined, so no user defined function is necessary.

$ include "seed7_05.s7i";

const proc: main is func
  local
    const integer: factorial is !10;
  begin
    writeln(factorial);
  end func;

Sidef

The compile-time evaluation is limited at a constant expression, which cannot refer at any other user-defined data, such as variables or functions.

define n = (10!);
say n;

or:

define n = (func(n){ n > 0 ? __FUNC__(n-1)*n : 1 }(10));
say n;

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
proc makeFacExpr n {
    set exp 1
    for {set i 2} {$i <= $n} {incr i} {
        append exp " * $i"
    }
    return "expr \{$exp\}"
}
eval [makeFacExpr 10]

How to show that the results were compiled? Like this:

% 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

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).

TXR

In TXR Lisp, the standard macro-time macro evaluates an expression at macro-expansion time, and replaces it by its result, which is then treated as a literal (because the macro inserts `quote` around it, if required).

Such a macro is easy to implement in Common Lisp and similar dialects. The documentation provides a reference implementation which is easily ported.

Example: provide a function buildinfo in the compiled program which returns the build machine name, and time and date of the compilation. A global variable which provides this value could similarly be defined:

(defun buildinfo ()
  (macro-time
    `Built by @{(uname).nodename} on @(time-string-local (time) "%c")`))

If we compile and disassemble the function, we see it just contains a canned literal:

3> (compile 'buildinfo)
#<vm fun: 0 param>
4> (disassemble *3)
data:
    0: buildinfo
    1: "Built by sun-go on Sat Oct  1 20:01:25 2022"
syms:
code:
    0: 8C000005 close t2 0 2 5 0 0 nil
    1: 00000002
    2: 00000000
    3: 00000002
    4: 10000401 end d1
    5: 10000002 end t2
instruction count:
    3
entry point:
    4
#<vm fun: 0 param>

Ursala

Any user-defined or library function callable at run time can also be called at compile time and evaluated with no unusual ceremony involved.

#import nat

x = factorial 10

#executable&

comcal = ! (%nP x)--<''>

some notes:

  • x is declared as a constant equal to ten factorial using the factorial function imported from the nat library.
  • %nP is a function derived from the type expression %n, for natural numbers, which takes a natural number as an argument and maps it to a list of character strings suitable for printing
  • The #executable& directive causes the function following to be compiled as a free standing executable transforming standard input to standard output thereby.
  • The -- operator represents list concatenation.
  • The list containing the empty string is concatenated with (%nP x) so that the output will be terminated with a line break.
  • The ! operator makes a constant function of its operand, so that the compiled program will ignore its input and print x regardless.

Here is a bash session showing compilation of the above code into a simple command line filter, and running it as the next command.

$ fun comcal.fun
fun: writing `comcal'
$ comcal < /dev/null
3628800

Similarly to the Ocaml and Tcl solutions, we can confirm that the calculation has been performed at compile time by inspecting the object code.

$ fun comcal --decompile
main = constant <'3628800',''>

Visual Basic .NET

Compiler: Roslyn Visual Basic, language version 15.8

The Roslyn compiler performs constant folding at compile-time and emits IL that contains the result.

Module Program
    Const FACTORIAL_10 = 10 * 9 * 8 * 7 * 6 * 5 * 4 * 3 * 2 * 1

    Sub Main()
        Console.WriteLine(FACTORIAL_10)
    End Sub
End Module
Emitted IL (disassembled with ILSpy):
.class private auto ansi sealed Program
	extends [System.Runtime]System.Object
{
	.custom instance void Microsoft.VisualBasic.CompilerServices.StandardModuleAttribute::.ctor() = (
		01 00 00 00
	)
	// Fields
	.field private static literal int32 FACTORIAL_10 = int32(3628800)

	// Methods
	.method public static 
		void Main () cil managed 
	{
		.custom instance void [System.Runtime]System.STAThreadAttribute::.ctor() = (
			01 00 00 00
		)
		// Method begins at RVA 0x2060
		// Code size 11 (0xb)
		.maxstack 8
		.entrypoint

		IL_0000: ldc.i4 3628800
		IL_0005: call void [System.Console]System.Console::WriteLine(int32)
		IL_000a: ret
	} // end of method Program::Main

} // end of class Program

Constant expressions that appear outside of constant declarations are also folded, so

Module Program
    Sub Main()
        Console.WriteLine(10 * 9 * 8 * 7 * 6 * 5 * 4 * 3 * 2 * 1)
    End Sub
End Module

and

Module Program
    Sub Main()
        Dim factorial As Integer
        factorial = 10 * 9 * 8 * 7 * 6 * 5 * 4 * 3 * 2 * 1
        Console.WriteLine(factorial)
    End Sub
End Module

produce the same IL, albeit without the constant field that other assemblies can reference.

Emitted IL (disassembled with ILSpy):
.class private auto ansi sealed Program
	extends [System.Runtime]System.Object
{
	.custom instance void Microsoft.VisualBasic.CompilerServices.StandardModuleAttribute::.ctor() = (
		01 00 00 00
	)
	// Methods
	.method public static 
		void Main () cil managed 
	{
		.custom instance void [System.Runtime]System.STAThreadAttribute::.ctor() = (
			01 00 00 00
		)
		// Method begins at RVA 0x2060
		// Code size 11 (0xb)
		.maxstack 8
		.entrypoint

		IL_0000: ldc.i4 3628800
		IL_0005: call void [System.Console]System.Console::WriteLine(int32)
		IL_000a: ret
	} // end of method Program::Main

} // end of class Program
Output:
3628800

Wren

Wren is a hybrid compiler/interpreter in the sense that the source code is first compiled to an intermediate bytecode which is then interpreted by the virtual machine.

Also Wren has no notion of constants - at compile time or otherwise - and is thoroughly object-oriented. Even literals such as 123 and true are technically instances of the immutable built-in classes Num and Bool.

There is little public information on the workings of the bytecode compiler other than that it is single pass and stack based. However, I gather that it does no compile time calculations at all and the factorial calculation in the program below is therefore done at runtime.

Not that it makes much difference in practice as the compiler which is written in C is so quick (at least with scripts of moderate length and on modern hardware) that the compile and runtime stages are indistinguishable to the user.

var factorial10 = 10 * 9 * 8 * 7 * 6 * 5 * 4 * 3 * 2

System.print(factorial10)
Output:
3628800

XLISP

Macros can be used to evaluate expressions at compile time:

(defmacro f10-at-compile-time () (* 2 3 4 5 6 7 8 9 10))

If the expression is quoted, however, it is not evaluated—it is inserted 'as is', and will be evaluated at run time:

(defmacro f10-at-run-time () '(* 2 3 4 5 6 7 8 9 10))

To show what is going on, first start a REPL and define little functions that just invoke each macro:

[1] (defun test-f10-ct () (f10-at-compile-time))

TEST-F10-CT
[2] (defun test-f10-rt () (f10-at-run-time))

TEST-F10-RT

Then use DECOMPILE to examine the bytecode generated for each function. First, the one where the calculation was performed at compile time:

[3] (decompile test-f10-ct)

TEST-F10-CT:0000 12 00       ARGSEQ 00 ; ()
TEST-F10-CT:0002 04 03       LIT 03 ; 3628800
TEST-F10-CT:0004 0d          RETURN
()

Here, 10! is included as the literal number 3628800. By contrast, if we decompile the function that uses the F10-AT-RUN-TIME macro:

[4] (decompile test-f10-rt)

TEST-F10-RT:0000 12 00       ARGSEQ 00 ; ()
TEST-F10-RT:0002 04 03       LIT 03 ; 10
TEST-F10-RT:0004 10          PUSH
TEST-F10-RT:0005 04 04       LIT 04 ; 9
TEST-F10-RT:0007 10          PUSH
TEST-F10-RT:0008 04 05       LIT 05 ; 8
TEST-F10-RT:000a 10          PUSH
TEST-F10-RT:000b 04 06       LIT 06 ; 7
TEST-F10-RT:000d 10          PUSH
TEST-F10-RT:000e 04 07       LIT 07 ; 6
TEST-F10-RT:0010 10          PUSH
TEST-F10-RT:0011 04 08       LIT 08 ; 5
TEST-F10-RT:0013 10          PUSH
TEST-F10-RT:0014 04 09       LIT 09 ; 4
TEST-F10-RT:0016 10          PUSH
TEST-F10-RT:0017 04 0a       LIT 0a ; 3
TEST-F10-RT:0019 10          PUSH
TEST-F10-RT:001a 04 0b       LIT 0b ; 2
TEST-F10-RT:001c 10          PUSH
TEST-F10-RT:001d 05 0c       GREF 0c ; *
TEST-F10-RT:001f 0c 09       TCALL 09
()

we see that it includes the instructions necessary to find the answer but not the answer itself.

XPL0

code IntOut=11;
IntOut(0, 10*9*8*7*6*5*4*3*2);

Generates this 80386 assembly code:

        XOR     EAX,EAX
        PUSH    EAX
        MOV     EAX,3628800
        CALL    INTR11
        RET

Yabasic

factorial = 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10
print "10! = ", factorial // 3628800

Z80 Assembly

Translation of: 8086 Assembly

Since 10! is bigger than 16 bits, I'll use 8! instead to demonstrate. Most assemblers only support the standard C operators for compile-time calculation, so we're going to need to multiply out the factorial manually.

ld hl,8*7*6*5*4*3*2 ;8! equals 40,320 or 0x9D80
call Monitor        ;unimplemented routine, displays the register contents to screen
Output:

0x9D80

zkl

zkl has two ways to do compile time calculations: a variant of C's macros and "parse time" calculations (since the compiler is written in zkl, the parser just recurses). File foo.zkl:

const { [1..10].reduce('*).println(" parse time") }

#fcn fact(N) { [1..N].reduce('*).println(" tokenize time"); ""}
   // paste output of fact into source
#tokenize fact(10)

println("compiled program running.");

Run the program: zkl foo:

Output:
3628800 tokenize time
3628800 parse time
compiled program running.

Tokenize time can paste text into the source, parse time can inject a limited set of objects into the parse tree (and is used for things like __DATE__, __FILE__ constants).

Zig

Zig provides arbitrary CTFE with limitations in IO, memoization and forbidding closures for compilation efficiency.

const std = @import("std");
fn factorial(n: u64) u64 {
    var total: u64 = 1;
    var i: u64 = 1;
    while (i < n + 1) : (i += 1) {
        total *= i;
    }
    return total;
}
pub fn main() void {
    @setEvalBranchQuota(1000); // minimum loop quota for backwards branches
    const res = comptime factorial(10); // arbitrary Compile Time Function Evaluation
    std.debug.print("res: {d}", .{res}); // output only at runtime
}

Output:

3628800