fbpx
Wikipedia

Compile-time function execution

In computing, compile-time function execution (or compile time function evaluation, or general constant expressions) is the ability of a compiler, that would normally compile a function to machine code and execute it at run time, to execute the function at compile time. This is possible if the arguments to the function are known at compile time, and the function does not make any reference to or attempt to modify any global state (i.e. it is a pure function).

If the value of only some of the arguments are known, the compiler may still be able to perform some level of compile-time function execution (partial evaluation), possibly producing more optimized code than if no arguments were known.

Examples edit

Lisp edit

The Lisp macro system is an early example of the use of compile-time evaluation of user-defined functions in the same language.

C++ edit

The Metacode extension to C++ (Vandevoorde 2003)[1] was an early experimental system to allow compile-time function evaluation (CTFE) and code injection as an improved syntax for C++ template metaprogramming.

In earlier versions of C++, template metaprogramming is often used to compute values at compile time, such as:

template <int N> struct Factorial {  enum { value = N * Factorial<N - 1>::value }; }; template <> struct Factorial<0> {  enum { value = 1 }; }; // Factorial<4>::value == 24 // Factorial<0>::value == 1 void Foo() {  int x = Factorial<0>::value; // == 1  int y = Factorial<4>::value; // == 24 } 

Using compile-time function evaluation, code used to compute the factorial would be similar to what one would write for run-time evaluation e.g. using C++11 constexpr.

#include <cstdio> 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; } 

In C++11, this technique is known as generalized constant expressions (constexpr).[2] C++14 relaxes the constraints on constexpr – allowing local declarations and use of conditionals and loops (the general restriction that all data required for the execution be available at compile-time remains).

Here's an example of compile time function evaluation in C++14:

// Iterative factorial at compile time. constexpr int Factorial(int n) {  int result = 1;  while (n > 1) {  result *= n--;  }  return result; } int main() {  constexpr int f4 = Factorial(4); // f4 == 24 } 

Immediate functions (C++) edit

In C++20, immediate functions were introduced, and compile-time function execution was made more accessible and flexible with relaxed constexpr restrictions.

// Iterative factorial at compile time. consteval int Factorial(int n) {  int result = 1;  while (n > 1) {  result *= n--;  }  return result; } int main() {  int f4 = Factorial(4); // f4 == 24 } 

Since function Factorial is marked consteval, it is guaranteed to invoke at compile-time without being forced in another manifestly constant-evaluated context. Hence, the usage of immediate functions offers wide uses in metaprogramming, and compile-time checking (used in C++20 text formatting library).

Here's an example of using immediate functions in compile-time function execution:

