Dynamic functions

This module implements several meta-functions that create new functions dynamically by wrapping the existing ones.

The function parameter_to_function_prefix wraps a function f(x1 x2 …) into a new function ${x1}_f(x2 …), that is, fixes one argument to some predefined value so that the wrapped function could be called with one argument less.

The function trace_functions wraps a function f into a new function _trace_f that prints a trace message f(${ARGN}) into the log context with the same name f, and then calls the original function with unchanged arguments.

The function dynamic_call forwards given arguments to a given function without any changes.

The function eval emulates return values for functions and macros:

function(concat_function _param1 _param2)
    result_is("${_param1}_${_param2}")
endfunction()

set(_ind 2)
eval(EXPR "a = ${_ind} + 3")
message(STATUS "a = ${a}") # prints a = 5

eval("b = concat_function(cmake language)")
message(STATUS "b = ${b}") # prints b = cmake_language

When to use

With the help of trace_functions, it’s easy to single-out calls to a specific function without changing the source of that function. parameter_to_function_prefix is written specifically to wrap the GlobalMap module, but it could be useful in other contexts as well.

Functions

parameter_to_function_prefix
parameter_to_function_prefix(<function list>>)

For each given function fn, creates a counterpart ${_prefix}_${fn} that has all the parameters of the original function except the first one, and does nothing but calls fn with the arguments given to ${_prefix}_${fn}.

Note

Since the argument count changes, the logic that depends on ARGN, ARGC and similar values, may break. Be careful when wrapping a function that depends on exact argument count and order.

trace_functions
trace_functions(<function list>>)

For each given function fn, creates a counterpart _trace_fn that prints a trace message called fn(${ARGN}) into the log context fn and then calls the original function with the unchanged arguments. For example:

trace_functions(global_set)
log_level(global_set TRACE)
log_to_file(global_set global_set.log)
# will append 'global_set(a bcd)' to 'global_set.log'
# before calling 'global_set'
_trace_global_set(a bcd)
dynamic_call
dynamic_call(<function> <argument list>)

Calls the given function with the given arguments. For example:

log_level(dynamic_call TRACE)
log_to_file(dynamic_call dynamic_call.log)
dynamic_call(${function_name} ${ARGN})
# will append 'global_set(a bcd)' to 'global_set.log'
# before calling 'global_set'
_trace_global_set(a bcd)
eval
eval("<var> = <function>(<argument>...)")

Calls the given function with the given arguments and stores the result in the result variable var. The function function must call one of result_is, result_expr to publish the result:

function(function_with_result _param1 _param2)
   result_expr(${_param1} + ${_param2})
endfunction()

function(function_with_result_2 _param1 _param2)
   result_is("${_param1}_${_param2}")
endfunction()

macro(macro_with_result _param1 _param2)
    result_is("${_param1}_${_param2}")
endmacro()

function(eval_test)
   eval("a = function_with_result(3 4)")
   assert_same(${a} 7)
   eval("b = function_with_result_2(cmake language)")
   assert_same(${b} cmake_language)
   set(_ind 2)
   eval(EXPR "a = ${_ind} + 3")
   assert_same(${a} 5)
   eval("a = macro_with_result(1 2)")
   assert_same(${a} 1_2)
endfunction()