void you_see_this_error_because_assertion_fails() {} consteval void cassert(bool b) {  if (!b)  you_see_this_error_because_assertion_fails(); } consteval void test() {  int x = 10;  cassert(x == 10); // ok  x++;  cassert(x == 11); // ok  x--;  cassert(x == 12); // fails here } int main() { test(); } 

In this example, the compilation fails because the immediate function invoked function which is not usable in constant expressions. In other words, the compilation stops after failed assertion.

The typical compilation error message would display:

In function 'int main()':  in 'constexpr' expansion of 'test()'  in 'constexpr' expansion of 'cassert(x == 12)' error: call to non-'constexpr' function 'you_see_this_error_because_assertion_fails()'   you_see_this_error_because_assertion_fails();   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~  [ ... ] 

Here's another example of using immediate functions as constructors which enables compile-time argument checking:

#include <string_view> #include <iostream> void you_see_this_error_because_the_message_ends_with_exclamation_point() {} struct checked_message {  std::string_view msg;  consteval checked_message(const char* arg)  : msg(arg) {  if (msg.ends_with('!'))  you_see_this_error_because_the_message_ends_with_exclamation_point();  } }; void send_calm_message(checked_message arg) {  std::cout << arg.msg << '\n'; } int main() {  send_calm_message("Hello, world");  send_calm_message("Hello, world!"); } 

The compilation fails here with the message:

In function 'int main()':  in 'constexpr' expansion of 'checked_message(((const char*)"Hello, world!"))' error: call to non-'constexpr' function 'void you_see_this_error_because_the_message_ends_with_exclamation_point()'   you_see_this_error_because_the_message_ends_with_exclamation_point();   ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^~  [ ... ] 

D edit

Here's an example of compile time function evaluation in the D programming language:[3]

int factorial(int n) {  if (n == 0)  return 1;  return n * factorial(n - 1); } // computed at compile time enum y = factorial(0); // == 1 enum x = factorial(4); // == 24 

This example specifies a valid D function called "factorial" which would typically be evaluated at run time. The use of enum tells the compiler that the initializer for the variables must be computed at compile time. Note that the arguments to the function must be able to be resolved at compile time as well.[4]

CTFE can be used to populate data structures at compile-time in a simple way (D version 2):

int[] genFactorials(int n) {  auto result = new int[n];  result[0] = 1;  foreach (i; 1 .. n)  result[i] = result[i - 1] * i;  return result; } enum factorials = genFactorials(13); void main() {} // 'factorials' contains at compile-time: // [1, 1, 2, 6, 24, 120, 720, 5_040, 40_320, 362_880, 3_628_800, // 39_916_800, 479_001_600] 

CTFE can be used to generate strings which are then parsed and compiled as D code in D.

Zig edit

Here's an example of compile time function evaluation in the Zig programming language:[5]

pub fn factorial(n: usize) usize {  var result = 1;  for (1..(n + 1)) |i| {  result *= i;  }  return result; } pub fn main() void {  const x = comptime factorial(0); // == 0  const y = comptime factorial(4); // == 24 } 

This example specifies a valid Zig function called "factorial" which would typically be evaluated at run time. The use of comptime tells the compiler that the initializer for the variables must be computed at compile time. Note that the arguments to the function must be able to be resolved at compile time as well.

Zig also support Compile-Time Parameters.[6]

pub fn factorial(comptime n: usize) usize {  var result: usize = 1;  for (1..(n + 1)) |i| {  result *= i;  }  return result; } pub fn main() void {  const x = factorial(0); // == 0  const y = factorial(4); // == 24 } 

CTFE can be used to create generic data structures at compile-time:

fn List(comptime T: type) type {  return struct {  items: []T,  len: usize,  }; } // The generic List data structure can be instantiated by passing in a type: var buffer: [10]i32 = undefined; var list = List(i32){  .items = &buffer,  .len = 0, }; 

References edit

  1. ^ Daveed Vandevoorde, Edison Design Group (April 18, 2003). "Reflective Metaprogramming in C++" (PDF). Retrieved July 19, 2015.
  2. ^ Gabriel Dos Reis and Bjarne Stroustrup (March 2010). "General Constant Expressions for System Programming Languages. SAC-2010. The 25th ACM Symposium On Applied Computing" (PDF).
  3. ^ D 2.0 language specification: Functions
  4. ^ D 2.0 language specification: Attributes
  5. ^ Zig 0.11.0 Language Reference: Compile-Time Expressions
  6. ^ Zig 0.11.0 Language Reference: Compile-Time Parameters

External links edit

  • Rosettacode examples of compile-time function evaluation in various languages

compile, time, function, execution, computing, compile, time, function, execution, compile, time, function, evaluation, general, constant, expressions, ability, compiler, that, would, normally, compile, function, machine, code, execute, time, execute, function. In computing compile time function execution or compile time function evaluation or general constant expressions is the ability of a compiler that would normally compile a function to machine code and execute it at run time to execute the function at compile time This is possible if the arguments to the function are known at compile time and the function does not make any reference to or attempt to modify any global state i e it is a pure function If the value of only some of the arguments are known the compiler may still be able to perform some level of compile time function execution partial evaluation possibly producing more optimized code than if no arguments were known Contents 1 Examples 1 1 Lisp 1 2 C 1 3 Immediate functions C 1 4 D 1 5 Zig 2 References 3 External linksExamples editLisp edit The Lisp macro system is an early example of the use of compile time evaluation of user defined functions in the same language C edit The Metacode extension to C Vandevoorde 2003 1 was an early experimental system to allow compile time function evaluation CTFE and code injection as an improved syntax for C template metaprogramming In earlier versions of C template metaprogramming is often used to compute values at compile time such as template lt int N gt struct Factorial enum value N Factorial lt N 1 gt value template lt gt struct Factorial lt 0 gt enum value 1 Factorial lt 4 gt value 24 Factorial lt 0 gt value 1 void Foo int x Factorial lt 0 gt value 1 int y Factorial lt 4 gt value 24 Using compile time function evaluation code used to compute the factorial would be similar to what one would write for run time evaluation e g using C 11 constexpr include lt cstdio gt 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 In C 11 this technique is known as generalized constant expressions constexpr 2 C 14 relaxes the constraints on constexpr allowing local declarations and use of conditionals and loops the general restriction that all data required for the execution be available at compile time remains Here s an example of compile time function evaluation in C 14 Iterative factorial at compile time constexpr int Factorial int n int result 1 while n gt 1 result n return result int main constexpr int f4 Factorial 4 f4 24 Immediate functions C edit In C 20 immediate functions were introduced and compile time function execution was made more accessible and flexible with relaxed constexpr restrictions Iterative factorial at compile time consteval int Factorial int n int result 1 while n gt 1 result n return result int main int f4 Factorial 4 f4 24 Since function Factorial is marked consteval it is guaranteed to invoke at compile time without being forced in another manifestly constant evaluated context Hence the usage of immediate functions offers wide uses in metaprogramming and compile time checking used in C 20 text formatting library Here s an example of using immediate functions in compile time function execution void you see this error because assertion fails consteval void cassert bool b if b you see this error because assertion fails consteval void test int x 10 cassert x 10 ok x cassert x 11 ok x cassert x 12 fails here int main test In this example the compilation fails because the immediate function invoked function which is not usable in constant expressions In other words the compilation stops after failed assertion The typical compilation error message would display In function int main in constexpr expansion of test in constexpr expansion of cassert x 12 error call to non constexpr function you see this error because assertion fails you see this error because assertion fails Here s another example of using immediate functions as constructors which enables compile time argument checking include lt string view gt include lt iostream gt void you see this error because the message ends with exclamation point struct checked message std string view msg consteval checked message const char arg msg arg if msg ends with you see this error because the message ends with exclamation point void send calm message checked message arg std cout lt lt arg msg lt lt n int main send calm message Hello world send calm message Hello world The compilation fails here with the message In function int main in constexpr expansion of checked message const char Hello world error call to non constexpr function void you see this error because the message ends with exclamation point you see this error because the message ends with exclamation point D edit Here s an example of compile time function evaluation in the D programming language 3 int factorial int n if n 0 return 1 return n factorial n 1 computed at compile time enum y factorial 0 1 enum x factorial 4 24 This example specifies a valid D function called factorial which would typically be evaluated at run time The use of enum tells the compiler that the initializer for the variables must be computed at compile time Note that the arguments to the function must be able to be resolved at compile time as well 4 CTFE can be used to populate data structures at compile time in a simple way D version 2 int genFactorials int n auto result new int n result 0 1 foreach i 1 n result i result i 1 i return result enum factorials genFactorials 13 void main factorials contains at compile time 1 1 2 6 24 120 720 5 040 40 320 362 880 3 628 800 39 916 800 479 001 600 CTFE can be used to generate strings which are then parsed and compiled as D code in D Zig edit Here s an example of compile time function evaluation in the Zig programming language 5 pub fn factorial n usize usize var result 1 for 1 n 1 i result i return result pub fn main void const x comptime factorial 0 0 const y comptime factorial 4 24 This example specifies a valid Zig function called factorial which would typically be evaluated at run time The use of comptime tells the compiler that the initializer for the variables must be computed at compile time Note that the arguments to the function must be able to be resolved at compile time as well Zig also support Compile Time Parameters 6 pub fn factorial comptime n usize usize var result usize 1 for 1 n 1 i result i return result pub fn main void const x factorial 0 0 const y factorial 4 24 CTFE can be used to create generic data structures at compile time fn List comptime T type type return struct items T len usize The generic List data structure can be instantiated by passing in a type var buffer 10 i32 undefined var list List i32 items amp buffer len 0 References edit Daveed Vandevoorde Edison Design Group April 18 2003 Reflective Metaprogramming in C PDF Retrieved July 19 2015 Gabriel Dos Reis and Bjarne Stroustrup March 2010 General Constant Expressions for System Programming Languages SAC 2010 The 25th ACM Symposium On Applied Computing PDF D 2 0 language specification Functions D 2 0 language specification Attributes Zig 0 11 0 Language Reference Compile Time Expressions Zig 0 11 0 Language Reference Compile Time ParametersExternal links editRosettacode examples of compile time function evaluation in various languages Retrieved from https en wikipedia org w index php title Compile time function execution amp oldid 1215852650, wikipedia, wiki, book, books, library,

article

, read, download, free, free download, mp3, video, mp4, 3gp, jpg, jpeg, gif, png, picture, music, song, movie, book, game, games.